5. Bean 自动装配

空~2022年9月6日
  • Spring
大约 3 分钟

5. Bean 自动装配

引用类型的自动注入: spring 框架根据某些规则可以给引用类型赋值.

不用你在给引用类型赋值了,使用的规则常用的是 byName, byType.

Spring 的三种装配方式

  1. xml 文件中显式装配
  2. 在 java 中显式装配
  3. 隐式自动装配(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 方法的参数类型同源

同源就是一类的意思:

  1. java 类中set 方法的参数的数据类型和 bean 的 class 的值是一样的
  2. java 类中set 方法的参数的数据类型和 bean 的 class 的值是父类(参数)和子类(bean)的关系
  3. 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>

使用注解自动装配

  1. 导入约束

    xmlns:context="http://www.springframework.org/schema/context"
    
  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
                            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 定义的注解