ApplicationListener:应用监听器,是一个抽象类,spring提供的基于事件驱动开发的功能,通过监听容器中发布的一些事件,事件发生则触发监听器的回调来完成事件驱动模型开发
@Component
public class MyApplicationListener implements ApplicationListener<ApplicationEvent>{
@Override
public void onApplicationEvent(ApplicationEvent event) {
System.out.println("发布事件触发");//当容器发布事件以后就会触发
}
}
在容器刷新完成和容器关闭时都会触发onApplicationEvent方法,这是为何呢?因为ApplicationContext默认发布了这两个事件,那怎么自己发布事件呢?
@Test
public void test(){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ExtConfig.class);
context.publishEvent(new ApplicationEvent(new String("abc")){
private static final long serialVersionUID = 1L;
});
context.close();
}
步骤:
1)、写一个监听器(ApplicationListener实现类)来监听某个事件(ApplicationEvent及其子类)
2)、把监听器加入到容器
3)、只要容器中有相关事件的发布,我们就能监听到这个事件
ContextRefreshedEvent:容器刷新完成(所有bean都完全创建)会发布这个事件
ContextClosedEvent:关闭容器会发布这个事件
4)、自定义发布一个事件:
applicationContext.publishEvent();
原理:
发布的事件:ContextRefreshedEvent、IOCTest_Ext$1[source=我发布的事件]、ContextClosedEvent
1)、ContextRefreshedEvent事件:
①容器创建对象:refresh();
②refresh();快要结束的时候执行finishRefresh();容器刷新完成会发布ContextRefreshedEvent事件
2)、自己发布事件
3)、context.close();容器关闭会发布ContextClosedEvent
【事件发布流程】:publishEvent(new ContextRefreshedEvent(this))
1)、获取事件的多播器(派发器):getApplicationEventMulticaster()
2)、multicastEvent派发事件:
3)、获取到所有的ApplicationListener;
for (final ApplicationListener<?> listener : getApplicationListeners(event, type))
1)、如果有Executor,可以支持使用Executor进行异步派发;
Executor executor = getTaskExecutor();
2)、否则,同步的方式直接执行listener方法;invokeListener(listener, event);拿到listener回调onApplicationEvent方法
【事件多播器(派发器)】
1)、容器创建对象:refresh();
2)、initApplicationEventMulticaster();初始化ApplicationEventMulticaster;
1)、先去容器中找有没有id=“applicationEventMulticaster”的组件;
2)、如果没有this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);并且加入到容器中,我们就可以在其他组件需要派发事件时,自动注入这个applicationEventMulticaster;
【容器中有哪些监听器】
1)、容器创建对象:refresh();
2)、registerListeners();
从容器中拿到所有的监听器,把他们注册到applicationEventMulticaster中;
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
//将listener注册到ApplicationEventMulticaster中
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
实现事件监听的另一种方式:@EventListener
@Component
public class AnnotationListener {
@EventListener(classes={ApplicationEvent.class})
public void eventListen(ApplicationEvent event){
System.out.println("监听到事件:" + event);
}
}
事件的监听有什么用处呢?看一个例子:
①自定义事件:注意若在该类上加@Component等注解,需将构造器的入参改为具体类型或者指定入参的id,否则会报错,因为其只有有参构造器,在不修改构造器入参的情况下容器创建其实例的时候需要传一个Object对象,而容器中所有的实例都是Object类型的,就会导致找到很多个实体引起冲突
public class MyApplicationEvent extends ApplicationEvent {
private static final long serialVersionUID = 1L;
public MyApplicationEvent(Object source) {
super(source);
System.out.println("自定义事件:" + source);
}
}
②自定义监听器:监听自定义的事件
@Component
public class AnnotationListener {
@EventListener(classes={MyApplicationEvent.class})
public void eventListen(ApplicationEvent event){
System.out.println("监听到自定义事件发布:" + event);
}
}
③发布事件:
@Test
public void test() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ExtConfig.class);
context.publishEvent(new MyApplicationEvent("hello"));
context.close();
}
那么发布的所有MyApplicationEvent类型的事件都会被AnnotationListener的eventListener方法监听到。那么就可以使用ApplicationLisener来监听一些状态变化,比如文件传送状态、接口回调状态等,在需要监听事件状态变化的地方都需要发布事件(个人理解)
原理:使用EventListenerMethodProcessor处理器来解析方法上的@EventListener,EventListenerMethodProcessor实现了SmartInitializingSingleton接口
SmartInitializingSingleton原理:->afterSingletonsInstantiated();
1)、ioc容器创建对象并refresh();
2)、finishBeanFactoryInitialization(beanFactory);初始化剩下的单实例bean;
1)、先创建所有的单实例bean;getBean();
2)、获取所有创建好的单实例bean,判断是否是SmartInitializingSingleton类型的;
如果是就调用afterSingletonsInstantiated();