目录
二、ApplicationEventMulticaster事件多播器
一、Spring中事件驱动开发,事件监听机制
Spring中是通过ApplicationListener及ApplicationEventMulticaster来进行事件驱动开发的,即实现观察者设计模式或发布-订阅模式;
事件(ApplicationEvent) :负责对应相应监听器,事件源发生某事件是特定事件监听器被触发的原因;
监听器(ApplicationListener) :监听容器中发布的事件,只要事件发生,就会触发监听器的回调,来完成事件驱动开发,属于观察者设计模式中的Observer(观察者)对象;
事件发布器(ApplicationEventMulticaster) :事件发布器可以认为是事件监听的容器,对外提供发布事件和增删事件监听器的接口,维护事件和事件监听器之间的映射关系,并在事件发生时负责通知相关监听器,即通知所有的观察者对象,属于观察者设计模式中的Subject(主题)对象;
二、ApplicationEventMulticaster事件多播器
1. ApplicationEventMulticaster的初始化
事件多播器是在Spring容器启动过程中(refresh()方法中)初始化的,初始化步骤:
① 先去容器中找有没有beanName为"applicationEventMulticaster"的BeanDefination,如果有就使用这一个;
② 如果没有就创建一个,并添加到容器中,默认为SimpleApplicationEventMulticaster;
// Initialize event multicaster for this context.
// 初始化事件多播器,设置ApplicationContext的applicationEventMulticaster,可以是用户设置的,或者是默认的SimpleApplicationEventMulticaster
initApplicationEventMulticaster();
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
/**
* 判断容器中是否存在beanName为applicationEventMulticaster的BeanDefination
* 自定义的事件多路广播器,必须实现ApplicationEventMulticaster接口
*/
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isTraceEnabled()) {
logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
else {
/**
* 如果没有,则默认采用SimpleApplicationEventMulticaster
*/
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
if (logger.isTraceEnabled()) {
logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
"[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
}
}
}
2. SimpleApplicationEventMulticaster类图
AbstractApplicationEventMulticaster的内部类DefaultListenerRetriever中维护了一个Set,
private class DefaultListenerRetriever {
public final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();
public final Set<String> applicationListenerBeans = new LinkedHashSet<>();
public Collection<ApplicationListener<?>> getApplicationListeners() {
List<ApplicationListener<?>> allListeners = new ArrayList<>(
this.applicationListeners.size() + this.applicationListenerBeans.size());
allListeners.addAll(this.applicationListeners);
if (!this.applicationListenerBeans.isEmpty()) {
BeanFactory beanFactory = getBeanFactory();
for (String listenerBeanName : this.applicationListenerBeans) {
try {
ApplicationListener<?> listener =
beanFactory.getBean(listenerBeanName, ApplicationListener.class);
if (!allListeners.contains(listener)) {
allListeners.add(listener);
}
}
catch (NoSuchBeanDefinitionException ex) {
// Singleton listener instance (without backing bean definition) disappeared -
// probably in the middle of the destruction phase
}
}
}
AnnotationAwareOrderComparator.sort(allListeners);
return allListeners;
}
}
三、ApplicationListener监听器注册流程
1. ApplicationListener的注册
注册事件监听器是在事件发布器初始化之后进行的,因为注册事件监听器,其实最终就是将事件监听器添加到事件发布器中,所以事件发布器要先于事件监听器初始化,事件监听器注册步骤如下:
protected void registerListeners() {
// Register statically specified listeners first.
//getApplicationListeners()获取的是通过context.addApplicationListener(new MyApplicationListener())添加的ApplicationListener
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!
//获取beanFactory中所有ApplicationListener类型的listenerBeanName,到此时Spring实例化bean的步骤还没有执行,所以将listenerBeanName添加到事件发布器中
//这里获得的listenerBeanNames不包括上面getApplicationListeners()方法获得的ApplicationListener
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
//将事件监听器添加到事件发布器中(事件发布器可以认为是事件监听的容器,事件发布器中会存放事件监听器)
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// Publish early application events now that we finally have a multicaster...
// 添加了事件监听器后,判断是否有earlyApplicationEvents,如果有就使用事件广播器发布earlyApplicationEvents
// earlyApplicationEvents表示在事件广播器还没生成好之前ApplicationContext所发布的事件
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
四、创建Listener的方式
创建Listener的方式有两种:
方式1:编程实现ApplicationListener接口
方式2:使用@EventListener注解
1. 编程实现ApplicationListener接口
1.1. 实现 public interface ApplicationListener<E extends ApplicationEvent> 接口,监听 ApplicationEvent 及其下面的子事件:
/**
* 事件监听器一般是由开发者自己定义
* 定义事件监听器
*/
@Component
//@Lazy
public class MyApplicationListener implements ApplicationListener{
@Override
public void onApplicationEvent(ApplicationEvent event) {
event = (PayloadApplicationEvent)event;
System.out.println(((PayloadApplicationEvent<?>) event).getPayload());
}
}
1.2. 关于ApplicationListenerDetector
Spring是怎么识别我们自定义的bean是不是监听器呢?就是通过ApplicationListenerDetector,
ApplicationListenerDetector是一个BeanPostProcessor,在初始化后会执行postProcessAfterInitialization()方法,如果当前bean是ApplicationListener类型,将其添加到applicationContext的applicationListeners中(注意:这里并不是直接添加到事件发布器中);
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
/**
* 会先判断bean是否是ApplicationListener类型
* 如果是通过@EventListener来声明的事件监听器,那不会进入到这个if
* 只有通过实现ApplicationListener接口这种方式的事件监听器会进入到if执行
*/
if (bean instanceof ApplicationListener) {
// potentially not detected as a listener by getBeanNamesForType retrieval
Boolean flag = this.singletonNames.get(beanName);
if (Boolean.TRUE.equals(flag)) {
// singleton bean (top-level or inner): register on the fly
this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);
}
else if (Boolean.FALSE.equals(flag)) {
if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) {
// inner bean with other scope - can't reliably process events
logger.warn("Inner bean '" + beanName + "' implements ApplicationListener interface " +
"but is not reachable for event multicasting by its containing ApplicationContext " +
"because it does not have singleton scope. Only top-level listener beans are allowed " +
"to be of non-singleton scope.");
}
this.singletonNames.remove(beanName);
}
}
return bean;
}
/** Statically specified listeners. */
private final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();
2. 使用@EventListener注解
2.1. 通过EventListenerMethodProcessor处理器来解析@EventListener注解
@EventListener注解使用示例:
@Component
public class UserService {
/**
* 定义事件监听器
*/
@EventListener
public void eventMethod(ApplicationEvent event){
System.out.println(event);
}
}
原理:EventListenerMethodProcessor实现了SmartInitializingSingleton接口的afterSingletonsInstantiated()方法,在该方法中会筛选出每个bean中所有加了@EventListener注解的方法,并通过EventListenerFactory将其注册为一个ApplicationListener的instance,解析如下:
private void processBean(final String beanName, final Class<?> targetType) {
if (!this.nonAnnotatedClasses.contains(targetType) &&
AnnotationUtils.isCandidateClass(targetType, EventListener.class) &&
!isSpringContainerClass(targetType)) {
// 找到所有加了@EventListener注解的方法
Map<Method, EventListener> annotatedMethods = null;
try {
annotatedMethods = MethodIntrospector.selectMethods(targetType,
(MethodIntrospector.MetadataLookup<EventListener>) method ->
AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class));
}
catch (Throwable ex) {
// An unresolvable type in a method signature, probably from a lazy bean - let's ignore it.
if (logger.isDebugEnabled()) {
logger.debug("Could not resolve methods for bean with name '" + beanName + "'", ex);
}
}
if (CollectionUtils.isEmpty(annotatedMethods)) {
this.nonAnnotatedClasses.add(targetType);
if (logger.isTraceEnabled()) {
logger.trace("No @EventListener annotations found on bean class: " + targetType.getName());
}
}
else {
// Non-empty set of methods
ConfigurableApplicationContext context = this.applicationContext;
Assert.state(context != null, "No ApplicationContext set");
List<EventListenerFactory> factories = this.eventListenerFactories;
Assert.state(factories != null, "EventListenerFactory List not initialized");
for (Method method : annotatedMethods.keySet()) {
for (EventListenerFactory factory : factories) {
// 利用EventListenerFactory来对加了@EventListener注解的方法生成ApplicationListener对象
if (factory.supportsMethod(method)) {
Method methodToUse = AopUtils.selectInvocableMethod(method, context.getType(beanName));
//加了@EventListener注解的方法对应的是什么样的ApplicationListener,取决于factory是怎么创建的,默认使用的是DefaultEventListenerFactory
ApplicationListener<?> applicationListener =
factory.createApplicationListener(beanName, targetType, methodToUse);
if (applicationListener instanceof ApplicationListenerMethodAdapter) {
((ApplicationListenerMethodAdapter) applicationListener).init(context, this.evaluator);
}
context.addApplicationListener(applicationListener);
break;
}
}
}
if (logger.isDebugEnabled()) {
logger.debug(annotatedMethods.size() + " @EventListener methods processed on bean '" +
beanName + "': " + annotatedMethods);
}
}
}
}
说明:这里的EventListenerFactory默认使用的是DefaultEventListenerFactory,作用是将加了@EventListener注解的方法封装成为ApplicationListener对象;
2.2. EventListenerMethodProcessor的类图
2.3. 关于SmartInitializingSingleton
public interface SmartInitializingSingleton {
/**
* Invoked right at the end of the singleton pre-instantiation phase,
* with a guarantee that all regular singleton beans have been created
* already. {@link ListableBeanFactory#getBeansOfType} calls within
* this method won't trigger accidental side effects during bootstrap.
* <p><b>NOTE:</b> This callback won't be triggered for singleton beans
* lazily initialized on demand after {@link BeanFactory} bootstrap,
* and not for any other bean scope either. Carefully use it for beans
* with the intended bootstrap semantics only.
*/
void afterSingletonsInstantiated();
}
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
// 获取合并后的BeanDefinition
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName );
//BeanDefinition如果是抽象的,是不会创建bean的(抽象的BeanDefinition和抽象的类是不一样的,抽象类在扫描的时候就会有判断,不会生成BeanDefinition)
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
// 获取FactoryBean对象
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);//创建FactoryBean对象
if (bean instanceof FactoryBean) {
FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(
(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
// 创建真正的Bean对象(getObject()返回的对象)
getBean(beanName);
}
}
}
else {
// 创建Bean对象
getBean(beanName);
}
}
}
// 所有的非懒加载单例Bean都创建完了后
// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
.tag("beanName", beanName);
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
smartInitialize.end();
}
}
}
说明:当所有非懒加载的单例bean都创建完之后,就会执行SmartInitializingSingleton的afterSingletonsInstantiated()方法,而EventListenerMethodProcessor就实现了SmartInitializingSingleton接口;
流程图
五、事件发布流程
以发布ContextRefreshedEvent事件为例:
1. publishEvent(new ContextRefreshedEvent(this)),发布事件;
2. 获取事件多播器并广播事件,既然是广播,如果定义了多个事件监听器,那么当发布一个事件的时候,这些事件监听器都会收到这个事件;
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
3. 获取到所有的ApplicationListener;
/**
* 广播事件
* 如果定义了多个事件监听器,当发布一个事件的时候,这些事件监听器都会收到这个事件
*/
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {//支持异步执行监听器
executor.execute(() -> invokeListener(listener, event));
}
else {//一个线程串行的去执行
invokeListener(listener, event);
}
}
}
如果有Executor,可以支持使用Executor进行异步派发,否则,以同步的方式直接执行listener方法,invokeListener(listener, event),都是拿到listener回调onApplicationEvent()方法;、
流程图