理解Spring
ApplicationListener
和源码
参考:https://blog.csdn.net/liyantianmin/article/details/81017960
一、是什么?
ApplicationContext事件机制是观察者设计模式的实现,通过ApplicationEvent类和ApplicationListener接口,可以实现ApplicationContext事件处理。
如果容器中有一个ApplicationListener Bean,每当ApplicationContext发布ApplicationEvent时,ApplicationListener Bean将自动被触发。这种事件机制都必须需要程序显示的触发。
二、有什么
其中spring有一些内置的事件,当完成某种操作时会发出某些事件动作。比如监听ContextRefreshedEvent事件,当所有的bean都初始化完成并被成功装载后会触发该事件,实现ApplicationListener接口可以收到监听动作,然后可以写自己的逻辑。
同样事件可以自定义、监听也可以自定义,完全根据自己的业务逻辑来处理。
2.1 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处理用户请求结束后,系统会自动触发该事件。
三、干什么?
3.1 自定义事件和监听,并触发
自定义事件
@Component
public class DIYEvent extends ApplicationContextEvent {
/**
* Create a new ContextStartedEvent.
*
* @param source the {@code ApplicationContext} that the event is raised for
* (must not be {@code null})
*/
public DIYEvent(ApplicationContext source) {
super(source);
}
}
自定义监听
@Component
public class DIYEventApplicationListenerTest implements ApplicationListener<DIYEvent> {
@Override
public void onApplicationEvent(DIYEvent event) {
System.out.println("触发 DIYEvent, 监听到~~~~");
}
}
触发
@RunWith(SpringRunner.class)
@SpringBootTest
public class DIYEventTest {
@Test
public void test() {
ApplicationContext applicationContext = ApplicationContextHolder.getContext();
DIYEvent diyEvent = (DIYEvent) applicationContext.getBean("DIYEvent");
applicationContext.publishEvent(diyEvent);
}
}
@Component
public class ApplicationContextHolder implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
ApplicationContextHolder.applicationContext = applicationContext;
}
public static ApplicationContext getContext() {
return applicationContext;
}
}
git项目:https://gitee.com/chenershuai/springtest.git
四、源码
这里分析下 ContextRefreshEvent
触发逻辑, Spring
项目启动,初始化容器等,AbstractApplicationContext.registerListeners()
为事件传播器注册事件监听器,AbstractApplicationContext.finishRefresh()
触发事件,之后逻辑如下代码,,
代码中,通过event
类型遍历所有的event,其中通过AnnotationAwareOrderComparator
解析注解@Order
定义 事件激活顺序,最终通过SimpleApplicationEventMulticaster#doInvokeListener
调用真实event onApplicationEvent
方法