前言

Spring 中用BeanDefinition接口描述一个bean,描述对象的信息,依赖的信息,Spring容器中用ConcurrentHashMap<String, BeanDefinition> beanDefinitionMap
存储beanName和BeanDefinition对象的映射关系【beanDefinitionMap 可参考DefaultListableBeanFactory】。
Spring在实例化一个bean,都是先从 beanDefinitionMap 中获取beanDefinition对象,进而构造出对应的bean。因此,我们手动注册bean的问题,就演化为如何往这个 beanDefinitionMap 放入我们要注册bean对应的 BeanDefinition 对象。
好的框架肯定有好的拓展性,Spring 提供了 BeanDefinitionRegistry 接口来操作底层beanFactory实现的beanDefinitionMap。
Spring5中的BeanDefinitionBuilder增加了一个新的genericBeanDefinition方法,签名如下:
public static BeanDefinitionBuilder genericBeanDefinition(
@Nullable Class beanClass, Supplier instanceSupplier)

实现思路

将自定义对象注入 ConcurrentHashMap<String, BeanDefinition> beanDefinitionMap 中,需要三个方法来实现,方法的签名省略了,只是用于说明步骤:

  1. BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(); 获取到 beanDefinitionBuilder 对象;
  2. BeanDefinition beanDefinition = beanDefinitionBuilder.getRawBeanDefinition(); 获取具体的beanDefinition对象;
  3. beanFactory.registerBeanDefinition(); 将beanDefinition对象注入到 beanDefinitionMap 中。

具体代码

下面用1个示例来说明,如何手动的将自定义对象注册到spring容器中。

  1. 创建两个对象,其中PersonDao和PersonManager是依赖关系,PersonManager是一个自建的类,而PersonDao对象已经交给spring管理了,目的是将PersonManager类交给spring管理。
    在这里插入图片描述
    在这里插入图片描述

  2. 将PersonManager对象交给spring管理

@Component
public class Test {

    @Autowired
    private ConfigurableApplicationContext context;

    /**
     * 初始化.
     */
    @PostConstruct
    public void init() {
        DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) context.getBeanFactory();
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder
            .genericBeanDefinition(PersonManager.class, () -> {
                PersonDao personDao = beanFactory.getBean(PersonDao.class);
                PersonManager personManager = new PersonManager();
                personManager.setPersonDao(personDao);
                return personManager;
            });
        BeanDefinition personManagerBeanDefinition = beanDefinitionBuilder
            .getRawBeanDefinition();
        ((DefaultListableBeanFactory) beanFactory)
            .registerBeanDefinition("personManager2", personManagerBeanDefinition);
    }
}

BeanDefinitionBuilder.genericBeanDefinition()方法的第一个参数是personManager2的类型,是PersonManager类型,第二个参数是Supplier类型,返回PersonManager类型的对象,可以new一个PersonManager类型对象返回,在Supplier的重写方法中,创建对象,给对象的成员变量personDao赋值。这样对象和对象的依赖关系就生成了,最后把对象交给spring管理。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐