How to use the Spring Application Listener
To set the application to use Spring Application listener, you can do the following.
1. In the application context file for Spring, declare a bean as follows
<bean id="applicationEventMulticaster" class="org.springframework.context.event.SimpleApplicationEventMulticaster"/>Actually, this may not needed at all. The following method is from Spring. By default, it will create a SimpleApplicationEventMulticaster if none is given.
package org.springframework.context.support; public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext, DisposableBean { /** * Initialize the ApplicationEventMulticaster. * Uses SimpleApplicationEventMulticaster if none defined in the context. * @see org.springframework.context.event.SimpleApplicationEventMulticaster */ protected void initApplicationEventMulticaster() { ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) { this.applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class); if (logger.isDebugEnabled()) { logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]"); } } else { this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory); beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster); if (logger.isDebugEnabled()) { logger.debug("Unable to locate ApplicationEventMulticaster with name '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "': using default [" + this.applicationEventMulticaster + "]"); } } } ... }
2. Create Application listeners
import org.springframework.context.ApplicationListener; @Component public class MyEventListener implements ApplicationListener{ ... } import org.springframework.context.ApplicationEvent; public class MyEvent extends ApplicationEvent { ... }
3. Just call the multicastEvent method of the bean applicationEventMulticaster when needed: applicationEventMulticaster.multicastEvent(event);
The method will invoke the application listeners to act on the event.
public void multicastEvent(final ApplicationEvent event) { for (final ApplicationListener listener : getApplicationListeners(event)) { Executor executor = getTaskExecutor(); if (executor != null) { executor.execute(new Runnable() { @SuppressWarnings("unchecked") public void run() { listener.onApplicationEvent(event); } }); } else { listener.onApplicationEvent(event); } } }
How does the Application know what application listeners are listening?
At the application startup, the beans that implement the ApplicationListener interface will be automatically detected and registered.
ContextLoaderListener(ContextLoader).initWebApplicationContext(ServletContext) -> XmlWebApplicationContext(AbstractApplicationContext).refresh(); -> DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory). applyBeanPostProcessorsAfterIniitalization -> AbstractApplicationContext$ApplicationListenerDetector.postProcessAfterInitialization public Object postProcessAfterInitialization(Object bean, String beanName) { if (bean instanceof ApplicationListener) { // potentially not detected as a listener by getBeanNamesForType retrieval Boolean flag = this.singletonNames.get(beanName); if (Boolean.TRUE.equals(flag)) { // singleton bean (top-level or inner): register on the fly addApplicationListener((ApplicationListener) bean); } else if (flag == null) { if (logger.isWarnEnabled() && !containsBean(beanName)) { // inner bean with other scope - can't reliably process events logger.warn("Inner bean '" + beanName + "' implements ApplicationListener interface " + "but is not reachable for event multicasting by its containing ApplicationContext " + "because it does not have singleton scope. Only top-level listener beans are allowed " + "to be of non-singleton scope."); } this.singletonNames.put(beanName, Boolean.FALSE); } } return bean; } public void addApplicationListener(ApplicationListener listener) { if (this.applicationEventMulticaster != null) { this.applicationEventMulticaster.addApplicationListener(listener); } else { this.applicationListeners.add(listener); } }
No comments:
Post a Comment