ApplicationListeners will only be executed once per event (even for scripted objects; SPR-6589)

This commit is contained in:
Juergen Hoeller 2010-01-07 12:58:18 +00:00
parent 8bda9cd2bf
commit 8af7f27942
3 changed files with 27 additions and 3 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2009 the original author or authors. * Copyright 2002-2010 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -146,7 +146,7 @@ public abstract class AbstractApplicationEventMulticaster implements Application
BeanFactory beanFactory = getBeanFactory(); BeanFactory beanFactory = getBeanFactory();
for (String listenerBeanName : this.defaultRetriever.applicationListenerBeans) { for (String listenerBeanName : this.defaultRetriever.applicationListenerBeans) {
ApplicationListener listener = beanFactory.getBean(listenerBeanName, ApplicationListener.class); ApplicationListener listener = beanFactory.getBean(listenerBeanName, ApplicationListener.class);
if (supportsEvent(listener, eventType, sourceType)) { if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) {
retriever.applicationListenerBeans.add(listenerBeanName); retriever.applicationListenerBeans.add(listenerBeanName);
allListeners.add(listener); allListeners.add(listener);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2007 the original author or authors. * Copyright 2002-2010 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -26,6 +26,7 @@ import org.springframework.aop.support.AopUtils;
import org.springframework.aop.target.dynamic.Refreshable; import org.springframework.aop.target.dynamic.Refreshable;
import org.springframework.beans.TestBean; import org.springframework.beans.TestBean;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.NestedRuntimeException; import org.springframework.core.NestedRuntimeException;
import org.springframework.scripting.Calculator; import org.springframework.scripting.Calculator;
@ -303,4 +304,19 @@ public class BshScriptFactoryTests extends TestCase {
assertTrue("Messenger should be Refreshable", messenger instanceof Refreshable); assertTrue("Messenger should be Refreshable", messenger instanceof Refreshable);
} }
public void testApplicationEventListener() throws Exception {
ApplicationContext ctx = new ClassPathXmlApplicationContext("bsh-with-xsd.xml", getClass());
Messenger eventListener = (Messenger) ctx.getBean("eventListener");
ctx.publishEvent(new MyEvent(ctx));
assertEquals("count=2", eventListener.getMessage());
}
private static class MyEvent extends ApplicationEvent {
public MyEvent(Object source) {
super(source);
}
}
} }

View File

@ -52,4 +52,12 @@
<lang:property name="message" value="Hello World!"/> <lang:property name="message" value="Hello World!"/>
</lang:bsh> </lang:bsh>
<lang:bsh id="eventListener" script-interfaces="org.springframework.context.ApplicationListener,org.springframework.scripting.Messenger" >
<lang:inline-script><![CDATA[
int count;
void onApplicationEvent (org.springframework.context.ApplicationEvent event) { count++; System.out.println(event); }
String getMessage() { return "count=" + count; }
]]></lang:inline-script>
</lang:bsh>
</beans> </beans>