自定义一个实现ApplicationListener接口的类:
@Component
public class MyApplicationListener implements ApplicationListener {@Overridepublic void onApplicationEvent(MyApplicationEvent event) {System.out.println("我是测试监听器的类方法:"+event.getSource());}
}
这里使用了@Component注解,此注解下节分析;
然后再自定义一个触发事件:
public class MyApplicationEvent extends ApplicationEvent {public MyApplicationEvent(Object source) {super(source);}
}
要达到的效果就是,当请求发布的事件是MyApplicationEvent事件的时候,就需要调用自定义的监听器;
执行结果:
可以看到执行的结果就是想要的结果。那么代码是如何实现这一点的呢?
这里只看关键代码,首先要找到AbstractApplicationContext#refresh的方法,其中最后第二步实例化方法是finishBeanFactoryInitialization(beanFactory)方法,它是通过getBean(beanName)来实例化剩余的单利的;
在此过程中,会调用如下方法:
@Overridepublic Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)throws BeansException {Object result = existingBean;for (BeanPostProcessor processor : getBeanPostProcessors()) {Object current = processor.postProcessAfterInitialization(result, beanName);if (current == null) {return result;}result = current;}return result;}
看方法名称可知,其实初始化后应用bean的后置处理器的方法;
即调用了ApplicationListenerDetector的BeanPostProcessor的后置处理器,它实现了MergedBeanDefinitionPostProcessor接口,
注(在此之前已经执行):
所以在这之前,它会在doCreateBean的实例化之后调用其后置处理器的postProcessMergedBeanDefinition()方法,此处是将自定义的监听器添加到singletonNames中。
然后接着上面继续,它后置方法postProcessAfterInitialization():
@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) {if (bean instanceof ApplicationListener) {// potentially not detected as a listener by getBeanNamesForType retrievalBoolean flag = this.singletonNames.get(beanName);if (Boolean.TRUE.equals(flag)) {// singleton bean (top-level or inner): register on the flythis.applicationContext.addApplicationListener((ApplicationListener>) bean);}else if (Boolean.FALSE.equals(flag)) {if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) {// inner bean with other scope - can't reliably process eventslogger.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.remove(beanName);}}return bean;}
此时,先判断了一下对象是否是ApplicationListener类型,如果是,则添加到this.defaultRetriever.applicationListeners变量中,取值的时候,则会根据具体的类型进行判断
for (ApplicationListener> listener : listeners) {if (supportsEvent(listener, eventType, sourceType)) {if (retriever != null) {filteredListeners.add(listener);}allListeners.add(listener);}}
此时,就会将根据事件类型,添加相应的监听器,然后调用对应的onApplicationEvent方法。
当然,此处也可以使用spi的形式注入或者@Bean的形式都可以;
监听器可以实现线程上下文的的热更新等功能。