动态注册bean的两种api
Spring中的bean定义都保存在 BeanDefinitionRegistry 接口中,单例的bean的实例都保存在 SingletonBeanRegistry 接口中。
因此动态注册bean也分为了两种方式:
使用BeanDefinitionRegistry接口的
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException
方法使用SingletonBeanRegistry接口的
void registerSingleton(String beanName, Object singletonObject)
方法
两者区别在于使用前者时,Spring容器会根据BeanDefinition实例化bean实例,而使用后者时,bean实例就是传递给registerSingleton方法的对象。
这里DefaultListableBeanFactory接口同时实现了这两个接口,在实践中通常会使用这个接口。
注意
我们可以在任何获得了BeanDefinitionRegistry或者SingletonBeanRegistry实例的地方进行动态注册。
但是如果bean不是在BeanFactoryPostProcessor中被注册,那么该bean则无法被BeanPostProcessor处理,即无法对其应用aop、Bean Validation等功能(因为IOC中绑定AOP发生在BeanPostProcessor的Spring生命周期方法里)。
在BeanFactoryPostProcessor中进行动态注册
public class PersonBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
DefaultListableBeanFactory defaultListableBeanFactory
= (DefaultListableBeanFactory) beanFactory;
//注册Bean定义,容器根据定义返回bean
log.info("register personManager1>>>>>>>>>>>>>>>>");
BeanDefinitionBuilder beanDefinitionBuilder =
BeanDefinitionBuilder.genericBeanDefinition(PersonManager.class);
beanDefinitionBuilder.addPropertyReference("personDao", "personDao");
BeanDefinition personManagerBeanDefinition = beanDefinitionBuilder.getRawBeanDefinition();
defaultListableBeanFactory.registerBeanDefinition("personManager1", personManagerBeanDefinition);
//注册bean实例
log.info("register personManager2>>>>>>>>>>>>>>>>");
PersonDao personDao = beanFactory.getBean(PersonDao.class);
PersonManager personManager = new PersonManager();
personManager.setPersonDao(personDao);
beanFactory.registerSingleton("personManager2", personManager);
}
}
在普通bean中注册
@RestController
@Slf4j
public class PersonManagerRegisterController {
/**
* The Application context.
*/
@Autowired
GenericApplicationContext applicationContext;
/**
* The Bean factory.
*/
@Autowired
ConfigurableBeanFactory beanFactory;
/**
* 动态注册bean,此处注册的bean没有AOP的支持
*/
@GetMapping("/registerPersonManager")
public void registerPersonManager() {
PersonDao personDao = applicationContext.getBean(PersonDao.class);
PersonManager personManager = new PersonManager();
personManager.setPersonDao(personDao);
beanFactory.registerSingleton("personManager3", personManager);
}