spring事件机制-onApplicationEvent执行两次
一、case复现
事件定义
public class MyEvent extends ApplicationEvent { public MyEvent(Object object) { super(object); } }
监听定义
@Component public class MyListener implements ApplicationListener<MyEvent> { @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> T getBean(String beanName, Class<T> 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的applicationContext.xml的父容器和springMVC的applicationContext-mvc.xml的子容器。
在通过applicationContext发送通知的时候,事件会被两个容器发布,造成上述情况。
四、解决方案
知道了原因,解决方案就比较简单了,看了网上大多数的方案都是
@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的问题,多大家有更好更多的方案,希望留言一起学习
相关推荐
yupi0 2020-10-10
spring 2020-08-18
编程点滴 2020-07-29
幸运小侯子 2020-07-05
itjavashuai 2020-07-04
qingjiuquan 2020-06-29
shushan 2020-06-25
小鱿鱼 2020-06-22
咻pur慢 2020-06-18
melonjj 2020-06-17
qingjiuquan 2020-06-13
neweastsun 2020-06-05
小鱿鱼 2020-06-05
mxcsdn 2020-05-31
吾日五省我身 2020-05-27
牧场SZShepherd 2020-05-27
sweetgirl0 2020-05-14