Spring框架的使用
第一章:Spring概述
1. Spring全家桶:
Spring、Spring MVC、Spring Boot、Spring Cloud
2. Spring:
出现在2002年左右,解决企业开发的难度,减轻对模块之间的管理,类和类之间的关系
Spring核心技术ioc,aop。能实现模块之间、类之间的解耦合
3. 依赖:
类A中使用类B的属性或者方法,叫做类A依赖类B
4. 特点
1)轻量
2)针对接口编程,解耦合
3)AOP编程的支持
4)方便集成各种优秀框架
5. 框架怎么学?
框架是一个软件,其他人写好的软件
1)知道框架能做什么,Mybatis——访问数据库,对表中的数据进行增删改查
2)框架的语法,框架要完成一个功能,需要一定步骤支持的
3)框架的内部实现,框架内部怎么做,原理是什么
4)通过学习,可以实现一个框架
第二章:IoC控制反转
1. IoC:
IoC(Inversion of Control):控制反转 是一个理论,概念,思想
描述的是:对象的创建,赋值,管理工作都交给代码之外的容器实现,也就是对象的创建是有其他外部资源完成
控制: 创建对象,对象的属性赋值,对象之间的关系管理
反转: 把原来开发人员管理,创建对象的权限转移给代码之外的容器实现。由容器 代替开发人员管理,创建对象
正转: 由开发人员在代码中,使用new构造方法创建对象(new对象这种行为叫做正转),开发人员主动的能够管理对象
容器: 是一个服务器软件,一个框架(Spring)
2. 为什么使用IoC ?
目的就是减少对代码的改动,也能实现不同的功能,实现解耦合
3. Java中创建对象的方式:
1)构造方法 new Student()
2)通过反射机制
3)序列化
4)克隆
5)IoC容器创建对象
6)动态代理
4. Spring实现步骤:
1.创建maven项目
2. 加入maven的依赖
spring依赖:
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
maven编译Java程序插件:
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
3.创建类(创建接口和实现类)
接口:
package com.bjpowernode.service;
public interface SomeService {
void doSome();
}
实现类:
package com.bjpowernode.impl;
import com.bjpowernode.service.SomeService;
public class SomeServiceImpl implements SomeService {
@Override
public void doSome() {
System.out.println("执行了SomeServiceImpl的doSome()方法");
}
}
传统的执行SomeServiceImpl的doSome()方法:
package com.bjpowernode;
import com.bjpowernode.impl.SomeServiceImpl;
import com.bjpowernode.service.SomeService;
import org.junit.Test;
public class MyTest {
@Test
public void test01(){
SomeService someService = new SomeServiceImpl();
someService.doSome();
}
}
4.创建Spring需要使用的配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="someService" class="com.bjpowernode.impl.SomeServiceImpl"/>
</beans>
1)声明bean,就是告诉spring要创建某个类的对象,一个bean标签声明一个对象。可以有多个bean标签
2)
id: 对象的自定义名称,唯一值/spring通过这个名称找到对象
相当于spring完成SomeService someservice = new SomeServiceIml;
class: 类的全限定名称(不能是接口,因为spring反射机制创建对象,必须使用类)
3)
spring是把创建好的对象放入到map中,spring框架有一个map存放对象的
springMap.put(id的值,对象);
例如:spring.put(someService,new SomeServiceImpl());
5.测试
测试调用doSome()方法:
public void test02(){
//1.指定spring配置文件的名称
String config = "beans.xml";
//2.创建表示spring容器的对象,ApplicationContext
//ApplicationContext就是表示spring容器,通过这个容器获取对象
//ClassPathXmlApplicationContext从类路径中加载spring的配置文件
//这里创建了someService对象,可以写个无参构造测试
ApplicationContext ac = new ClassPathXmlApplicationContext(config);
//从容器中获取某个对象,你要调用对象的方法
SomeService someService= (SomeService) ac.getBean("someService");
someService.doSome();
}
Spring默认创建对象的时间:在创建Spring容器时,会创建配置文件中的所有的对象,一个bean标签是一个对象
查看容器中定义对象的数量: int num = ac.getBeanDefinitionCount();
查看容器中每个定义对象的名称: String[] names = ac.getBeanDefinitionNames();
5. 给对象的属性赋值:
di: 依赖注入,表示创建对象,给属性赋值
di的实现方式有两种:
1.在spring文件中,使用标签和属性完成,叫做基于XML的di实现
2.使用spring中的注解,完成属性赋值,叫做基于注解的di实现
di的语法分类:
1.set注入(设值注入):spring调用类的set方法,在set方法可以实现属性的赋值
2.构造注入,spring调用类的有参数构造方法,创建对象,在构造方法中完成赋值
1.设值注入
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="student" class="com.bjpowernode.ba01.Student">
<property name="name" value="张三"/>
<property name="age" value="20"/>
</bean>
</beans>
property标签中的name属性:调用的是name属性对应的Set方法
因为只是使用set方法,所以类中即使没有email这个属性,只定义一个setEmail()方法也是可以正常执行的
当类中有引用类型的属性时呢?
Student类:
package com.bjpowernode.ba01;
public class Student {
private String name;
private int age;
private School school;
//Setter()方法.....
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", school=" + school +
'}';
}
}
School类:
package com.bjpowernode.ba01;
public class School {
private String name;
private String address;
//Setter()方法...
@Override
public String toString() {
return "School{" +
"name='" + name + '\'' +
", address='" + address + '\'' +
'}';
}
}
XML文件中:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="student" class="com.bjpowernode.ba01.Student">
<property name="name" value="张三"/>
<property name="age" value="20"/>
<property name="school" ref="MySchool"/>
</bean>
<bean id="MySchool" class="com.bjpowernode.ba01.School">
<property name="name" value="北京大学"/>
<property name="address" value="北京"/>
</bean>
</beans>
2.构造注入
构造注入使用constructor-arg 标签
创建Student和School类,并加入构造方法:
package com.bjpowernode.ba01;
public class Student {
private String name;
private int age;
private School school;
public Student(String myname, int myage, School myschool) {
this.name = myname;
this.age = myage;
this.school = myschool;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", school=" + school +
'}';
}
}
//=======================================================
package com.bjpowernode.ba01;
public class School {
private String name;
private String address;
public School(String schoolname, String schooladdress) {
this.name = schoolname;
this.address = schooladdress;
}
@Override
public String toString() {
return "School{" +
"name='" + name + '\'' +
", address='" + address + '\'' +
'}';
}
}
创建XML文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="student" class="com.bjpowernode.ba01.Student">
<constructor-arg name="myname" value="张三"/>
<constructor-arg name="myage" value="20"/>
<constructor-arg name="myschool" ref="MySchool"/>
</bean>
<bean id="MySchool" class="com.bjpowernode.ba01.School">
<!--<property name="name" value="北京大学"/>
<property name="address" value="北京"/>-->
<constructor-arg name="schooladdress" value="北京"/>
<constructor-arg name="schoolname" value="北京大学"/>
</bean>
</beans>
也可以使用constructor-arg 标签的index属性,index可省略:
<bean id="student" class="com.bjpowernode.ba01.Student">
<constructor-arg index="0" value="张三"/>
<constructor-arg index="1" value="20"/>
<constructor-arg index="2" ref="MySchool"/>
</bean>
创建测试类:
public class MyTest {
@Test
public void test01(){
String config = "ba01/applicationContext.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(config);
Student student = (Student) ac.getBean("student");
System.out.println(student);
}
}
Student{name=‘张三’, age=20, school=School{name=‘北京大学’, address=‘北京’}}
一个constructor-arg标签表示构造方法的一个参数
constructor-arg标签中的属性:
name: 表示构造方法的形参名
index: 表示构造方法的参数的位置,参数从左往右的位置是从0开始的
value: 构造方法的形参类型是简单类型的,使用value
ref: 构造方法的形参类型是引用类型的,使用ref
3. 自动注入:
引用类型的自动注入:spring框架中根据某些规则可以给引用类型赋值,不用你再给引用类型赋值了
引用规则常用的是byName,ByType
byName:
按名称注入:Java类中引用类型的属性名和spring框架中(配置文件)bean标签的id名称一样,且数据类型是一致的,这样的容器中的bean,spring能够赋值给引用类型
1)创建Student类和School类
package com.bjpowernode.ba01;
public class Student {
private String name;
private int age;
private School school;
//setter方法...
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", school=" + school +
'}';
}
}
package com.bjpowernode.ba01;
public class School {
private String name;
private String address;
//setter方法...
@Override
public String toString() {
return "School{" +
"name='" + name + '\'' +
", address='" + address + '\'' +
'}';
}
}
2)XML文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="student" class="com.bjpowernode.ba01.Student" autowire="byName">
<property name="name" value="张三"/>
<property name="age" value="20"/>
</bean>
<bean id="school" class="com.bjpowernode.ba01.School">
<property name="address" value="北京"/>
<property name="name" value="北京大学"/>
</bean>
</beans>
3) 测试类:
public class MyTest {
@Test
public void test01(){
String config = "ba01/applicationContext.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(config);
Student student = (Student) ac.getBean("student");
System.out.println(student);
}
}
Student{name=‘张三’, age=20, school=School{name=‘北京大学’, address=‘北京’}}
byType:
按类型注入:Java类中引用的数据类型和spring容器中(配置文件)bean标签中的class属性是 同源 关系的,这样的bean能够赋值给引用类型
同源: 就是一类的意思
1)Java类中引用类型的数据类型和bean的class的值是一样的
2)Java类中引用类型的数据类型和bean的class的值是父子类关系的
3)Java类中引用类型的数据类型和bean的class的值是接口和实现类关系的
在上述byName代码的基础之上:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="student" class="com.bjpowernode.ba01.Student" autowire="byType">
<property name="name" value="张三"/>
<property name="age" value="20"/>
</bean>
<bean id="mySchool" class="com.bjpowernode.ba01.School">
<property name="address" value="北京"/>
<property name="name" value="北京大学"/>
</bean>
//假设MySchool这个类继承了School,且使用byType时,那么加入下面的bean标签会报错
<bean id="mySchool" class="com.bjpowernode.ba01.MySchool">
<property name="address" value="北京"/>
<property name="name" value="北京大学"/>
</bean>
</beans>
注意:自动类型注入xml中只能声明一个符合条件的,多于一个会报错
6. 为什么使用多配置文件:
当项目中的类很多,模块很多的时候,使用一个配置文件属实不方便
我们可以使用多配置文件来划分模块类型或类:
例如:项目中有 学生模块 和 学校模块
学生模块:Spring-Student.xml
学校模块:Spring-School.xml
还需创建一个主配置文件:Total.xml
在Total.xml中写入import标签,并在import标签的resource属性中说明要链接的其他模块xml文件的位置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="classpath:ba01/Spring-Student.xml"/>
<import resource="classpath:ba01/Spring-School.xml"/>
</beans>
也可以使用通配符的方式:Spring-*.xml
<import resource="classpath:ba01/Spring-*.xml"/>
使用这种方式时,主配置文件名称不能以Spring开头命名,否则会死循环,递归
7.基于注解的注入方式:
需要学习的注解:
1)@Component
2)@Respotory:用在持久层上面,放在dao的实体类上面,表示创建dao对象,dao对象是能访问数据库的
3)@Service:用在业务层类的上面的,放在service的实现类上面,创建service对象,service对象是做业务处理,可以有事务功能的
4)@Controller:用在控制器上面,放在控制器(处理器)类的上面,创建控制对象的,控制器对象能接受用户提交的参数,显示请求的处理结果
以上的功能是一样的,都能创建对象,但是这三个注解还有额外的功能,给项目对象分层的
5)@Value
6)@Autowired
7)@Resource
使用步骤:
1)创建实体类,并加入注解:
Student类:
package com.bjpowernode.ba01;
import org.springframework.stereotype.Component;
//加入注解,并命名
@Component(value = "myStudent")
public class Student {
private String name;
private int age;
//Setter和Getter方法...
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
@Component(value = “myStudent”)
这句话的意思等同于:
<bean id="myStudent" class="com.bjpowernode.ba01.Student"/>
如果不指定value属性值,则获取bean的时候使用spring默认设置的名称:类名(首字母需小写)
2)在配置文件中声明扫描器:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.bjpowernode.ba01"/>
</beans>
3)创建测试类:
public class MyTest {
@Test
public void test01(){
String config = "applicationContext.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(config);
Student student = (Student) ac.getBean("myStudent");
System.out.println(student);
}
}
如何在扫描器中指定多个不同的包呢?
指定多个包的三种方式:
1)使用多次的组件扫描器,指定不同的包
<context:component-scan base-package="com.bjpowernode.ba01"/>
<context:component-scan base-package="com.bjpowernode.ba02"/>
<context:component-scan base-package="com.bjpowernode.ba03"/>
2)使用分隔符(;或,)分隔多个包名
<context:component-scan base-package="com.bjpowernode.ba01;
com.bjpowernode.ba02;
com.bjpowernode.ba03"/>
3)指定父包
<context:component-scan base-package="com.bjpowernode"/>
简单类型的属性赋值:
使用@Value
value属性:
String类型的,表示简单类型的属性值
value属性可省略
位置:
1.在属性定义的上面
package com.bjpowernode.ba01;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component("myStudent")
public class Student {
@Value(value = "张三")
private String name;
@Value("25")
private int age;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
2.在set方法的上面
package com.bjpowernode.ba01;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component(value = "myStudent")
public class Student {
private String name;
private int age;
@Value(value = "张三")
public void setName(String name) {
this.name = name;
}
@Value(value = "25")
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
引用属性的赋值:
使用@Autowired
有两种方式:byType和byName
位置:
1.在属性定义的上面
2.在set方法的上面
1.使用byType(默认就是byType)
1.创建School类并赋值:
package com.bjpowernode.ba01;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component(value = "mySchool")
public class School {
@Value("北京大学")
private String name;
@Value("北京")
private String address;
public void setName(String name) {
this.name = name;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "School{" +
"name='" + name + '\'' +
", address='" + address + '\'' +
'}';
}
}
2.创建Student类并且给引用类型赋值:
package com.bjpowernode.ba01;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component("myStudent")
public class Student {
@Value(value = "张三")
private String name;
@Value("25")
private int age;
@Autowired
private School school;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setSchool(School school) {
this.school = school;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", school=" + school +
'}';
}
}
3.创建测试类:
public class MyTest {
@Test
public void test01(){
String config = "applicationContext.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(config);
Student student = (Student) ac.getBean("myStudent");
System.out.println(student);
}
}
Student{name=‘张三’, age=25, school=School{name=‘北京大学’, address=‘北京’}}
2. 使用使用byName
需要做的是:
1.在属性上面加入@Autowired
2.在属性上面加入@Qualifier(value = “bean的id”)
实现步骤:
1):创建School类:
package com.bjpowernode.ba01;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component(value = "mySchool")
public class School {
@Value("北京大学")
private String name;
@Value("北京")
private String address;
public void setName(String name) {
this.name = name;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "School{" +
"name='" + name + '\'' +
", address='" + address + '\'' +
'}';
}
}
2)创建Student类:使用 @Qualifier(value = “mySchool”)
package com.bjpowernode.ba01;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component("myStudent")
public class Student {
@Value(value = "张三")
private String name;
@Value("25")
private int age;
@Autowired
@Qualifier(value = "mySchool")
private School school;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setSchool(School school) {
this.school = school;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", school=" + school +
'}';
}
}
3)创建测试类:
public class MyTest {
@Test
public void test01(){
String config = "applicationContext.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(config);
Student student = (Student) ac.getBean("myStudent");
System.out.println(student);
}
}
Student{name=‘张三’, age=25, school=School{name=‘北京大学’, address=‘北京’}}
@Autowired的required属性
在上述使用byType给引用属性赋值的代码基础上:
如果**@Qualifier(value = “指定的bean的ID不存在”)** 的话,程序会报错并且停止运行,也就是下面的情况
@Autowired
@Qualifier(value = "我不存在哦!")
private School school;
如何解决保存程序会执行结束的问题呢?
使用@Autowired的required属性:
默认和不写为true,表示引用类型赋值失败,程序报错并且终止运行
将其设置为false后,引用类型如果赋值失败,程序正常执行,引用类型的值为null
那么Autowired的required属性用true还是false呢?
使用true:能将问题爆露出来并能够及时得到解决
8.使用JDK中的注解给引用类型的属性赋值:
@Resource:来自jdk中的注解,spring框架中提供了对这个注解功能的支持,可以使用它给引用类型赋值
使用的也是自动注入原理,支持byName,byType,默认是byName
位置:
1.在属性的定义的上面,无需set方法,推荐使用
2.在set方法的上面
使用@Resource注解的,默认是Byname,如果byName找不到需要的bean,则自动使用byType
School类:
package com.bjpowernode.ba01;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component(value = "mySchool")
public class School {
@Value("北京大学")
private String name;
@Value("北京")
private String address;
public void setName(String name) {
this.name = name;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "School{" +
"name='" + name + '\'' +
", address='" + address + '\'' +
'}';
}
}
Student类:
package com.bjpowernode.ba01;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component("myStudent")
public class Student {
@Value(value = "张三")
private String name;
@Value("25")
private int age;
@Resource
private School school;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setSchool(School school) {
this.school = school;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", school=" + school +
'}';
}
}
测试类:
package com.bjpowernode;
import com.bjpowernode.ba01.Student;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
@Test
public void test01(){
String config = "applicationContext.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(config);
Student student = (Student) ac.getBean("myStudent");
System.out.println(student);
}
}
结果仍会正常执行并赋值,因为使用@Resource注解的,默认是Byname,如果byName找不到需要的bean,则自动使用byType
如果只想使用byName方式:
@Resource(name = "mySchool")
private School school;
9.XML和注解的方式怎么选择呢?
注解的缺点:
1、很多朋友比如在使用spring注解时,会发现注解分散到很多类中,不好管理和维护;这个其实要借助工具,我目前使用的是IDEA,它在这方面表现的非常好;当然现在还有Spring的STS,也是不错的; 所以借助工具,能解决这个问题;
2、注解的开启/关闭必须修改源代码,因为注解是源代码绑定的,如果要修改,需要改源码,这个有这个问题,所以如果是这种情况,还是使用XML配置方式;比如数据源;
3、注解还一个缺点就是灵活性,在实现复杂的逻辑上,没有XML来的更加强大;注解就是要么用,要么不用,比如之前的jpa bean validation,要么全,要么没;遇到这种情况很痛苦;
4、还一种就是约定大于配置,但是在处理一些复杂的情况下,注解还是需要的(如Spring的数据验证/数据绑定注解很强大);
5、通用配置还是走XML吧,比如事务配置,比如数据库连接池等等,即通用的配置集中化,而不是分散化,如很多人使用@Transactional来配置事务,在很多情况下这是一种太分散化的配置;
6、XML方式比注解的可扩展性和复杂性维护上好的多,比如需要哪些组件,不需要哪些;在面对这种情况,注解扫描机制比较逊色,因为规则很难去写或根本不可能写出来;
注解的好处:
1、XML配置起来有时候冗长,此时注解可能是更好的选择,如jpa的实体映射;注解在处理一些不变的元数据时有时候比XML方便的多,比如springmvc的数据绑定,如果用xml写的代码会多的多;
2、注解最大的好处就是简化了XML配置;其实大部分注解一定确定后很少会改变,所以在一些中小项目中使用注解反而提供了开发效率,所以没必要一头走到黑;
3、注解相对于XML的另一个好处是类型安全的,XML只能在运行期才能发现问题。
10. 读取配置文件:
1)首先在resorurce文件夹下创建配置文件:
test.properties
myname=张三
myage=20
myschool=北京大学
myaddress=北京
2)在spring的主配置文件中加入context:property-placeholder标签:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.bjpowernode.ba01"/>
<context:property-placeholder location="classpath:test.properties"/>
</beans>
3)在Student类和School类中使用:
//Student类
package com.bjpowernode.ba01;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component("myStudent")
public class Student {
@Value(value = "${myname}")
private String name;
@Value("${myage}")
private int age;
@Resource(name = "mySchool")
private School school;
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", school=" + school +
'}';
}
}
//School类
package com.bjpowernode.ba01;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component(value = "mySchool")
public class School {
@Value("${myschool}")
private String name;
@Value("${myaddress}")
private String address;
@Override
public String toString() {
return "School{" +
"name='" + name + '\'' +
", address='" + address + '\'' +
'}';
}
}
4)测试类:
package com.bjpowernode;
import com.bjpowernode.ba01.Student;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
@Test
public void test01(){
String config = "applicationContext.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(config);
Student student = (Student) ac.getBean("myStudent");
System.out.println(student);
}
}
程序正常输出结果:
Student{name=‘张三’, age=25, school=School{name=‘北京大学’, address=‘北京’}}
第三章:AOP面向切面编程
本文地址:https://blog.csdn.net/qq_41151938/article/details/107068172