Springboot動態裝載卸載Bean


有時候我們需要在項目中動態加載或者卸載Bean,這就需要Bean的class文件事先是存在的,只是在需要的時候才加載進來。

比如我定義一個接口OneService和它的一個實現類,下面是比較常規的實現,調用OneService的時候,調的就是OneServiceImplA

public interface OneService {
    String say();
}



//--------------------------------------------------
@Service
public class OneServiceImplA implements OneService {
    @Override
    public String say() {
        System.out.println("I'm OneServiceImplA");
        return "OneServiceImplA";
    }
}

 

但有些情況下,OneServiceImplA不能滿足我的需求,我想用OneServiceImplB,可以發現這個類上沒有注解,springboot啟動的時候不會加載它

public class OneServiceImplB implements OneService, InitializingBean {
    @Override
    public String say() {
        System.out.println("I'm OneServiceImplB");
        return "OneServiceImplB";
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("我是動態注冊的你,不是容器啟動的時候注冊的你");
    }

    @PreDestroy
    public void preDestroy() {
        System.out.println("我被動態刪除了!");
    }
}

當我想在項目中調用OneServiceImplB的時候怎么辦?我們需要實現一個工具類

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) {
        try {
            return applicationContext.getBean(name);
        } catch (NoSuchBeanDefinitionException ex) {
            return null;
        }
    }

    //通過類型獲取上下文中的bean
    public static Object getBean(Class<?> requiredType) {
        return applicationContext.getBean(requiredType);
    }
}

在項目啟動的時候,把ApplicationContext對象注入進去。

啟動類:

@SpringBootApplication
public class ServerApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext applicationContext = SpringApplication.run(ServerApplication.class, args);
        SpringContextUtil.setApplicationContext(applicationContext);
    }
}

這樣在有需要的時候,我們就可以動態的加載和刪除這個bean了。

 /**
     * 動態注冊Bean
     *
     * @param beanName
     * @return
     */
    @GetMapping("dynamicInit")
    public String initBean(String beanName) {
        //獲取ApplicationContext
        ConfigurableApplicationContext applicationContext = (ConfigurableApplicationContext) SpringContextUtil.getApplicationContext();
        //通過ApplicationContext獲取DefaultListableBeanFactory
        DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getBeanFactory();
        //獲取BeanDefinitionBuilder
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(OneServiceImplB.class);
        //注冊bean
        beanFactory.registerBeanDefinition(beanName, beanDefinitionBuilder.getRawBeanDefinition());
        OneServiceImplB oneServiceImplB = (OneServiceImplB) SpringContextUtil.getBean(beanName);
        return oneServiceImplB.say();
    }

    /**
     * 根據beanName刪除bean
     * @param beanName
     * @return
     */
    @GetMapping("dynamicRemove")
    public String removeBean(String beanName) {
        ConfigurableApplicationContext applicationContext = (ConfigurableApplicationContext) SpringContextUtil.getApplicationContext();
        DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getBeanFactory();
        //動態刪除bean
        beanFactory.removeBeanDefinition(beanName);
        return "remove ok";
    }

 參考:

https://www.cnblogs.com/eternityz/p/12241143.html

https://www.jianshu.com/p/fd357e1c579e


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM