事件驱动模型开发,当有事件发生时触发事件,通过监听器监听,执行回调方法,完成要实现功能
@org.junit.Test
public void test(){
//创建ioc容器
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfiguration.class);
//创建 ApplicationEvent 事件对象,由于ApplicationEvent是一个抽象类,此处使用匿名类的方法创建
ApplicationEvent event = new ApplicationEvent(new String("aaa")){
};
//通过 IOC 容器对象调用 publishEvent() 发布事件
context.publishEvent(event);
}
创建 IOC 容器时,会自动执行一个创建容器事件,查看源码分析创建容器事件的发布与执行
protected void publishEvent(Object event, ResolvableType eventType) {
Assert.notNull(event, "Event must not be null");
if (this.logger.isTraceEnabled()) {
this.logger.trace("Publishing event in " + this.getDisplayName() + ": " + event);
}
Object applicationEvent;
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent)event;
} else {
applicationEvent = new PayloadApplicationEvent(this, event);
if (eventType == null) {
eventType = ((PayloadApplicationEvent)applicationEvent).getResolvableType();
}
}
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
} else {
//1.调用 getApplicationEventMulticaster() 方法获取一个ApplicationEventMulticaster"多播器"也叫派发器
//2.通过多播器调用 multicastEvent() 方法执行派发事件
this.getApplicationEventMulticaster().multicastEvent((ApplicationEvent)applicationEvent, eventType);
}
if (this.parent != null) {
if (this.parent instanceof AbstractApplicationContext) {
((AbstractApplicationContext)this.parent).publishEvent(event, eventType);
} else {
this.parent.publishEvent(event);
}
}
}
public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
ResolvableType type = eventType != null ? eventType : this.resolveDefaultEventType(event);
//获取所有通过发布的事件对象获取对应的 ApplicationListener 监听器
Iterator var4 = this.getApplicationListeners(event, type).iterator();
//遍历获取到的监听器
while(var4.hasNext()) {
final ApplicationListener<?> listener = (ApplicationListener)var4.next();
Executor executor = this.getTaskExecutor();
//判断是否可以异步执行,如果可以则使用多线程方式进行异步执行
if (executor != null) {
//多线程方式异步执行
executor.execute(new Runnable() {
public void run() {
SimpleApplicationEventMulticaster.this.invokeListener(listener, event);
}
});
} else {
//同步执行
this.invokeListener(listener, event);
}
}
}
同样,例如在调用close() 方法关闭容器时,在该方法中也是调用了publishEvent() 方法,传递了一个关闭事件,获取多播器,通过多播器,找到对象的监听器,执行监听器中的逻辑
发布事件时通过多播器,将事件传递给对应的监听器,进而调用监听器中的方法,实现该事件要完成的功能,我们也可以自定义多播器,指定多播器使用的 Executor,进而实现事件执行的同步或异步功能
多播器的注册过程:
在创建 IOC 容器时 调用 refresh() 方法,该方法中调用了 initApplicationEventMulticaster() 方法,在创建其它 bean 对象之前通过该方法初始化 ApplicationEventMulticaster 多播器
查看 initApplicationEventMulticaster() 方法
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();
//1.通过BeanFactory 在IOC 容器中寻找有没有 id 为"applicationEventMulticaster"的bean,这个bean 就是多播器
if (beanFactory.containsLocalBean("applicationEventMulticaster")) {
//如果有,直接通过id 在容器你中获取
this.applicationEventMulticaster = (ApplicationEventMulticaster)beanFactory.getBean("applicationEventMulticaster", ApplicationEventMulticaster.class);
if (this.logger.isDebugEnabled()) {
this.logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
} else {
//如果没有new 一个多播器
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
//将new 出来的多播器注册到容器中
beanFactory.registerSingleton("applicationEventMulticaster", this.applicationEventMulticaster);
if (this.logger.isDebugEnabled()) {
this.logger.debug("Unable to locate ApplicationEventMulticaster with name 'applicationEventMulticaster': using default [" + this.applicationEventMulticaster + "]");
}
}
}
在创建 IOC 容器时 调用 refresh() 方法,方法中调用 this.finishRefresh() 刷新容器发布创建容器事件以前调用了 registerListeners() 方法,注册监听器
查看 registerListeners() 注册监听器的方法
protected void registerListeners() {
//1.获取 ApplicationListener 监听器迭代器(第一次执行时可能没有)
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<ApplicationEvent> 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);
}
}
}
步骤:
代码
1.创建自定义事件
import org.springframework.context.ApplicationEvent;
//自定义事件,继承 ApplicationEvent 接口,事件一般都会传递数据
//在发生事件后,监听器通过事件对象获取要处理的数据,有个带参构造
//通过带参构造传递数据,对属性赋值
public class MyApplicationEvent extends ApplicationEvent {
//这个变量可以看为事件要处理的数据
public Object source;
public MyApplicationEvent(Object source) {
super(source);
this.source = source;
}
@Override
public Object getSource() {
return source;
}
}
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
//不要忘记将自定义监听器注入到容器中
@Component
public class MyApplicationListener <MyApplicationEvent>implements ApplicationListener {
//实现 ApplicationListener 接口,泛型中指定要监控的事件类型
//重写onApplicationEvent()方法编写事件发生后要执行的逻辑
//当向容器中发布事件时,,会触发该方法
@Override
public void onApplicationEvent(ApplicationEvent applicationEvent) {
//获取事件中保存的数据
applicationEvent.getSource();
System.out.println("我是对应 MyApplicationEvent 事件的监听器,执行...");
}
}
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
//不要忘记注入到容器中
@Component
public class PublishEvent implements ApplicationContextAware {
//通过继承 ApplicationContextAware 接口的方式,
//在启动 Spring 时,自动获取Spring创建的IOC容器,赋值给,当前类中的属性
//通过 ApplicationContext 调用 publishEvent() 方法发布事件使用
private ApplicationContext context;
//重写 ApplicationContextAware 接口中的 setApplicationContext() 方法拿到 Spring 自己创建的 IOC 容器
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext;
}
//通过该方法可以触发事件
public void publishTest(){
System.out.println("我被触发,我要发布事件");
//创建事件对象,设置事件数据
MyApplicationEvent event = new MyApplicationEvent(new String("我是事件数据"));
//通过 IOC 容器调用 publishEvent() 方法发布事件
context.publishEvent(event);
}
}
通过方法监听事件示例
//使用注解方式,设置监听事件的方法(该方法的类不要忘记注入到容器中)
@EventListener(classes = {MyApplicationEvent.class})
public void listenerMethod(MyApplicationEvent event){
System.out.println("我是监听方法,监听 MyApplicationEvent 事件");
//获取事件中的数据
System.out.println(event.source);
}
SmartInitializingSingleton 是一个接口,该接口中有一个 afterSingletonsInstantiated() 抽象方法
afterSingletonsInstantiated() 方法在什么时候执行
当创建 IOC 容器时,调用 refresh() 方法,在refresh() 方法中调用 finishBeanFactoryInitialization(beanFactory) 方法,该方法中又调用了preInstantiateSingletons(),实现对单实例 bean 的创建初始化,当所有注意,是所有 bean 创建初始化完成以后,遍历所以bean的名字获取出来,判断这个bean是否是 SmartInitializingSingleton 类型,如果是执行 SmartInitializingSingleton 中的 afterSingletonsInstantiated() 方法
注意点: 是所有 bean 创建初始化完成后,再遍历执行这个 afterSingletonsInstantiated() 方法的
public void preInstantiateSingletons() throws BeansException {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Pre-instantiating singletons in " + this);
}
//==================1.获取所有 bean 的名字===================
List<String> beanNames = new ArrayList(this.beanDefinitionNames);
Iterator var2 = beanNames.iterator();
while(true) {
while(true) {
String beanName;
RootBeanDefinition bd;
//========do while循环,查看下面的条件,判断所有bean是否全部初始化完成===================================
do {
do {
do {
if (!var2.hasNext()) {
var2 = beanNames.iterator();
//=========2.遍历获取到的 bean 的名字======================
while(var2.hasNext()) {
beanName = (String)var2.next();
//=======3.通过获取到额benaName,去容器中查找这个bean=================
Object singletonInstance = this.getSingleton(beanName);
//=====4.判断这个bean是否是SmartInitializingSingleton类型====================
if (singletonInstance instanceof SmartInitializingSingleton) {
//===========5.如果是转换回来=====================
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton)singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
smartSingleton.afterSingletonsInstantiated();
return null;
}
}, this.getAccessControlContext());
} else {
//6.=======执行afterSingletonsInstantiated ()方法===================
smartSingleton.afterSingletonsInstantiated();
}
}
}
return;
}
beanName = (String)var2.next();
bd = this.getMergedLocalBeanDefinition(beanName);
} while(bd.isAbstract());
} while(!bd.isSingleton());
//========判断所有bean是否全部初始化完成===================================
} while(bd.isLazyInit());
if (this.isFactoryBean(beanName)) {
final FactoryBean<?> factory = (FactoryBean)this.getBean("&" + beanName);
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = (Boolean)AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
public Boolean run() {
return ((SmartFactoryBean)factory).isEagerInit();
}
}, this.getAccessControlContext());
} else {
isEagerInit = factory instanceof SmartFactoryBean && ((SmartFactoryBean)factory).isEagerInit();
}
if (isEagerInit) {
this.getBean(beanName);
}
} else {
//=在Spring容器首次启动时,前面的都没有,会首先走这里创建所有的bean,初始化============
this.getBean(beanName);
}
}
}
}
@EventListener 注解设置监听方法,底层就是通过这个接口,对该接口中的方法在 EventListenerMethodProcessor 子类中进行了实现