Spring源码解析-事件

时间:2023-03-09 19:58:10
Spring源码解析-事件

Spring事件的组件

主要是3个组件:

1.ApplicationEvent   事件

2.ApplicationListener 监听器,对事件进行监听

3.ApplicationEventMulticaster 事件广播器,将publish的事件广播给所有的监听器。

事件

Spring源码解析-事件

ContextRefreshedEvent :当ApplicationContext初始化或者刷新,将会发布,例如使用ConfigurableApplicationContext接口调用refresh方法,初始化意味着加载所有的bean,同时

ApplicationContext是支持热刷新。

ContextStartedEvent:当ApplicationContext启动的时候,将会调用start方法,发布此事件。

ContextStoppedEvent:当容器停止的时候,发布事件。

ContextClosedEvent:当容器关闭的时候,发布事件。

RequestHandledEvent:http请求完成后,发布事件。

监听器

ApplicationListener:ApplicationContext容器内部自定义事件监听器接口,继承自java.util.EventListener,ApplicationContext容器在启动时,会自动识别并加载EventListener类型bean的定义,一旦容器事件发布,将会通知注册到容器的监听器。

Spring源码解析-事件

public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {

	/**
* Handle an application event.
* @param event the event to respond to
*/
void onApplicationEvent(E event); }

发布事件者

ApplicationEventPublisher和ApplicationEventMulticaster
ApplicationEventPublisher:是一个封装事件发布接口,作为ApplicationContext父类接口。
ApplicationEventMulticaster:管理ApplicationListener对象,并且发布它们。

Spring源码解析-事件                             Spring源码解析-事件

ApplicationContext继承ApplicationEventPublisher而担当者事件发布的角色,而ApplicationContext并没有进行事件的发布,而是交给了AbstractApplicationEventMulticaster来实现事件监听器的管理。

简单实例

模拟人民银行利息调整,通知到其他银行的事件。

Spring源码解析-事件

利息事件

package org.lzyer.test;

import org.springframework.context.ApplicationEvent;

/**
* Created by Administrator on 2017/10/23.
*/
public class ExRateChangeEvent extends ApplicationEvent {
/**
* Create a new ApplicationEvent.
*
* @param source the component that published the event (never {@code null})
*/
public ExRateChangeEvent(Object source) {
super(source);
}
}

农业银行监听器

package org.lzyer.test;

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component; /**
* Created by Administrator on 2017/10/23.
*/
@Component
public class ABCListener implements ApplicationListener<ApplicationEvent> {
@Override
public void onApplicationEvent(ApplicationEvent event) {
if(event instanceof ExRateChangeEvent){
System.out.println("农业银行收到->"+event.getSource());
}
}
}

工商银行监听器

package org.lzyer.test;

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component; /**
* Created by Administrator on 2017/10/23.
*/
@Component
public class ICBCListener implements ApplicationListener<ApplicationEvent> { @Override
public void onApplicationEvent(ApplicationEvent event) {
if(event instanceof ExRateChangeEvent){
System.out.println("工商银行收到->"+event.getSource());
}
}
}

spring-beans.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="org.lzyer.test"></context:component-scan>
</beans>

测试代码

@Test
public void testPublishEvent(){
ApplicationContext context = new ClassPathXmlApplicationContext("spring/spring-beans.xml");
context.publishEvent(new ExRateChangeEvent("利息上调"));
}

结果:

农业银行收到->利息上调
工商银行收到:->利息上调

事件原理流程

spring容器初始化调用的refresh方法

AbstractApplicationContext@refresh

@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
//省略 try {
//省略 // 初始化广播事件
initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses.
onRefresh();
//注册监听器
// Check for listener beans and register them.
registerListeners(); // Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event.
finishRefresh();
} catch (BeansException ex) {
//省略
}
}
}

initApplicationEventMulticaster()注册广播事件

protected void initApplicationEventMulticaster() {
//获取beanFactory
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isDebugEnabled()) {
logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
else {//创建一个默认的事件广播器
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
if (logger.isDebugEnabled()) {
logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
"': using default [" + this.applicationEventMulticaster + "]");
}
}
}
AbstractApplicationEventMulticaster类中的属性

Spring源码解析-事件

Spring源码解析-事件

registerListeners方法
/**
* Add beans that implement ApplicationListener as listeners.
* Doesn't affect other listeners, which can be added without being beans.
*/
protected void registerListeners() {
// Register statically specified listeners first.
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let post-processors apply to them!
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String lisName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(lisName);
}
}

在refresh最后的一个方法,中发布刷新事件。

finishRefresh
protected void finishRefresh() {
// Initialize lifecycle processor for this context.
initLifecycleProcessor(); // Propagate refresh to lifecycle processor first.
getLifecycleProcessor().onRefresh(); // Publish the final event.发布刷新事件
publishEvent(new ContextRefreshedEvent(this)); // Participate in LiveBeansView MBean, if active.
LiveBeansView.registerApplicationContext(this);
}

事件整体结构图

Spring源码解析-事件

最后走一波debug

Spring源码解析-事件

Spring源码解析-事件

Spring源码解析-事件

Spring源码解析-事件

Spring源码解析-事件

 

参考资料
http://www.jianshu.com/p/bc1055b065ce
http://liuxiamai.iteye.com/blog/2322197
http://jinnianshilongnian.iteye.com/blog/1902886