如何以编程方式刷新springbean



我们有一个Spring应用程序负责完成一些集成工作,预计该应用程序将全天候运行。

我们使用的集成模式之一是使用一堆集群IBMMQ队列管理器的JMS消息传递。对于集群的IBM MQ队列管理器,如果其中一个队列管理器出现故障,则需要重新实例化队列连接工厂bean,以便连接能够与仍在运行的其余队列管理器一起工作。

我们进行了JMS健康检查,IBM MQ队列管理器的状态发生了变化,我们用程序重新启动了spring上下文,结果重新创建了队列连接工厂bean,一切都很好。

然而,这对我们来说并不理想,因为我们的应用程序中与IBM MQ无关的其他部分工作得很好,实际上可能处于处理过程中。因此,我们更愿意只重新创建JMS上下文,相当于重新创建队列连接工厂bean和其他一些依赖于它们的bean(消息侦听器容器、JmsTemplates等(,而不是重新启动整个应用程序上下文。

我找到了这篇关于如何重新初始化弹簧的文章,并尝试实现解决方案2(删除&在注册表中注册bean,但我无法使其工作。

// If I call below:
beanFactory.destroySingleton(qcfName);
var qcf = jmsConfig.connectionFactory();
beanFactory.registerSingleton(qcfName, qcf);
// I get this exception:
Could not register object [org.springframework.cloud.sleuth.instrument.messaging.LazyConnectionFactory@5a0fb814] under bean name 'connectionFactory':
there is already object [org.springframework.cloud.sleuth.instrument.messaging.LazyConnectionFactory@5a0fb814] bound

// If I call below:
beanFactory.destroySingleton(qcfName);
beanFactory.removeBeanDefinition(qcfName);
var qcf = jmsConfig.connectionFactory();
beanFactory.registerSingleton(qcfName, qcf);
// I am getting this exception:
No bean named 'connectionFactory' available

我尝试了一些其他的排列,比如destroyBean,但我无法使它发挥作用。

你知道我做错了什么吗?我该怎么解决?提前感谢您的投入。

我知道你想做什么,所以我测试了几种方法,得到了这个:

@SpringBootApplication
public class DemoApplication implements CommandLineRunner {
@Autowired
AnnotationConfigReactiveWebServerApplicationContext context;
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
context.registerBean("jms", Bean1.class, () -> new Bean1());
var jmsBean1 = context.getBean(Bean1.class);
jmsBean1.hello();
var jmsBean2 = context.getBean(Bean1.class);
context.removeBeanDefinition("jms");
context.registerBean("jms", Bean1.class, () -> new Bean1());
var jmsBean3 = context.getBean(Bean1.class);
System.out.println(jmsBean1.hashCode());
System.out.println(jmsBean2.hashCode());
System.out.println(jmsBean1 == jmsBean2);
System.out.println(jmsBean3.hashCode());
System.out.println(jmsBean1 == jmsBean3);
}
}
class Bean1 {
public void hello() {
System.out.println("hello");
}
}

结果是:

hello
405390165 // jmsBean1 hashcode -> singleton
405390165 //jmsBean2 hashcode -> singleton
true // jmsBean1 == jmsBean2
1182556970 // jmsBean3 hashcode
false // jmsBean3 is different object

正如您所看到的,当您注册新的bean时,默认的bean作用域是singleton
注意:删除bean定义后,由于JVM GC ,尽量不要保留对旧对象的引用

测试日期:弹簧套(v2.6.3(
弹簧框架(5.3.15(

我的测试项目是Reactive Web项目,因为你看到注入了ReactiveApplicationContext,这取决于你的项目,你必须注入你的上下文类型。

最新更新