在这次度量指标的项目中,用到了spring的listener的加载过程。在这里总结一下:
之前找实习的时候阅读过spring的源码,了解了一下spring的加载流程。
ApplicationContext ac = new ClassPathXmlApplicationContext(“applicationContext.xml”);
debug的时候对refresh()进入。
public void refresh() throws BeansException, IllegalStateException {
Object var1 = this.startupShutdownMonitor;
synchronized(this.startupShutdownMonitor) {
//容器刷新前的准备,设置上下文状态,获取属性,验证必要的属性等
this.prepareRefresh();
//获取新的beanFactory,销毁原有beanFactory、为每个bean生成BeanDefinition等
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
this.prepareBeanFactory(beanFactory);
try {
//配置标准的beanFactory,设置ClassLoader,设置SpEL表达式解析器,添加忽略注入的接口,添加bean,添加bean后置处理器等
this.postProcessBeanFactory(beanFactory);
//模板方法,此时,所有的beanDefinition已经加载,但是还没有实例化。
//允许在子类中对beanFactory进行扩展处理。比如添加ware相关接口自动装配设置,添加后置处理器等,是子类扩展
//prepareBeanFactory(beanFactory)的方法。
// 实例化并调用所有注册的beanFactory后置处理器(实现接口BeanFactoryPostProcessor的bean,在beanFactory标准初始化之后执行)。
this.invokeBeanFactoryPostProcessors(beanFactory);
//实例化和注册beanFactory中扩展了BeanPostProcessor的bean。
this.registerBeanPostProcessors(beanFactory);
//初始化国际化工具类MessageSource
this.initMessageSource();
//初始化事件广播器
this.initApplicationEventMulticaster();
//模板方法,在容器刷新的时候可以自定义逻辑,不同的Spring容器做不同的事情。
this.onRefresh();
//注册监听器,广播early application events
this.registerListeners();
//实例化所有剩余的(非懒加载)单例
//实例化的过程各种BeanPostProcessor开始起作用。
this.finishBeanFactoryInitialization(beanFactory);
//refresh做完之后需要做的其他事情。
//清除上下文资源缓存(如扫描中的ASM元数据)
//初始化上下文的生命周期处理器,并刷新(找出Spring容器中实现了Lifecycle接口的bean并执行start()方法)。
//发布ContextRefreshedEvent事件告知对应的ApplicationListener进行响应的操作
this.finishRefresh();
} catch (BeansException var9) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
}
this.destroyBeans();
this.cancelRefresh(var9);
throw var9;
} finally {
this.resetCommonCaches();
}
}
}
在上面代码的第27行,是this.registerListeners();注册监听器,代码如下:
protected void registerListeners() {
Iterator var1 = this.getApplicationListeners().iterator();
while(var1.hasNext()) {
ApplicationListener<?> listener = (ApplicationListener)var1.next();
this.getApplicationEventMulticaster().addApplicationListener(listener);
}
String[] listenerBeanNames = this.getBeanNamesForType(ApplicationListener.class, true, false);
String[] var7 = listenerBeanNames;
int var3 = listenerBeanNames.length;
for(int var4 = 0; var4 < var3; ++var4) {
String listenerBeanName = var7[var4];
this.getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
Set earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
Iterator var9 = earlyEventsToProcess.iterator();
while(var9.hasNext()) {
ApplicationEvent earlyEvent = (ApplicationEvent)var9.next();
this.getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
从容器中拿到所有的监听器,把他们注册到applicationEventMulticaster中(多播器(派发器))。
自定义listener步骤:
(1)写一个监听器(ApplicationListener实现类)来监听某个事件(ApplicationEvent及其子类)
@EventListener;原理:使用EventListenerMethodProcessor处理器来解析方法上的@EventListener;
(2)spring启动会把监听器加入到容器;
(3)只要容器中有相关事件的发布,我们就能监听到这个事件;
比如: ContextRefreshedEvent:容器刷新完成(所有bean都完全创建)会发布这个事件; ContextClosedEvent:关闭容器会发布这个事件;
(4)发布一个事件:applicationContext.publishEvent(),执行监听器的onApplicationEvent方法。
总结:
(1)Spring中的事件是一个 ApplicationEvent类的子类,由实现 ApplicationEventPublisherAware 接口的类发送,实现 ApplicationListener 接口的类监听。
(2)Spring中已经定义了一组内置事件,这些事件由ApplicationContext容器发出。(ContextRefreshedEvent、ContextStartedEvent、ContextStoppedEvent、ContextClosedEvent、RequestHandledEvent)
(3)要监听ApplicationContext事件,监听类应该实现ApplicationListener接口并重写onApplicationEvent()方法。
附:spring内置事件:
(1)ContextRefreshedEvent
ApplicationContext 被初始化或刷新时,该事件被发布。这也可以在 ConfigurableApplicationContext接口中使用 refresh() 方法来发生。此处的初始化是指:所有的Bean被成功装载,后处理Bean被检测并激活,所有Singleton Bean 被预实例化,ApplicationContext容器已就绪可用。
(2)ContextStartedEvent
当使用 ConfigurableApplicationContext (ApplicationContext子接口)接口中的 start() 方法启动 ApplicationContext 时,该事件被发布。你可以调查你的数据库,或者你可以在接受到这个事件后重启任何停止的应用程序。
(3)ContextStoppedEvent
当使用 ConfigurableApplicationContext 接口中的 stop() 停止 ApplicationContext 时,发布这个事件。你可以在接受到这个事件后做必要的清理的工作。
(4)ContextClosedEvent
当使用 ConfigurableApplicationContext 接口中的 close() 方法关闭 ApplicationContext 时,该事件被发布。一个已关闭的上下文到达生命周期末端;它不能被刷新或重启。
(5)RequestHandledEvent
这是一个 web-specific 事件,告诉所有 bean HTTP 请求已经被服务。只能应用于使用DispatcherServlet的Web应用。在使用Spring作为前端的MVC控制器时,当Spring处理用户请求结束后,系统会自动触发该事件。
Spring的监听器
最新推荐文章于 2024-03-27 15:49:23 发布