動態注冊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); }
