5. Bean 自动装配
2022年9月6日
5. Bean 自动装配
引用类型的自动注入: spring 框架根据某些规则可以给引用类型赋值.
不用你在给引用类型赋值了,使用的规则常用的是 byName, byType.
Spring 的三种装配方式
- xml 文件中显式装配
- 在 java 中显式装配
- 隐式自动装配(autowire)
ByName 自动装配
通过set 方法后面的属性名寻找对应的 bean id, 需要保证所有bean 的 id 唯一,并且这个bean id 需要和自动注入属性的 set 方法的属性名一致
public class Student {
    private String name;
    private int age;
    private School school;
    // set方法后面为School(首字母大写) 则配置文件的bean id是school(首字母必须小写)
    public void setSchool(School school) {
        this.school = school;
    }
}
<bean id="student" class="com.demo.di01.Student" autowire="byName"/>
<!--配置文件的id值-->
<bean id="school" class="com.demo.di01.School">
  <property name="name" value="school"/>
</bean>
ByType 自动装配
通过该属性的数据类型自动装配(有多个同源的数据类型的属性时无法使用), 需要保证该属性的 bean class 和set 方法的参数类型同源
同源就是一类的意思:
- java 类中set 方法的参数的数据类型和 bean 的 class 的值是一样的
- java 类中set 方法的参数的数据类型和 bean 的 class 的值是父类(参数)和子类(bean)的关系
- java 类中set 方法的参数的数据类型和 bean 的 class 的值是接口和实现类关系的
- 子类
// 子类
@Data
public class PrimarySchool extends School{
    public PrimarySchool() {
        System.out.println("PrimarySchool");
    }
}
- 父类
// 父类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class School {
    private String name;
}
- 学生类
public class Student {
    private String name;
    private int age;
    private School school;
    public void setSchool(School school) {
        System.out.println(school + "aaa");
    }
}
- beans.xml
<bean id="student" class="com.demo.di01.Student" autowire="byType"/>
<!--
    父类与子类同源, 不能同时存在
    <bean id="school" class="com.demo.di01.School">
            <property name="name" value="School"/>
    </bean>
-->
<bean id="school" class="com.demo.di01.PrimarySchool">
  <property name="name" value="PrimarySchool"/>
</bean>
使用注解自动装配
- 导入约束 - xmlns:context="http://www.springframework.org/schema/context"
- 配置注解的支持 - <?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/> <bean id="cat" class="pojo.Cat"/> <bean id="dog" class="pojo.Dog"/> <bean id="person" class="pojo.Person"/> </beans>
@Autowired
@Autowired, @Qualifier, @NUllable
- 在 IOC 容器中注册 bean 对象后,可在对应属性上直接使用该注解, 可以不写 set()方法, 该注解默认是通过 ByType 实现
- 该注解也可以在 set()方法上使用
- 该注解可以带参数
@Autowired(required = false)使用该参数后,该属性值允许为 null 效果和@NUllable类似
public class Animal {
    @Autowired(required = false)
    public String name;
    public void shut(@Nullable Animal animal) {
        System.out.println(animal.name + "shut");
    }
}
- 当自动装配的环境比较复杂(有多个相同类型的 bean 对象时),自动装配无法确定具体的 bean 对象,可以使用@Qualifier(value = "cat")指定唯一的 bean 对象配合@Autowired完成自动装配, 此时@Autowired通过 ByName 实现
@Autowired
@Qualifier(value = "cat")
private animal cat;
java 原生注解@Resource该注解和@Autowired相反默认通过 ByName,如果指定了 name,则用 byName 自动装配,如果指定了 type,则用 byType 自动装配
@Resource(name = "dog")
private Animal dog;
总结
@Autowired和@Resouce的区别
@Autowired默认按 byType 自动装配,而@Resource默认 byName 自动装配
@Autowired只包含一个参数: required,表示是否开启自动注入,默认是 true 而@Resource包含七个参数,其中最重要的两个参数是: name 和 type
@Autowired如果要使用 byName,需要使用@Qualifier一起配合而@Resource如果指定了 name,则用 byName 自动装配,如果指定了 type,则用 byType 自动装配
@Autowired能够用在: 构造器、方法、参数、成员变量和注解上,而@Resource能用在: 类、成员变量和方法上
@Autowired是 spring 定义的注解,而@Resource是 JSR-250 定义的注解