转载自:https://www.cnblogs.com/leihuazhe/p/8137564.html
定义一个没有被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");
}
如上,就能动态的注册bean。
注意:
假如动态bean中属性不是引用context中的,需要通过参数传入。
例如:
public class UserService{
private InterfaceGroup group;
public InterfaceGroup getGroup() {
return group;
}
public void setGroup(InterfaceGroup group) {
this.group = group;
}
}
InterfaceGroup group =new InterfaceGroup();
//设置属性....
group.setXXX()
//传入参数给动态bean引用
registerBean(group)
/**
* 动态注册bean
*
* @param group 自定义类型
* @return
*/
public void registerBean(InterfaceGroup group) {
//将applicationContext转换为ConfigurableApplicationContext
ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) SpringContextUtil.getApplicationContext();
// 获取bean工厂并转换为DefaultListableBeanFactory
DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) configurableApplicationContext.getBeanFactory();
// 通过BeanDefinitionBuilder创建bean定义
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(UserService.class);
// 设置属性
beanDefinitionBuilder.addPropertyValue("group", group);
// 注册bean
defaultListableBeanFactory.registerBeanDefinition("userService", beanDefinitionBuilder.getRawBeanDefinition());
//通过工具类获取动态注册的bean
LOG.info((SpringContextUtil.getBean("userService")).toString());