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);
// beanDefinitionBuilder.addPropertyValue("name",beanName);给bean设置属性
//注册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
SpringContextUtil的改进版,将构建bean和获取bean统一在一个类中
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; } } public static <T> T getBean(String name,Class<T> beanClass) { try { return applicationContext.getBean(name,beanClass); } catch (NoSuchBeanDefinitionException ex) { return null; } } //通过类型获取上下文中的bean public static Object getBean(Class<?> requiredType) { return applicationContext.getBean(requiredType); } public static void setBean(String beanName,Class<?> beanClass){ //获取ApplicationContext ConfigurableApplicationContext applicationContext = (ConfigurableApplicationContext) SpringContextUtil.getApplicationContext(); //通过ApplicationContext获取DefaultListableBeanFactory DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getBeanFactory(); //获取BeanDefinitionBuilder BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(beanClass); beanDefinitionBuilder.addPropertyValue("name",beanName); //注册bean beanFactory.registerBeanDefinition(beanName, beanDefinitionBuilder.getRawBeanDefinition()); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗