首先回忆一下,Spring的bean都是BeanFactory中管理的,具体的类就是DefaultListableBeanFactory,在这个类当中有一个注入bean的方法:registerBeanDefinition,在调用registerBeanDefinition方法时,需要BeanDefinition参数,那么这个参数怎么获取呢?Spring提供了BeanDefinitionBuilder可以构建一个BeanDefinition,那么我们的问题就是如何获取BeanFactory了,这个就很简单了,只要获取到ApplicationContext对象即可获取到BeanFacory了
具体步骤如下:
XXX yourBean = new XXX();
//1.将applicationContext转化为ConfigurableApplicationContext
ConfigurableApplicationContext context = (ConfigurableApplicationContext) applicationContext;
//2.获取bean工厂并转换为DefaultListableBeanFactory
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) context.getBeanFactory();
//3.本文用的是DruidDataSource,所有在这里我们获取的是该bean的BeanDefinitionBuilder,通过BeanDefinitionBuilder来创建bean定义
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(XXXX.class);
//4.获取XXX类里的属性和对应值,并将其交给BeanDefinitionBuilder创建bean的定义
Map<String, Object> propertyKeyValues = getPropertyKeyValues(XXX.class, yourBean);
for(Map.Entry<String,Object> entry : propertyKeyValues.entrySet()) {
beanDefinitionBuilder.addPropertyValue(entry.getKey(), entry.getValue());
}
//5.bean定义好以后,将其交给beanFactory注册成bean对象,由spring容器管理
beanFactory.registerBeanDefinition(yourBeanName,beanDefinitionBuilder.getBeanDefinition());
//6.最后获取步骤5生成的bean
XXX yourbean = context.getBean(yourBeanName);
// 动态删除
beanFactory.removeBeanDefinition("yourBeanName");
多次注入同一个bean的情况
//多次注入同一个bean的,如果beanName不一样的话,那么会产生两个Bean;如果beanName一样的话,后面注入的会覆盖前面的。
//第二种情况的时候,
用beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(XXX.class);
获取bean会报错,因为在getBean的时候,找到了两个bean,这时候就不知道要获取哪个了,可以用XXX yourBean=ctx.getBean("yourBeanName") 来获取