【Spring】(重要)Bean的自动装配

23 阅读2分钟

新手小白记录跟着狂神学Spring的过程(第12-13集)~

1.bean的自动装配

自动装配的原理是基于byNamebyType的。

1.1 byName自动装配

会自动在容器中查找,和自己对象set方法后面的值对应的bean id。所以bean的id要全局唯一并且和属性名一致。

    <bean id="cat" class="com.pojo.Cat"/>

    <bean id="user" class="com.pojo.User" autowire="byName">
        <property name="school" value="scnu"/>  
        <!-- 省略了<property name="cat" ref="cat"/> -->
    </bean>

User user = context.getBean("user",User.class);

user.getCat.shout();

会输出:miao~

证明自动装配成功!

1.2 byType自动装配

会自动在容器上下文中,根据bean的class,查找和对象属性类型相同的bean(用byType自动装配可以无需bean的id)。

弊端:不能出现class相同的两个bean,否则会报错。

    <!-- 这里的id没起到作用,甚至可以不写id-->
    <bean id="dog1111" class="com.pojo.Dog"/>

    <bean id="user" class="com.pojo.User" autowire="byType">
        <property name="name" value="Zoe"/>  
        <!-- 省略了<property name="dog" ref="dog1111"/> -->
    </bean>

User user = context.getBean("user",User.class);

user.getDog.shout();

会输出:wang~

证明自动装配成功!

1.3 使用注解实现自动装配

首先,导入约束,然后添加对注解的支持。

<?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和class -->
    <bean id="cat" class="com.pojo.Cat"/>
    <bean id="dog" class="com.pojo.Dog"/>
    <bean id="user" class="com.pojo.User"/>
    
</beans>

@Autowired

  • 在类里面添加注解@Autowired,自动注入bean。默认先按byType查找,找不到则报错,找到多个就按byName查找。直接在属性上添加注解,也可以在set方法上使用。使用@Autowired可以不编写set方法,前提是自动装配的属性在IoC容器(也就是Spring容器)中存在,且名字相同。
public class User{  
  @Autowired
  private Cat cat;

  @Autowired
  private Dog dog;

  private String name;

  //以下省略get和set方法……
}
  • 如果显式地定义了@Autowired(required = "false") ,说明这个对象可以为null,否则不允许为空
  • 如果@Autowired 自动装配的环境比较复杂,例如同一个类有多个bean,我们可以使用 @Qualifier(value = "xxx") 来配合@Autowired 的使用,从而指定唯一的bean。
    <bean id="cat" class="com.pojo.Cat"/>
    <bean id="dog11" class="com.pojo.Dog"/>
    <bean id="dog22" class="com.pojo.Dog"/>
    <bean id="user" class="com.pojo.User"/>

public class User{
  
  @Autowired
  private Cat cat;

  @Autowired
  @Qualifier(value = "dog22")
  private Dog dog;

  private String name;

  //以下省略get和set方法……
}

@Resource

默认先通过byName寻找,可以指定bean的id @Resource(name = "dog11");

如果找不到名字,就通过byType寻找(此时根据byType的原则,在Spring容器中,目标类型必须有且仅有一个,否则报错)

    <bean id="cat" class="com.pojo.Cat"/>
    <bean id="dog11" class="com.pojo.Dog"/>
    <bean id="dog22" class="com.pojo.Dog"/>
    <bean id="user" class="com.pojo.User"/>

public class User{
  
  @Resource
  private Cat cat;

  @Resource(name = "dog11")
  private Dog dog;

  private String name;

  //以下省略get和set方法……
}

@Resource和@Autowired的区别:

@Autowired@Resource
实现方式先 byType,后 byNamebyType 为基础)先 byName,后 byTypebyName 为基础)
名称指定方式需配合 @Qualifier 注解直接通过 name 属性指定
支持泛型注入支持(如 List<UserService>不支持

补充:@Autowired 支持泛型注入的场景

// 泛型接口
public interface BaseService<T> {}

// 实现类1(泛型类型:User)
@Service
public class UserService implements BaseService<User> {}

// 实现类2(泛型类型:Order)
@Service
public class OrderService implements BaseService<Order> {}

// 注入:按泛型类型(BaseService<User>)匹配,找到唯一UserService
@Autowired
private BaseService<User> userBaseService;

参考视频:12、自动装配Bean_哔哩哔哩_bilibili13、注解实现自动装配_哔哩哔哩_bilibili