在spring運行時,動態的添加bean,dapeng框架在解析xml的soa:service字段時,使用到了動態注冊,注冊了一個實現了
FactoryBean
類!
定義一個沒有被Spring管理的Controller
public class UserController implements InitializingBean{
private UserService userService;
public UserService getUserService() {
return userService;
}
public void setUserService(UserService userService) {
this.userService = userService;
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("我是動態注冊的你,不是容器啟動的時候注冊的你");
}
public String toAction(String content){
return "-->" + userService.doService(content);
}
}
需要注意的是,如果要注入UserService,需要提供它的getter和setter方法
現在啟動springboot工程,顯而易見這個類是不會被Spring管理的,接下來我們定義一個獲取Spring上下文的工具類,如下
工具類
public class SpringContextUtil {
private static ApplicationContext applicationContext;
//獲取上下文
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
//設置上下文
public static void setApplicationContext(ApplicationContext applicationContext) {
SpringContextUtil.applicationContext = applicationContext;
}
//通過名字獲取上下文中的bean
public static Object getBean(String name){
return applicationContext.getBean(name);
}
//通過類型獲取上下文中的bean
public static Object getBean(Class<?> requiredType){
return applicationContext.getBean(requiredType);
}
}
我們在Springboot的啟動類中,保存當前Spring上下文,代碼如下:
@SpringBootApplication
public class HelloApplication {
public static void main(String[] args) {
ApplicationContext app = SpringApplication.run(HelloApplication.class, args);
SpringContextUtil.setApplicationContext(app);
}
}
然后我們在另一個被Spring管理的容器中,寫如下方法,進行bean的動態注冊
@GetMapping("/bean")
public String registerBean() {
//將applicationContext轉換為ConfigurableApplicationContext
ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) SpringContextUtil.getApplicationContext();
// 獲取bean工廠並轉換為DefaultListableBeanFactory
DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) configurableApplicationContext.getBeanFactory();
// 通過BeanDefinitionBuilder創建bean定義
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(UserController.class);
// 設置屬性userService,此屬性引用已經定義的bean:userService,這里userService已經被spring容器管理了.
beanDefinitionBuilder.addPropertyReference("userService", "userService");
// 注冊bean
defaultListableBeanFactory.registerBeanDefinition("userController", beanDefinitionBuilder.getRawBeanDefinition());
UserController userController = (UserController) SpringContextUtil.getBean("userController");
return userController.toAction("動態注冊生成調用");
//刪除bean.
//defaultListableBeanFactory.removeBeanDefinition("testService");
}