Springイベントメカニズム-onApplicationEventは2回実行
詳細
一、case再現
イベント定義
リスニング定義
イベント通知
テスト結果:
三、原因
WebプロジェクトでspringとspringMVCを同時に統合すると、コンテキストにはspringのアプリケーションContextという2つのコンテナが存在する.xmlの親コンテナとspringMVCのアプリケーションContext-mvc.xmlのサブコンテナ.
アプリケーションContextで通知を送信すると、イベントは2つのコンテナでパブリッシュされ、このような状況になります.
四、解決方案
原因を知って、解決策は比較的に簡単で、ネット上の大多数の方案を見てすべて
しかし,このシナリオはまずイベントのタイプを決め,カスタムイベントは通用しないため,ソリューションの構想は親コンテナで通知を送信することである.
テスト結果:
これで、このcaseの問題を解決して、多くのみんなはもっと多くの方案があって、伝言を残して一緒に勉強することを望みます
一、case再現
イベント定義
public class MyEvent extends ApplicationEvent {
public MyEvent(Object object) {
super(object);
}
}
リスニング定義
@Component
public class MyListener implements ApplicationListener {
@Override
public void onApplicationEvent(MyEvent event) {
System.out.println("myEvent occured msg : " + event.getSource());
}
}
イベント通知
@ResponseBody
@RequestMapping(value = "/publish")
public String publish(String key) {
BeanFactory.pushEvent(new MyEvent("publish"));
return "success";
}
@Component
public class BeanFactory implements ApplicationContextAware {
private static ApplicationContext applicationContext;
public static T getBean(String beanName, Class clazz) {
return (T) applicationContext.getBean(beanName);
}
/**
*
*
* @param applicationEvent
*/
public static void pushEvent(ApplicationEvent applicationEvent) {
//
//ContextLoader.getCurrentWebApplicationContext().publishEvent(applicationEvent);
applicationContext.publishEvent(applicationEvent);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
}
テスト結果:
myEvent occured msg : publish
myEvent occured msg : publish
三、原因
WebプロジェクトでspringとspringMVCを同時に統合すると、コンテキストにはspringのアプリケーションContextという2つのコンテナが存在する.xmlの親コンテナとspringMVCのアプリケーションContext-mvc.xmlのサブコンテナ.
アプリケーションContextで通知を送信すると、イベントは2つのコンテナでパブリッシュされ、このような状況になります.
四、解決方案
原因を知って、解決策は比較的に簡単で、ネット上の大多数の方案を見てすべて
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
if(event.getApplicationContext().getParent() == null){
// , spring 。
}
}
しかし,このシナリオはまずイベントのタイプを決め,カスタムイベントは通用しないため,ソリューションの構想は親コンテナで通知を送信することである.
/**
*
*
* @param applicationEvent
*/
public static void pushEvent(ApplicationEvent applicationEvent) {
//
ContextLoader.getCurrentWebApplicationContext().publishEvent(applicationEvent);
}
テスト結果:
myEvent occured msg : publish
これで、このcaseの問題を解決して、多くのみんなはもっと多くの方案があって、伝言を残して一緒に勉強することを望みます