我們有一個 Spring 應用程式負責執行一些預計將 24 x 7 全天候運行的集成作業。
我們使用的一種集成模式是使用一組集群的 IBM MQ 佇列管理器的 JMS 訊息傳遞。使用集群的 IBM MQ 佇列管理器,如果其中一個佇列管理器出現故障,您需要重新實體化佇列連接工廠 bean,以便連接能夠與仍然運行的其余佇列管理器一起作業。
我們進行了 JMS 健康檢查,IBM MQ 佇列管理器的狀態發生了變化,我們以編程方式重新啟動 spring 背景關系,結果佇列連接工廠 bean 被重新創建,一切正常。
然而,這對我們來說并不理想,因為與 IBM MQ 無關的應用程式的其他部分作業得很好,實際上可以在處理東西的中間。因此,我們寧愿只重新創建 JMS 背景關系,幾乎重新創建佇列連接工廠 bean 和一些其他依賴于這些的 bean(訊息偵聽器容器、JmsTemplats 等),而不是重新啟動整個應用程式背景關系。
我發現這篇文章how-to-reinitialize-a-spring-bean并嘗試實施解決方案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但我無法讓它作業。
知道我做錯了什么以及我應該如何解決它?預先感謝您的意見。
uj5u.com熱心網友回復:
我了解您要做什么,所以我測驗了幾種方法并得到了這個:
@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 范圍是單例的。
注意:洗掉 bean 定義后盡量不要保留對舊物件的參考,因為 JVM GC
測驗:Spring boot (v2.6.3)
spring framework (5.3.15)
My test project was Reactive Web project because of that you saw ReacttiveApplicationContext injected, depends on your project you have to inject your context type.
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/426031.html
