前言
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 中,需要三个方法来实现,方法的签名省略了,只是用于说明步骤:
- BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(); 获取到 beanDefinitionBuilder 对象;
- BeanDefinition beanDefinition = beanDefinitionBuilder.getRawBeanDefinition(); 获取具体的beanDefinition对象;
- beanFactory.registerBeanDefinition(); 将beanDefinition对象注入到 beanDefinitionMap 中。
具体代码
下面用1个示例来说明,如何手动的将自定义对象注册到spring容器中。
-
创建两个对象,其中PersonDao和PersonManager是依赖关系,PersonManager是一个自建的类,而PersonDao对象已经交给spring管理了,目的是将PersonManager类交给spring管理。
-
将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管理。