1. 基于@Autowired自动装配流程
编写Bean1
2
3
4
5
6
// 组件注解
public class Car {
private String name;
private Double price;
}
1 |
|
组件扫描1
<context:component-scan base-package="demo.spring.bean" />
编写测试方法1
2
3
4
5
6
public void test() throws Exception {
ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person = (Person) ioc.getBean("person");
System.out.println(person.getCar() != null); // true,自动装配成功
}
1.1. 只有Bean组件才能自动装配
如果去掉Person的组件注解,Spring根本就不会去管Person,@Autowired就没有意义了1
2
3
4
5
6
// @Component 去掉组件注解
public class Person {
// 无意义
private Car car;
}
如果去掉Car的组件注解,也是无法装配成功的1
2
3
4
5
6
public class Person {
// NoSuchBeanDefinitionException,找不到类型为Car的组件
private Car car;
}
2. @Autowired原理的简单探索
参考:https://blog.csdn.net/horacehe16/article/details/79811763
@Autowired可以应用于 属性、构造方法、setter等等。但是开发过程中应用于属性是最常见的。时间有限,就先只探索一下@Autowired应用于属性的情况
2.1. 探索:容器中该类型的组件只有一个
修改Person类,修改car属性名,发现自动装配成功,说明容器中同类型组件只有1个时,是根据类型注入,变量名与id不一致也没有关系1
2
3
4
5
6
public class Person {
private Car haha; // 修改属性名,使之与Car组件的id不一致
}
2.2. 探索:容器中该类型的组件有多个
基于注解注册多个Car组件1
2
3
4
5
6
public class Car {
private String name;
private Double price;
}
1 |
|
基于XML注册多个Car组件1
2<bean id="car1" class="demo.spring.bean.Car"/>
<bean id="car2" class="demo.spring.bean.Car"/>
修改Person,使得Car属性名与所有Car组件id不一致1
2
3
4
5
6
public class Person {
private Car haha; // 与所有Car组件的id都不一致
}
运行,抛出异常1
2
3
4
5org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'person': Unsatisfied dependency expressed through field 'haha';
nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException:
No qualifying bean of type 'demo.spring.bean.Car' available: expected single matching bean but found 2: car,carExtend
修改Person,使得Car属性名与其中一个Car组件id一致,发现注入成功。可知,容器中同一类型组件有多个,是根据 类型+id 同时匹配才注入。只有类型匹配是不够的1
2
3
4
5
6
7
8
9
10
11
12
public class Person {
private Car car; // 与Car的id一致,成功注入Car
private Car carExtend; // 与CarExtend的id一致,成功注入CarExtend
private Car car1;
private Car car2;
}
如果你不想修改变量名呢?此时可以使用@Autowired+@Qualifier的组合。注意必须两个注解结合使用1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Person {
("car") // 指定组件id
private Car carAaa;
("carExtend")
private Car carBbb;
("car1")
private Car carCcc;
("car2")
private Car carDdd;
}
@Autowired+@Qualifier写起来太麻烦,所以用@Resource进行简化
1 |
|
3. @Autowired的required属性
将Car的组件注解去掉1
2
3
4
5
6
// @Component 去掉
public class Car {
private String name;
private Double price;
}
因为没有类型为Car的组件,所以Person在注入Car时会出错。这是因为@Autowired有一个required属性,默认为true,表示找不到要注入的组件就会出错1
2
3
4
5
6
public class Person {
// NoSuchBeanDefinitionException,找不到类型为Car的组件
private Car car;
}
设置required=false1
2
3
4
5
6
public class Person {
(required=false) // 找不到类型为Car的组件,但不会出错,只是car的值为null
private Car car;
}
4. @Autowired与@Resource的区别
除了@Autowired,也可以直接用@Resource,二者效果上是等同的
1 |
|
在指定id时,@Autowired要结合@Qualifier,@Resource直接指定name属性即可1
2
3
4
5
6(name="car")
private Car car;
("car")
private Car car;
有3个注解都是实现自动装配的
- @Resource属于包javax.annotation,是JavaEE注解,所以最通用,扩展性最好,Spring/EJB都可以使用
- @Autowired属于包org.springframework.beans.factory.annotation,是Spring注解,功能最强大
- @Inject是EJB注解