1、简单介绍
自动装配是 Spring 满足 bean依赖的一种方式,Spring 会在上下文中自动寻找,并自动给 bean 装配属性。
Spring 中有三种装配的方式
- 在 xml 中显示的配置 (前面几篇博客都用的显示xml配置)
- 在 java 中显示的配置
- 隐式的自动装配bean(重要)
2、测试环境准备
- 一条狗
public class Dog {
public void shout(){
System.out.println("汪汪汪~~~");
}
}
- 一只猫
public class Cat {
public void shout(){
System.out.println("喵喵喵~~~");
}
}
- 一个人
public class People {
private String name;
private Dog dog;
private Cat cat;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
public Cat getCat() {
return cat;
}
public void setCat(Cat cat) {
this.cat = cat;
}
@Override
public String toString() {
return "People{" +
"name='" + name + '\'' +
", dog=" + dog +
", cat=" + cat +
'}';
}
}
- beans.xml
<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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="dog" class="com.study.pojo.Dog"/>
<bean id="cat" class="com.study.pojo.Cat"/>
<bean id="people" class="com.study.pojo.People">
<property name="name" value="Amy"/>
<property name="dog" ref="dog"/>
<property name="cat" ref="cat"/>
</bean>
</beans>
- 测试类
public class MyTest {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
People people = (People) applicationContext.getBean("people");
// 汪汪汪~~~
people.getDog().shout();
// 喵喵喵~~~
people.getCat().shout();
}
}
上述代码还用的是 xml 显示的配置属性
3、ByName 自动装配
<bean id="dog" class="com.study.pojo.Dog"/>
<bean id="cat" class="com.study.pojo.Cat"/>
<!-- byName: 会自动在容器上下文中查找,和自己对象set方法后面的值对应的beanId -->
<bean id="people" class="com.study.pojo.People" autowire="byName">
<property name="name" value="Amy"/>
</bean>
4、ByType 自动装配
<bean class="com.study.pojo.Dog"/>
<bean class="com.study.pojo.Cat"/>
<!-- byType: 会自动在容器上下文中查找,和自己对象属性类型相同的bean,bean的id可以省略 -->
<bean id="people" class="com.study.pojo.People" autowire="byType">
<property name="name" value="Amy"/>
</bean>
小结:
- ByName 的时候,需要保证所有 bean 的 id 唯一,并且这个 beanId 需要和自动注入的属性的set 方法的值一致!
- ByType 的时候,需要保证所有 bean 的 class 唯一,并且这个 beanId 需要和自动注入的属性的类型一致!
5、使用注解实现自动装配
- 导入约束
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
</beans>
- 配置注解的支持
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
// 开启注解的支持
<context:annotation-config/>
</beans>
- @Autowired
xml 改造
<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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<bean id="dog" class="com.study.pojo.Dog"/>
<bean id="cat" class="com.study.pojo.Cat"/>
<bean id="people" class="com.study.pojo.People"/>
</beans>
对象改造
public class People {
private String name;
@Autowired
private Dog dog;
@Autowired
private Cat cat;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Dog getDog() {
return dog;
}
public Cat getCat() {
return cat;
}
@Override
public String toString() {
return "People{" +
"name='" + name + '\'' +
", dog=" + dog +
", cat=" + cat +
'}';
}
}
public @interface Autowired {
boolean required() default true;
}
@Autowired 会根据byName和byType去上下文自动装配,直接在属性上使用即可,也可以在 set 方法上使用,使用 @Autowired 我们可以不用编写 set 方法了,前提是这个自动装配的bean在ioc容器中存在,且符合ByName自动装配
科普一个注解:@Nullable
字段标记了这个注解,说明这个字段可以为 null。
@Autowired(required = false)
如果 required = false ,就相当于@Nullable
说明这个字段可以为 null
使用@Autowired的对象,如果容器中的bean 都不符合byName和byType自动装配要求,比如说类型一样的有多个,名字和set后面的名称不一致,我们还可以用 @Qualifier(value = "")
配合@Autowired来指定装配一个唯一的bean
@Autowired(required = false)
@Qualifier(value = "dog111")
private Dog dog;
@Autowired
@Qualifier(value = "cat111")
private Cat cat;
@Resource
:Java 原生的注解,和 @Autowired 有一样的功能,适用于byName和byType自动装配,还可指定name,找到唯一的bean
@Resource
private Dog dog;
@Resource(name = "cat1")
private Cat cat;
小结
@Autowired 和 @Resource 的区别:
- 都是用来自动装配的,都可以放在属性字段上
- @Autowired 是先通过byType的方式查找bean,如果相同类型的bean大于1,则按byName的方式查找bean,如果名字还不一样,可以用 @Qualifier(value = “dog111”) 来指定唯一的bean
- @Resource 是先通过byName的方式查找bean,如果名字找不到,则通过byType的方式查找bean,如果还找不到,可以通过@Resource(name = “cat1”)指定唯一的bean
- 执行顺序不同,@Autowired 是先 byType 再 byName,@Resource 则相反