Spring的自动化装配Bean

 2023-02-17
原文作者:小岛秀夫 原文地址:https://juejin.cn/post/7025920578104066056

在Spring中,对象无需自己查找或创建与其关联的其他对象,而是由容器进行对象的“装配”,这就是Spring中依赖注入的本质。我们可以通过在代码中加入一些注解或配置自动装配Bean,实现自动化装配需要以下两步:

  1. 创建Bean并能在容器中注册
  2. 自动满足Bean之间的依赖

创建Bean并能在容器中注册

要创建能在容器中被发现的Bean,首先要在对应的类上使用@Component(或@Controller@Repository@Service)注解,使其称为一个Spring的Bean,其名称为类名。 例如我们将@Service注解加到如下实现类上

    @Service
    public class EmployeeServiceImpl implements EmployeeService {
        // ...
    }

在查看Spring容器中加载了哪些类

    @Test
    public void getAllBeans() {
        String[] beans = applicationContext.getBeanDefinitionNames();
        for (String beanName : beans) {
            Class<?> beanType = applicationContext.getType(beanName);
            System.out.println("BeanName:" + beanName);
            System.out.println("Bean的类型:" + beanType);
            System.out.println("Bean所在的包:" + beanType.getPackage());
        }
    }

得到了如下的输出

    BeanName:employeeServiceImpl
    Bean的类型:class com.meituan.finance.account.biz.impl.EmployeeServiceImpl
    Bean所在的包:package com.meituan.finance.account.biz.impl

可以发现Bean的名称默认为类名的小驼峰命名。 我们也可以,通过使用@Service("empService")Named("empService")自定义Bean的名称为empService

当bean生成之后我们需要让Spring容器能够在启动时发现并进行管理,就需要启用组件扫描 使用@ComponentScan注解可以启用Bean组件的扫描,默认情况下扫描所在类相同的包,或者在XML中进行配置

    <context:component-scan base-package="com.meituan.finance.account"/>

自动满足Bean之间的依赖

Spring提供了@Autowried注解用于进行Bean的自动装配,可以用于属性、构造方法和set方法上。在启动spring IoC时,容器自动装载了一个AutowiredAnnotationBeanPostProcessor后置处理器,当容器扫描到@Autowied@Resource(CommonAnnotationBeanPostProcessor后置处理器处理的)或@Inject时,就会在IoC容器自动查找需要的bean,并装配给该对象的属性 在使用@Autowired时,首先在容器中查询对应类型的bean

  1. 如果查询结果刚好为一个,就将该bean装配给@Autowired指定的数据
  2. 如果查询的结果不止一个,那么@Autowired会根据名称来查找。
  3. 如果查询的结果为空并且required=false(more),那么会抛出异常。

Spring官方推荐将其应用在构造方法上,定义一个全参的构造方法后,对其加上@Autowired注解,实际上这个注解可以省略:

当一个类只有一个构造函数时,可以省略@Autowired的注解。

对构造方法加入注解,有以下优点

  1. 允许声明不可变域,即使用final修饰。
  2. 容易遵循单一职责设计原则。
  3. 注入的顺序更靠前

Java变量的初始化顺序:

  1. 静态变量或静态语句块
  2. 实例变量或初始化语句块
  3. 构造方法
  4. @Autowired装配的对象