spring 程序执行时动态注册bean到context

 转载自: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());

 

展开阅读全文

没有更多推荐了,返回首页