封面来源:碧蓝航线 愚者的天平 活动CG
Spring Application Event 官方文档:Standard and Custom Events
为了更好的阅读体验,请先将 SpringBoot 常用拓展点 作为前置阅读。
0. 前言
上周对 LinkedHashMap 的源码进行了剖析,那篇文章本应该在 4 月份就发布了,只是由于种种原因一拖再拖,甚至最终拖到了 7 月才正在发布,而这篇文章计划在剖析 LinkedHashMap 源码之后,预计 5 月份发布的,可前一篇的不断推迟,也导致本篇只能无奈地跟着顺延。但是没有关系,接下来我将开启“爆肝模式”,把前几个月落下的内容全部补齐。💪
还记得刚实习那会儿,自己的实力就算不是“非常菜”,但把“非常”两字去了也还是非常准确的。那时候自己对设计模式的了解仅限于理论,实际运用更是从来都没尝试过,而在自己第一次看到公司代码里基于 EventBus 实现的“发布-订阅”模式后,更是让我啧啧称奇。后来我了解到,这其实就是观察者模式的一种运用。
Spring 作为 Java 中的顶级明星框架,自然也实现了事件的“发布-订阅”模式(或者说事件监听机制),那就跟随本文,一起看看 Spring 的底层是如何实现模式的。
1. ResolvableType
在 Spring 的许多内部机制中,ResolvableType 被用来进行类型匹配和检查。在后续的源码分析中会看到 ResolvableType 的使用,因此有必要简单介绍下它的使用。
1.1 概述
ResolvableType 对 Java 中的 java.lang.reflect.Type 进行了封装,提供了获取目标 Type 的父类、接口和泛型参数的能力。
ResolvableType 能够从一个字段(Field)、一个方法参数、方法返回值类型或一个类(Class)中获取。ResolvableType 的大多数方法也都会返回一个 ResolvableType 实例,以便后续使用。
1.2 简单使用
有一个名为 MyMap 的类,它继承了 HashMap:
1 2 3 4 static class MyMap extends HashMap < String , List < Integer >> {
@ Serial
private static final long serialVersionUID = - 9026643848761552207L ;
}
如何获取继承的 HashMap 的泛型信息呢?
ResolvableType 针对这个场景提供了许多简单易用的 API:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @ Test
public void testResolvableType () {
ResolvableType myMapType = ResolvableType . forClass ( MyMap . class );
// 泛型参数在父类的 HashMap 中,因此先获取到父类的 ResolvableType
ResolvableType hashMapType = myMapType . getSuperType ();
// 根据索引获取泛型信息 String
ResolvableType firstGenericType = hashMapType . getGeneric ( 0 );
Class < ? > firstGenericClazz = firstGenericType . resolve ();
assertThat (firstGenericClazz) . isEqualTo ( String . class );
// 再获取第二个泛型信息 List<Integer>
ResolvableType secondGenericType = hashMapType . getGeneric ( 1 );
ResolvableType secondFirstGenericType = secondGenericType . getGeneric ( 0 );
Class < ? > secondFirstGenericClazz = secondFirstGenericType . resolve ();
assertThat (secondFirstGenericClazz) . isEqualTo ( Integer . class );
}
除了使用 forClass()静态工厂来构建 ResolvableType 实例外,还有许多其他构建方式:
forField()
forMethodReturnType()
forMethodParameter()
forConstructorParameter()
…
对于每种创建方式,ResolvableType 还提供了多种重载,以满足不同的使用场景。
大多数创建方式都能直观地看出其实际作用,但有一小部分并没有那么直观,本节将针对“没那么直观”的部分进行讲解。
1.3 forRawClass
forRawClass() 方法接收一个 Class 类型的参数,返回该 Class 的原始类(Raw Class)的 ResolvableType 对象。
看一个和 forClass() 的对比:
1 2 3 4 5 6 7 8 9 10 @ Test
public void testForRawClass () {
ResolvableType type = ResolvableType . forClass ( List . class );
// 包含泛型信息
assertThat ( type . toString () ) . isEqualTo ( "java.util.List<?>" );
type = ResolvableType . forRawClass ( List . class );
// 不包含泛型信息
assertThat ( type . toString () ) . isEqualTo ( "java.util.List" );
}
1.4 forClass 的重载
forClass() 方法除了接收一个单一的 Class 对象外,还提供了一个重载:
1 ResolvableType forClass ( Class < ? > baseType , Class < ? > implementationClass)
这个重载能够 返回具有给定实现类型(implementationClass)的基类(baseType)的 ResolvableType 。
这将用于描述类似多态的场景:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 static class Foo < T > {
}
static class Bar extends Foo < String > {
}
@ Test
public void testForClass () {
ResolvableType type = ResolvableType . forClass ( Bar . class );
/*
* 把当前 ResolvableType 转换成给定的 ResolvableType
* Bar 是 Foo 的子类,将 Bar 转成 Foo
*/
ResolvableType fooType = type . as ( Foo . class );
assertThat ( fooType . toString () ) . contains ( "Foo<java.lang.String>" );
// 类似于 Foo<String> foo = new Bar();
fooType = ResolvableType . forClass ( Foo . class , Bar . class );
assertThat ( fooType . toString () ) . contains ( "Foo<java.lang.String>" );
}
1.5 forConstructorParameter 的重载
forConstructorParameter() 方法用于获取指定构造器参数的 ResolvableType,和 forClass() 方法类似,它也提供了一个的重载:
1 ResolvableType forConstructorParameter ( Constructor < ? > constructor , int parameterIndex , Class < ? > implementationClass)
这个重载解决的场景也和 forClass() 的重载类似:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 static class GenericClass < T > {
public GenericClass ( T value ) {
}
}
static class IntegerGenericClass extends GenericClass < Integer > {
public IntegerGenericClass ( Integer value ) {
super (value);
}
}
@ Test
public void testForConstructorParameter () {
ResolvableType type = ResolvableType . forConstructorParameter ( GenericClass . class . getConstructors ()[ 0 ], 0 );
assertThat ( type . toString () ) . isEqualTo ( "?" );
type = ResolvableType . forConstructorParameter ( GenericClass . class . getConstructors ()[ 0 ], 0 , IntegerGenericClass . class );
assertThat ( type . toString () ) . isEqualTo ( "java.lang.Integer" );
}
1.6 forField 的重载
使用 forField() 方法能够获取 Field 对象对应的 ResolvableType 对象,和 forClass、forConstructorParameter 类似,forField() 提供了处理泛型变量的重载:
1 ResolvableType forField ( Field field , Class < ? > implementationClass)
使用方式也类似:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 static class BaseClass < T > {
protected T value ;
}
static class StringClass extends BaseClass < String > {
}
@ Test
@ SneakyThrows
public void testForField_1 () {
Field field = BaseClass . class . getDeclaredField ( "value" );
ResolvableType type = ResolvableType . forField (field);
assertThat ( type . toString () ) . isEqualTo ( "?" );
type = ResolvableType . forField (field, StringClass . class );
assertThat ( type . toString () ) . isEqualTo ( "java.lang.String" );
}
对于拥有多层嵌套的泛型参数,forField() 还支持传入 nestingLevel(嵌套等级)来精准获取嵌套泛型的 ResolvableType:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 static class NestedFieldClass {
private List < List < Integer >> list ;
}
@ Test
@ SneakyThrows
public void testForField_2 () {
Field field = NestedFieldClass . class . getDeclaredField ( "list" );
ResolvableType type = ResolvableType . forField (field);
assertThat ( type . toString () ) . isEqualTo ( "java.util.List<java.util.List<java.lang.Integer>>" );
// 1 表示外层,2 及其以后才是嵌套泛型
type = ResolvableType . forField (field, 1 );
assertThat ( type . toString () ) . isEqualTo ( "java.util.List<java.util.List<java.lang.Integer>>" );
type = ResolvableType . forField (field, 2 );
assertThat ( type . toString () ) . isEqualTo ( "java.util.List<java.lang.Integer>" );
type = ResolvableType . forField (field, 3 );
assertThat ( type . toString () ) . isEqualTo ( "java.lang.Integer" );
}
需要注意的是,传入的参数名叫 nestingLevel,这里使用的是 Level,而不是 Index,因此它的起始值是从 1 开始,而不是从 0 开始的。
1.7 forType 的重载
先简单介绍下 Java 中的 Type 接口的体系:
classDiagram
class Type {
<<interface>>
getTypeName()
}
class Class~T~
class GenericArrayType {
<<interface>>
Type getGenericComponentType()
}
class ParameterizedType {
<<interface>>
Type[] getActualTypeArguments()
Type getRawType()
Type getOwnerType()
}
class TypeVariable~D extends GenericDeclaration~{
<<interface>>
Type[] getBounds()
D getGenericDeclaration()
String getName()
AnnotatedType[] getAnnotatedBounds()
}
class WildcardType {
<<interface>>
Type[] getUpperBounds()
Type[] getLowerBounds()
}
Type <|.. Class~T~
Type <|-- ParameterizedType
Type <|-- GenericArrayType
Type <|-- TypeVariable~D extends GenericDeclaration~
Type <|-- WildcardType
Class 就很熟悉了,用于表示类和接口类型
ParameterizedType 用于表示参数化类型,比如 List<String>
GenericArrayType 用于表示泛型数组类型,比如 T[]
TypeVariable 用于表示类型变量,比如 T
WildcardType 用于表示通配符类型,比如 ? extends Number
一份简单的“食用”示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 static class Sample < T > {
List < String > list ;
T [] array ;
List < ? extends Number > wildcardList ;
}
@ Test
@ SneakyThrows
public void testTypeSystem () {
// 获取类的类型
Class < ? > clazz = Class . forName ( "java.util.List" );
assertThat ( clazz . toString () ) . isEqualTo ( "interface java.util.List" );
// 获取参数化类型
Field field = Sample . class . getDeclaredField ( "list" );
Type genericType = field . getGenericType ();
if (genericType instanceof ParameterizedType parameterizedType) {
// 原始类型
assertThat ( parameterizedType . getRawType (). toString () )
. isEqualTo ( "interface java.util.List" );
// 实际类型参数
assertThat ( parameterizedType . getActualTypeArguments () )
. extracting (Object :: toString)
. containsOnly ( "class java.lang.String" );
}
// 获取泛型数组类型
Field arrayField = Sample . class . getDeclaredField ( "array" );
Type arrayType = arrayField . getGenericType ();
if (arrayType instanceof GenericArrayType genericArrayType) {
assertThat ( genericArrayType . getGenericComponentType (). toString () )
. isEqualTo ( "T" );
}
// 获取类型变量
TypeVariable < Class < Sample >> [] typeParameters = Sample . class . getTypeParameters ();
assertThat ( typeParameters . length ) . isEqualTo ( 1 );
TypeVariable < Class < Sample >> typeParam = typeParameters[ 0 ] ;
assertThat ( typeParam . getName () ) . isEqualTo ( "T" );
// 获取类型变量的上界
assertThat ( typeParam . getBounds () )
. singleElement ()
. extracting (Objects :: toString)
. isEqualTo ( "class java.lang.Object" );
// 获取通配符类型
Field wildcardField = Sample . class . getDeclaredField ( "wildcardList" );
Type wildcardType = wildcardField . getGenericType ();
if (wildcardType instanceof ParameterizedType parameterizedType) {
Type [] actualTypeArguments = parameterizedType . getActualTypeArguments ();
assertThat ( actualTypeArguments . length ) . isEqualTo ( 1 );
Type typeArg = actualTypeArguments[ 0 ] ;
if (typeArg instanceof WildcardType wildcard) {
assertThat ( wildcard . getUpperBounds () )
. singleElement ()
. extracting (Objects :: toString)
. isEqualTo ( "class java.lang.Number" );
assertThat ( wildcard . getLowerBounds () ) . isEmpty ();
}
}
}
言归正传,forType() 就是用于获取 Type 实例的 ResolvableType,ResolvableType 为 forType() 提供了三种重载,还是用一份代码搞定“食用”示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 static class Outer < T > {
public T genericMethod () {
return null ;
}
}
@ Test
@ SneakyThrows
public void testForType () {
ResolvableType type = ResolvableType . forType ( Bar . class );
assertThat ( type . toString () )
. contains ( "Bar" )
. doesNotContain ( "Foo" );
ParameterizedTypeReference < List < String >> typeReference = new ParameterizedTypeReference <> () {
} ;
type = ResolvableType . forType (typeReference);
assertThat ( type . toString () ) . isEqualTo ( "java.util.List<java.lang.String>" );
Method method = Outer . class . getMethod ( "genericMethod" );
type = ResolvableType . forMethodReturnType (method);
assertThat ( type . toString () ) . isEqualTo ( "?" );
ResolvableType genericClassType = ResolvableType . forClassWithGenerics ( Outer . class , String . class );
type = ResolvableType . forType ( method . getGenericReturnType (), genericClassType);
assertThat ( type . toString () ) . isEqualTo ( "java.lang.String" );
}
1.8 forInstance
forInstance() 能够直接获取一个实例对应的 ResolvableType。
由于 Java 的泛型擦除,直接使用该方法可能无法获取到实际的泛型参数类型,此时可以要求实例所在的类实现 ResolvableTypeProvider 接口:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 static class MyGenericClass < T > {
}
static class MyGenericClass2 < T > implements ResolvableTypeProvider {
private final T payload ;
public MyGenericClass2 ( T payload ) {
this . payload = payload;
}
@ Override
public ResolvableType getResolvableType () {
return ResolvableType . forClassWithGenerics ( MyGenericClass2 . class , payload . getClass ());
}
}
@ Test
public void testForInstance () {
MyGenericClass < Integer > obj = new MyGenericClass <> () ;
ResolvableType type = ResolvableType . forInstance (obj);
// 拿不到实际的泛型
assertThat ( type . toString () ) . contains ( "MyGenericClass<?>" );
MyGenericClass2 < String > object = new MyGenericClass2 <> ( "payload" ) ;
type = ResolvableType . forInstance (object);
// 实现 ResolvableTypeProvider 后就拿得到了
assertThat ( type . toString () ) . contains ( "MyGenericClass2<java.lang.String>" );
}
1.9 getNested 的重载
ResolvableType 中的成员方法都比较简单,基本都能见名知义,就不一一介绍每个方法的使用方式了。
在这些成员方法中,有个名为 getNested() 的方法,显然这是用于获取嵌套泛型的 ResolvableType 信息。
除了只接收一个 nestingLevel 参数外,它还有一个重载:
1 ResolvableType getNested ( int nestingLevel , @ Nullable Map < Integer , Integer > typeIndexesPerLevel)
typeIndexesPerLevel 参数类型是 Map,对其进行直译可以理解为“每层的类型索引”。
还是用个用例来理解它的使用方式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @ Test
public void testGetNested () {
ParameterizedTypeReference < List < Map < String , List < Integer >>>> typeReference = new ParameterizedTypeReference <> () {
} ;
ResolvableType type = ResolvableType . forType (typeReference);
ResolvableType nested = type . getNested ( 1 );
// 第一层就是最外面的
assertThat ( nested . toString () ) . isEqualTo ( "java.util.List<java.util.Map<java.lang.String, java.util.List<java.lang.Integer>>>" );
nested = type . getNested ( 2 );
assertThat ( nested . toString () ) . isEqualTo ( "java.util.Map<java.lang.String, java.util.List<java.lang.Integer>>" );
/*
* nestingLevel: 第三层嵌套
* 2 -> 0: 第 2 层嵌套取 index = 0 的泛型,即: Map<String, List<Integer>>>
* 3 -> 1: 第 3 层嵌套取 index = 1 的泛型,即: List<Integer>
*/
nested = type . getNested ( 3 , Map . of ( 2 , 0 , 3 , 1 ));
assertThat ( nested . toString () ) . isEqualTo ( "java.util.List<java.lang.Integer>" );
}
这两个参数有些细节需要注意:
nestingLevel 重点在 Level,从 1 开始
typeIndexesPerLevel 类型是 Map,其 key 是指 Level,要从 1 开始,但 value 是指 Index,此时要从 0 开始
Level 和 Index 的区别有点坑,使用时应当特别注意。😣
1.10 hasUnresolvableGenerics
hasUnresolvableGenerics() 用于检查当前 ResolvableType 中是否包含无法解析的泛型参数。
1 2 3 4 5 6 7 8 @ Test
public void testHasUnresolvableGenerics () {
ResolvableType type = ResolvableType . forClassWithGenerics ( List . class , Integer . class );
assertThat ( type . hasUnresolvableGenerics () ) . isFalse ();
type = ResolvableType . forClass ( List . class );
assertThat ( type . hasUnresolvableGenerics () ) . isTrue ();
}
2. 简单的示例
Spring 内部提供了多种发布事件与监听事件的方式,并且随着 Spring 的不断迭代,使用方式也越来越简单。
不必纠结茴字有几种写法,直接聚焦于最简单的写法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @ SpringBootApplication
public class SimpleSpringEventListenerTest {
public static void main ( String [] args ) {
ConfigurableApplicationContext context = SpringApplication . run ( SimpleSpringEventListenerTest . class , args);
context . publishEvent ( new UserRegisterEvent ( "成功注册用户: mofan" ));
context . close ();
}
@ Slf4j
@ Component
private static class UserRegisterEventListener {
@ EventListener
public void doEvent ( UserRegisterEvent event ) {
log . info ( "监听到用户注册事件: {}" , event . info ());
}
}
private record UserRegisterEvent ( String info) {
}
}
运行 main() 方法后,控制台打印出:
监听到用户注册事件: 成功注册用户: mofan
这个 Demo 可以说是非常简单了,简单得连整个逻辑都是在一个类中完成的。
言归正传,Spring 底层究竟是怎么实现这种事件的发布与监听机制呢?
3. 猜想与假设
从上述 Demo 的执行过程可以看到,执行 publishEvent() 方法发布事件后,会立即执行 UserRegisterEventListener 中的 doEvent() 方法。
UserRegisterEventListener 类被 @Component 注解修饰,会在 SpringApplication.run() 方法执行后添加到 Spring 容器中。
Spring 实现的事件监听机制其实就是设计模式中 观察者模式 的应用,根据对观察者模式的理解,不妨大胆猜测:当调用 publishEvent() 方法发布事件后,会遍历当前程序中所有的监听器,如果存在对应事件的监听器,那么就会调用监听器中的方法,完成事件监听。
如果要验证这个猜想,可以从以下几个方面出发:
监听器是怎么注册的,或者说 @EventListener 注解是怎么解析的
调用 publishEvent() 方法后,是怎么触发监听器的
4. 注册监听器
事件监听器的注册涉及到 EventListenerMethodProcessor,先看它的定义:
1 2 3 4 public class EventListenerMethodProcessor
implements SmartInitializingSingleton , ApplicationContextAware , BeanFactoryPostProcessor {
// --snip--
}
实现了三个经典的拓展点,关于这些拓展点的使用方式、加载时机、执行时机可以参考 SpringBoot 常用拓展点 ,这里不再赘述。
EventListenerMethodProcessor 的加载与执行和解析 @Autowired 注解的 AutowiredAnnotationBeanPostProcessor 非常相似:
flowchart TD
1("...")
subgraph 2 ["createApplicationContext()"]
2.1("1. 注册 EventListenerMethodProcessor 的 BeanDefinition"):::orange-red-filling
end
3("prepareContext()")
subgraph 4 ["refreshContext()"]
subgraph 4.1 ["AbstractApplicationContext#invokeBeanFactoryPostProcessors"]
4.1.1("2. 调用 EventListenerMethodProcessor#postProcessBeanFactory() 获取 EventListenerFactory"):::orange-red-filling
end
subgraph 4.2 ["finishBeanFactoryInitialization()"]
4.2.1("3. 调用 EventListenerMethodProcessor#afterSingletonsInstantiated() 注册监听器"):::orange-red-filling
end
end
5("...")
1 --> 2 --> 3 --> 4 --> 5
4.1 --> 4.2
classDef orange-red-filling fill:#f96;
EventListenerMethodProcessor 的加载与执行分为 3 步:
在调用 createApplicationContext() 创建 ApplicationContext 时,注册 EventListenerMethodProcessor 的 BeanDefinition
EventListenerMethodProcessor 实现了 BeanFactoryPostProcessor 接口,因此在 refresh 过程中会调用 postProcessBeanFactory() 方法,获取 EventListenerFactory 用于后续创建事件监听器
EventListenerMethodProcessor 也实现了 SmartInitializingSingleton 接口,之后还会调用 afterSingletonsInstantiated() 方法用于创建事件监听器
4.1 注册处理器
1 2 3 protected ConfigurableApplicationContext createApplicationContext () {
return this . applicationContextFactory . create ( this . webApplicationType );
}
未设置过 applicationContextFactory 的情况下,将使用默认值:
1 2 3 4 5 // class SpringApplication
private ApplicationContextFactory applicationContextFactory = ApplicationContextFactory . DEFAULT ;
// interface ApplicationContextFactory
ApplicationContextFactory DEFAULT = new DefaultApplicationContextFactory () ;
内部创建按需 ConfigurableApplicationContext:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 // 创建方法
@ Override
public ConfigurableApplicationContext create ( WebApplicationType webApplicationType) {
try {
return getFromSpringFactories (webApplicationType , ApplicationContextFactory :: create ,
this :: createDefaultApplicationContext) ;
}
catch ( Exception ex ) {
throw new IllegalStateException ( "Unable create a default ApplicationContext instance, "
+ "you may need a custom ApplicationContextFactory" , ex) ;
}
}
// 默认值
private ConfigurableApplicationContext createDefaultApplicationContext () {
if ( ! AotDetector . useGeneratedArtifacts () ) {
// 程序通常会执行到这
return new AnnotationConfigApplicationContext () ;
}
return new GenericApplicationContext () ;
}
private < T > T getFromSpringFactories ( WebApplicationType webApplicationType ,
BiFunction < ApplicationContextFactory , WebApplicationType , T > action , Supplier < T > defaultResult) {
// 循环从 META-INF/spring.factories 加载的 ApplicationContextFactory 实现类
for ( ApplicationContextFactory candidate : SpringFactoriesLoader . loadFactories ( ApplicationContextFactory . class ,
getClass (). getClassLoader ()) ) {
// 调用它们的 create() 方法创建
T result = action . apply (candidate, webApplicationType);
if (result != null ) {
return result ;
}
}
// 如果返回的 result 都是 null,给个默认值
return (defaultResult != null ) ? defaultResult . get () : null ;
}
从 META-INF/spring.factories 加载 ApplicationContextFactory 后,调用重写的 create() 方法返回 result,如果 result != null,就直接返回。
如果能够加载到 ApplicationContextFactory,并且 create() 方法返回的 result 也不是 null,加载的 ApplicationContextFactory 通常是 ServletWebServerApplicationContextFactory。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class ServletWebServerApplicationContextFactory implements ApplicationContextFactory {
// --snip--
@ Override
public ConfigurableApplicationContext create ( WebApplicationType webApplicationType ) {
return (webApplicationType != WebApplicationType . SERVLET ) ? null : createContext ();
}
private ConfigurableApplicationContext createContext () {
if ( ! AotDetector . useGeneratedArtifacts ()) {
// 程序通常会执行到这
return new AnnotationConfigServletWebServerApplicationContext ();
}
return new ServletWebServerApplicationContext ();
}
}
一般来说,调用该实现类的 create() 会返回一个 AnnotationConfigServletWebServerApplicationContext 实例。
如果调用加载的 ApplicationContextFactory 的 create() 方法返回的 result 都是 null,最后则会执行 defaultResult 逻辑,给一个默认值:
1 2 3 4 5 6 7 private ConfigurableApplicationContext createDefaultApplicationContext () {
if ( ! AotDetector . useGeneratedArtifacts () ) {
// 程序通常会执行到这
return new AnnotationConfigApplicationContext () ;
}
return new GenericApplicationContext () ;
}
简单总结下创建 ConfigurableApplicationContext 的过程:
flowchart TB
a(["开始"])
b("从 META-INF/spring.factories 中加载若干个 ApplicationContextFactory")
c("遍历每个加载的 Factory")
d("调用 create() 方法创建")
e{"创建结果是 null"}
f{"是否处理完加载的<br/> Factory"}
g("使用默认方式创建")
h("返回创建的对象")
z(["结束"])
a --> b --> c --> d --> e
e --> |是|f
e --> |否|h
f --> |是|g
f --> |否|c
g --> h --> z
根据前文的描述,这里创建的 ConfigurableApplicationContext 通常有两种:
AnnotationConfigServletWebServerApplicationContext
AnnotationConfigApplicationContext
但无论是哪一种,在调用它们自己的构造函数时,都会再去创建 AnnotatedBeanDefinitionReader 实例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public AnnotationConfigServletWebServerApplicationContext ( DefaultListableBeanFactory beanFactory) {
super (beanFactory) ;
// here
this . reader = new AnnotatedBeanDefinitionReader ( this ) ;
this . scanner = new ClassPathBeanDefinitionScanner ( this ) ;
}
public AnnotationConfigApplicationContext () {
StartupStep createAnnotatedBeanDefReader = getApplicationStartup () . start ( "spring.context.annotated-bean-reader.create" );
// here
this . reader = new AnnotatedBeanDefinitionReader ( this ) ;
createAnnotatedBeanDefReader . end ();
this . scanner = new ClassPathBeanDefinitionScanner ( this ) ;
}
而在构造 AnnotatedBeanDefinitionReader 时就会去注册 EventListenerMethodProcessor 的 BeanDefinition:
1 2 3 4 5 6 7 8 9 10 11 12 public AnnotatedBeanDefinitionReader ( BeanDefinitionRegistry registry) {
this (registry , getOrCreateEnvironment (registry)) ;
}
public AnnotatedBeanDefinitionReader ( BeanDefinitionRegistry registry , Environment environment) {
Assert . notNull (registry, "BeanDefinitionRegistry must not be null" );
Assert . notNull (environment, "Environment must not be null" );
this . registry = registry ;
this . conditionEvaluator = new ConditionEvaluator (registry , environment , null ) ;
// 加载
AnnotationConfigUtils . registerAnnotationConfigProcessors ( this . registry );
}
注册该处理器的逻辑由 AnnotationConfigUtils.registerAnnotationConfigProcessors() 方法完成:
1 2 3 public static void registerAnnotationConfigProcessors ( BeanDefinitionRegistry registry) {
registerAnnotationConfigProcessors (registry , null ) ;
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 public static Set < BeanDefinitionHolder > registerAnnotationConfigProcessors (
BeanDefinitionRegistry registry , @ Nullable Object source) {
// --snip--
Set < BeanDefinitionHolder > beanDefs = new LinkedHashSet <> ( 8 ) ;
// 注册 ConfigurationClassPostProcessor,可用于处理 @Configuration
// 注册 AutowiredAnnotationBeanPostProcessor,可用于处理 @Autowired、@Value
// 注册 CommonAnnotationBeanPostProcessor,可用于处理 @Resource、@PostConstruct
// 注册 PersistenceAnnotationBeanPostProcessor,对 JPA 的支持
// 注册 EventListenerMethodProcessor
if ( ! registry . containsBeanDefinition (EVENT_LISTENER_PROCESSOR_BEAN_NAME) ) {
RootBeanDefinition def = new RootBeanDefinition ( EventListenerMethodProcessor . class ) ;
def . setSource (source);
beanDefs . add ( registerPostProcessor (registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
}
// 注册 DefaultEventListenerFactory
if ( ! registry . containsBeanDefinition (EVENT_LISTENER_FACTORY_BEAN_NAME) ) {
RootBeanDefinition def = new RootBeanDefinition ( DefaultEventListenerFactory . class ) ;
def . setSource (source);
beanDefs . add ( registerPostProcessor (registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
}
return beanDefs ;
}
在最后两步里,先是注册了 EventListenerMethodProcessor,最后还注册了 DefaultEventListenerFactory。这个 DefaultEventListenerFactory 也有大用处,后面会说到。
到此,EventListenerMethodProcessor 的 BeanDefinition 已经成功注册了,如果后续要获取对应的 Bean,调用下 BeanFactory 中的 getBean() 方法即可。
4.2 postProcessBeanFactory
随着程序的执行,来到 refresh 阶段。
EventListenerMethodProcessor 实现了 BeanFactoryPostProcessor 接口,因此在调用 AbstractApplicationContext#invokeBeanFactoryPostProcessors() 方法时就会执行 EventListenerMethodProcessor 重写的 postProcessBeanFactory() 方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 @ Override
public void postProcessBeanFactory ( ConfigurableListableBeanFactory beanFactory) {
this . beanFactory = beanFactory ;
this . originalEvaluationContext . setBeanResolver ( new BeanFactoryResolver ( this . beanFactory ));
// 获取 EventListenerFactory 类型的 Bean
Map < String , EventListenerFactory > beans = beanFactory . getBeansOfType ( EventListenerFactory . class , false , false );
List < EventListenerFactory > factories = new ArrayList <> ( beans . values () ) ;
// 排个序
AnnotationAwareOrderComparator . sort (factories);
// 设置成员变量
this . eventListenerFactories = factories ;
}
方法内部逻辑很简单,重点是获取了容器中所有 EventListenerFactory 类型的 Bean。
上一节中介绍注册 EventListenerMethodProcessor 时,还说到会注册 DefaultEventListenerFactory,而它就是 EventListenerFactory 的默认实现。
Call Back 了,属于是。😆
EventListenerFactory 有什么用呢?
从名字就能看出,这玩意是用来创建事件监听器(EventListener)的,那它会在什么时候创建呢?
4.3 afterSingletonsInstantiated
refresh 阶段干的事有很多,SmartInitializingSingleton 接口的执行阶段也是在这,该接口被执行时,表明 容器中所有的单例 Bean 已经都被实例化 完了。
EventListenerMethodProcessor 好巧不巧也实现了 SmartInitializingSingleton,其实也很好理解,只有单例 Bean 都实例化了,才能解析 @EventListener 注解,不然漏了咋办?
重写的 afterSingletonsInstantiated() 方法不算很长,但条件判断和异常处理比较多,代码格式不是很好,就不贴代码了,直接概括下主要逻辑:
通过 beanFactory.getBeanNamesForType(Object.class) 获取 Spring 容器中所有的 Bean 的 name;
根据 name,获取 Bean 的实际类型 type(就这步导致条件判断和异常处理比较多);
最后根据 Bean 的 name、type 获取内部所有事件监听器。
重点在第三步,由 processBean() 方法完成,这个方法的格式也不太行,依旧概括下主要逻辑:
获取类中所有被 @EventListener 注解标记的方法;
1 2 3 4 Map < Method , EventListener > annotatedMethods = null ;
annotatedMethods = MethodIntrospector . selectMethods (targetType,
( MethodIntrospector . MetadataLookup < EventListener > ) method ->
AnnotatedElementUtils . findMergedAnnotation (method, EventListener . class ));
遍历这些方法,把它们包装成 ApplicationListener 对象添加到 ConfigurableApplicationContext 中。
关注下包装成 ApplicationListener 的逻辑:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 ConfigurableApplicationContext context = this . applicationContext ;
List < EventListenerFactory > factories = this . eventListenerFactories ;
// 遍历所有被 @EventListener 注解标记的方法
for ( Method method : annotatedMethods . keySet () ) {
// 遍历 EventListenerFactory
for ( EventListenerFactory factory : factories) {
// 判断是否执行对应的方法
if ( factory . supportsMethod (method) ) {
// 处理被代理的情况,找到正在执行的方法
Method methodToUse = AopUtils . selectInvocableMethod (method, context . getType (beanName));
// 包装成 ApplicationListener
ApplicationListener < ? > applicationListener =
factory . createApplicationListener (beanName, targetType, methodToUse);
// 按需初始化,DefaultEventListenerFactory 的包装结果总是满足
if (applicationListener instanceof ApplicationListenerMethodAdapter alma) {
alma . init (context, this . evaluator );
}
// 添加到 ConfigurableApplicationContext
context . addApplicationListener (applicationListener);
// 一个监听器方法最多只能被一个 Factory 包装
break ;
}
}
}
遍历 factories 时,可以拿到默认实现 DefaultEventListenerFactory:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public class DefaultEventListenerFactory implements EventListenerFactory , Ordered {
private int order = LOWEST_PRECEDENCE ;
public void setOrder ( int order ) {
this . order = order;
}
@ Override
public int getOrder () {
return this . order ;
}
@ Override
public boolean supportsMethod ( Method method ) {
return true ;
}
@ Override
public ApplicationListener < ? > createApplicationListener ( String beanName , Class < ? > type , Method method ) {
return new ApplicationListenerMethodAdapter (beanName, type, method);
}
}
内部逻辑比较简单,supportsMethod() 方法总是返回 true,createApplicationListener() 返回的 ApplicationListenerMethodAdapter 实例(满足按需初始化,会调用 init() 方法)。
ApplicationListenerMethodAdapter 也比较重要,先混个眼熟。😁
当然,实际工作环境中拿到的 factories 可能会有很多种,但在本文的例子中,@EventListener 标记的方法就是用 DefaultEventListenerFactory 包装的。
ConfigurableApplicationContext#addApplicationListener()
简单说下添加事件监听器的逻辑,调用后会来到 AbstractApplicationContext#addApplicationListener() 方法中:
1 2 3 4 5 6 7 8 @ Override
public void addApplicationListener ( ApplicationListener < ? > listener) {
Assert . notNull (listener, "ApplicationListener must not be null" );
if ( this . applicationEventMulticaster != null ) {
this . applicationEventMulticaster . addApplicationListener (listener);
}
this . applicationListeners . add (listener);
}
在这里会向 applicationEventMulticaster 中添加监听器。它又是怎么来的呢?
其值变化逻辑分布在两处:
initApplicationEventMulticaster()
doClose()
显然 applicationEventMulticaster 是在 initApplicationEventMulticaster() 方法中被设置的(这个方法会在 refresh 阶段执行):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 protected void initApplicationEventMulticaster () {
ConfigurableListableBeanFactory beanFactory = getBeanFactory () ;
// 当前容器中是否包含名为 applicationEventMulticaster 的 Bean(不包括父容器)
if ( beanFactory . containsLocalBean (APPLICATION_EVENT_MULTICASTER_BEAN_NAME) ) {
// 如果有,那就拿到它,并设置 applicationEventMulticaster
this . applicationEventMulticaster =
beanFactory . getBean (APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster . class );
if ( logger . isTraceEnabled () ) {
logger . trace ( "Using ApplicationEventMulticaster [" + this . applicationEventMulticaster + "]" );
}
}
else {
// 如果没有,就创建一个并设置 applicationEventMulticaster
this . applicationEventMulticaster = new SimpleApplicationEventMulticaster (beanFactory) ;
// 顺便在容器中注册一个新 Bean
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 () + "]" );
}
}
}
总的来说,applicationEventMulticaster 通常是 SimpleApplicationEventMulticaster 实例。
它内部的 addApplicationListener() 的逻辑又是怎样的呢?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 private final DefaultListenerRetriever defaultRetriever = new DefaultListenerRetriever () ;
@ Override
public void addApplicationListener ( ApplicationListener < ? > listener) {
synchronized ( this . defaultRetriever ) {
// Explicitly remove target for a proxy, if registered already,
// in order to avoid double invocations of the same listener.
Object singletonTarget = AopProxyUtils . getSingletonTarget (listener);
if (singletonTarget instanceof ApplicationListener) {
this . defaultRetriever . applicationListeners . remove (singletonTarget);
}
this . defaultRetriever . applicationListeners . add (listener);
this . retrieverCache . clear ();
}
}
简单来说就是向 defaultRetriever 中添加监听器。
无论是 AbstractApplicationContext 中的 applicationEventMulticaster,还是 SimpleApplicationEventMulticaster 中的 defaultRetriever,也都得混个眼熟,后面介绍事件的发布和监听是都会用到。
到此,事件监听器的注册就算告一段落了,但这仅仅是一个开始,上述所有逻辑都是在调用的 SpringApplication.run() 方法中完成的,相当于只做了准备工作,完全不涉及到事件的发布与监听。各种复杂的逻辑由一个 run() 方法就搞定了,不得不再次感叹 SpringBoot 极致的封装性。
5. 发布事件
事件的发布由 ApplicationEventPublisher 接口完成:
1 2 3 4 5 6 7 8 @ FunctionalInterface
public interface ApplicationEventPublisher {
default void publishEvent ( ApplicationEvent event ) {
publishEvent ((Object) event);
}
void publishEvent ( Object event );
}
ApplicationContext 接口也是它的子接口,因此可以用 ApplicationContext 及其子类调用 publishEvent() 方法完成事件的发布。
调用 publishEvent() 方法后会进入“老熟人” AbstractApplicationContext 中:
1 2 3 public void publishEvent ( Object event) {
publishEvent (event , null ) ;
}
它又调用了内部的一个重载:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 protected void publishEvent ( Object event , @ Nullable ResolvableType typeHint) {
Assert . notNull (event, "Event must not be null" );
ResolvableType eventType = null ;
// Decorate event as an ApplicationEvent if necessary
ApplicationEvent applicationEvent ;
// 判断发布的事件是否是 ApplicationEvent 类型
if (event instanceof ApplicationEvent applEvent) {
applicationEvent = applEvent ;
eventType = typeHint ;
}
else {
ResolvableType payloadType = null ;
if (typeHint != null && ApplicationEvent . class . isAssignableFrom ( typeHint . toClass ()) ) {
eventType = typeHint ;
}
else {
payloadType = typeHint ;
}
// 如果不是,包装成 PayloadApplicationEvent
// 示例代码会走到这,并且 payloadType 依旧是 null
applicationEvent = new PayloadApplicationEvent <> ( this , event , payloadType) ;
}
// Determine event type only once (for multicast and parent publish)
if (eventType == null ) {
// 获取事件类型,类型由 ResolvableType 实例表示
eventType = ResolvableType . forInstance (applicationEvent);
if (typeHint == null ) {
typeHint = eventType ;
}
}
// Multicast right now if possible - or lazily once the multicaster is initialized
if ( this . earlyApplicationEvents != null ) {
// 启动阶段发布的事件
this . earlyApplicationEvents . add (applicationEvent);
}
else if ( this . applicationEventMulticaster != null ) {
// 使用 applicationEventMulticaster 广播事件
// 示例代码会走到这
this . applicationEventMulticaster . multicastEvent (applicationEvent, eventType);
}
// Publish event via parent context as well...
// 事件还支持父子容器,子容器发布的事件,父容器可以监听到
if ( this . parent != null ) {
if ( this . parent instanceof AbstractApplicationContext abstractApplicationContext) {
abstractApplicationContext . publishEvent (event, typeHint);
}
else {
this . parent . publishEvent (event);
}
}
}
根据最初的示例代码,发布的事件类型是 UserRegisterEvent。
按照 publishEvent() 方法的逻辑,UserRegisterEvent 实例会被包装成 PayloadApplicationEvent,事件类型 eventType 就是包装成的 PayloadApplicationEvent 实例对应的 ResolvableType,最后的发布事件会使用 applicationEventMulticaster 对该事件进行广播。
如果继续深入 applicationEventMulticaster.multicastEvent() 方法就会进入事件监听阶段,其实事件发布与监听是一个连贯的逻辑,本文将其分开意在让读者更便于理解。
6. 监听事件
前文中已经分析过 applicationEventMulticaster 其实是 SimpleApplicationEventMulticaster 实例,那么调用 multicastEvent() 方法就会进入该类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 @ Override
public void multicastEvent ( ApplicationEvent event , @ Nullable ResolvableType eventType) {
// 再次拿到事件类型
ResolvableType type = (eventType != null ? eventType : ResolvableType . forInstance (event) ) ;
// 获取一个线程池
Executor executor = getTaskExecutor () ;
// 遍历监听器
for ( ApplicationListener < ? > listener : getApplicationListeners (event , type)) {
// 如果存在线程池,并且监听器支持异步执行
if (executor != null && listener . supportsAsyncExecution () ) {
// 异步监听
try {
executor . execute (() -> invokeListener (listener, event));
}
catch ( RejectedExecutionException ex ) {
// Probably on shutdown -> invoke listener locally instead
invokeListener (listener , event) ;
}
}
else {
// 同步监听
invokeListener (listener , event) ;
}
}
}
根据这部分源码可知,监听器的执行还支持异步,实际使用时在监听器方法上标记 @Async 注解即可轻松实现,这里不再展开。
主要逻辑由两个:
调用 getApplicationListeners() 获取事件监听器
调用 invokeListener() 执行监听器
6.1 获取事件监听器
getApplicationListeners() 方法主要干两件事:
尝试从缓存中获取事件监听器,如果获取到,直接返回;
没获取到,执行 retrieveApplicationListeners() 检索监听器并放到缓存里。
不纠结缓存的实现,直接进入 retrieveApplicationListeners():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 private Collection < ApplicationListener < ? >> retrieveApplicationListeners (
ResolvableType eventType , @ Nullable Class < ? > sourceType , @ Nullable CachedListenerRetriever retriever) {
// 所有符合条件的监听器
List < ApplicationListener < ? >> allListeners = new ArrayList <> () ;
Set < ApplicationListener < ? >> filteredListeners = (retriever != null ? new LinkedHashSet <> () : null ) ;
Set < String > filteredListenerBeans = (retriever != null ? new LinkedHashSet <> () : null ) ;
Set < ApplicationListener < ? >> listeners ;
Set < String > listenerBeans ;
// 从 defaultRetriever 中获取监听器
synchronized ( this . defaultRetriever ) {
// 示例中的监听器就在这里面
listeners = new LinkedHashSet <> ( this . defaultRetriever . applicationListeners ) ;
// 以 Bean 形式存在的监听器
listenerBeans = new LinkedHashSet <> ( this . defaultRetriever . applicationListenerBeans ) ;
}
// Add programmatically registered listeners, including ones coming
// from ApplicationListenerDetector (singleton beans and inner beans).
for ( ApplicationListener < ? > listener : listeners) {
// 判断监听器是否支持当前事件
if ( supportsEvent (listener , eventType , sourceType)) {
// 添加到缓存
if (retriever != null ) {
filteredListeners . add (listener);
}
// 添加到结果集
allListeners . add (listener);
}
}
// --snip--
return allListeners ;
}
逻辑比较多,只截取重点。
已知的是 listeners 中存在示例中的监听器,接着需要通过 supportsEvent() 方法来过滤:
1 2 3 4 5 6 7 protected boolean supportsEvent (
ApplicationListener < ? > listener , ResolvableType eventType , @ Nullable Class < ? > sourceType) {
GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener gal ? gal :
new GenericApplicationListenerAdapter (listener)) ;
return ( smartListener . supportsEventType (eventType) && smartListener . supportsSourceType (sourceType) ) ;
}
在判断的时候会包装成 GenericApplicationListener 进行判断。
回顾下前文中介绍了监听器方法会被包装成 ApplicationListenerMethodAdapter:
1 2 3 public class ApplicationListenerMethodAdapter implements GenericApplicationListener {
// --snip--
}
它刚好是 GenericApplicationListener 的子类。
就看这类名,可以断定出 Spring 能够支持带泛型的事件。
接下里会调用 supportsEventType() 和 supportsSourceType() 判断监听器是否支持当前发布的事件。
supportsSourceType() 总是返回 true,没啥好说的:
1 2 3 4 @ Override
public boolean supportsSourceType ( @ Nullable Class < ? > sourceType) {
return true ;
}
supportsEventType() 方法中会使用 declaredEventTypes 成员变量,它在构造函数中通过调用 resolveDeclaredEventTypes() 进行初始化:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 private static List < ResolvableType > resolveDeclaredEventTypes ( Method method , @ Nullable EventListener ann) {
// 获取方法参数个数
int count = ( KotlinDetector . isSuspendingFunction (method) ? method . getParameterCount () - 1 : method . getParameterCount () ) ;
// 参数个数不能大于 1
if (count > 1 ) {
throw new IllegalStateException (
"Maximum one parameter is allowed for event listener method: " + method) ;
}
if (ann != null ) {
// 如果注解的 classes 属性有值
Class < ? > [] classes = ann . classes ();
if ( classes . length > 0 ) {
List < ResolvableType > types = new ArrayList <> ( classes . length ) ;
for ( Class < ? > eventType : classes) {
// 将 classes 转换成 ResolvableType 后返回
types . add ( ResolvableType . forClass (eventType));
}
// 也就是说,如果指定了 classes,会忽略监听方法的参数
// classes 的优先级更高
return types ;
}
}
// classes 没值,方法参数个数也为 0
if (count == 0 ) {
throw new IllegalStateException (
"Event parameter is mandatory for event listener method: " + method) ;
}
// 否则取第一个参数的 ResolvableType
return Collections . singletonList ( ResolvableType . forMethodParameter (method, 0 ));
}
declaredEventTypes 表示当前监听器支持哪些类型的事件。
回到 supportsEventType() 方法中,但在阅读源码前别忘记示例中的事件类型已经被包装成 PayloadApplicationEvent<UserRegisterEvent>,而不是原始类型:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 // eventType --> PayloadApplicationEvent<UserRegisterEvent>
@ Override
public boolean supportsEventType ( ResolvableType eventType) {
// 遍历监听器支持的事件类型,示例中的是 UserRegisterEvent
for ( ResolvableType declaredEventType : this . declaredEventTypes ) {
// 判断事件类型中是否有无法解析的泛型参数
if ( eventType . hasUnresolvableGenerics () ?
declaredEventType . toClass (). isAssignableFrom ( eventType . toClass ()) :
// 会走到这
// 判断 UserRegisterEvent 与 PayloadApplicationEvent<UserRegisterEvent>
// 显然不满足
declaredEventType . isAssignableFrom (eventType) ) {
return true ;
}
if ( PayloadApplicationEvent . class . isAssignableFrom ( eventType . toClass ()) ) {
// 是否存在无法解析的泛型参数
if ( eventType . hasUnresolvableGenerics () ) {
return true ;
}
// 获取 eventType 的泛型参数信息,相当于拿到 UserRegisterEvent
ResolvableType payloadType = eventType . as ( PayloadApplicationEvent . class ). getGeneric ();
// 那这个判断肯定满足了
if ( declaredEventType . isAssignableFrom (payloadType) ) {
return true ;
}
}
}
return false ;
}
现在已经拿到能够监听发布的事件的监听器了,那这个监听器要怎么执行呢?
6.2 执行监听器
回到 SimpleApplicationEventMulticaster#multicastEvent() 中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @ Override
public void multicastEvent ( ApplicationEvent event , @ Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : ResolvableType . forInstance (event) ) ;
Executor executor = getTaskExecutor () ;
for ( ApplicationListener < ? > listener : getApplicationListeners (event , type)) {
if (executor != null && listener . supportsAsyncExecution () ) {
try {
executor . execute (() -> invokeListener (listener, event));
}
catch ( RejectedExecutionException ex ) {
// Probably on shutdown -> invoke listener locally instead
invokeListener (listener , event) ;
}
}
else {
invokeListener (listener , event) ;
}
}
}
遍历监听器时,将调用 invokeListener() 方法执行监听器,其内部又会调用 doInvokeListener():
1 2 3 4 5 6 7 8 9 @ SuppressWarnings ({ "rawtypes" , "unchecked" })
private void doInvokeListener ( ApplicationListener listener , ApplicationEvent event) {
try {
listener . onApplicationEvent (event);
}
catch ( ClassCastException ex ) {
// --snip--
}
}
最终其实是调用了 ApplicationListener 的 onApplicationEvent() 方法来执行监听器。
还记得示例中的监听器方法会被包装成哪个对象吗?
ApplicationListenerMethodAdapter。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @ Override
public void onApplicationEvent ( ApplicationEvent event) {
processEvent (event) ;
}
public void processEvent ( ApplicationEvent event) {
Object [] args = resolveArguments (event) ;
if ( shouldHandle (event , args)) {
Object result = doInvoke (args) ;
if (result != null ) {
handleResult (result) ;
}
else {
logger . trace ( "No result object given - no result to handle" );
}
}
}
内部有四个主要逻辑:
resolveArguments()
shouldHandle()
doInvoke()
handleResult()
resolveArguments():根据传入的 ApplicationEvent 实例,获取执行监听器方法时使用的参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 protected Object [] resolveArguments ( ApplicationEvent event) {
// 获取参数类型
ResolvableType declaredEventType = getResolvableType (event) ;
if (declaredEventType == null ) {
return null ;
}
// 方法没有参数
if ( this . method . getParameterCount () == 0 ) {
return new Object [ 0 ] ;
}
Class < ? > declaredEventClass = declaredEventType . toClass ();
// 参数类型不是 ApplicationEvent,而是 PayloadApplicationEvent
if ( ! ApplicationEvent . class . isAssignableFrom (declaredEventClass) &&
event instanceof PayloadApplicationEvent < ? > payloadEvent) {
// 拿到内部的 payload
Object payload = payloadEvent . getPayload ();
// 判断 payload 的类型是否与参数类型一直
if ( declaredEventClass . isInstance (payload) ) {
return new Object [] {payload} ;
}
}
// 否则,直接返回
return new Object [] {event} ;
}
里面又调用了 getResolvableType() 来获取参数类型:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 private ResolvableType getResolvableType ( ApplicationEvent event) {
ResolvableType payloadType = null ;
// 如果是 PayloadApplicationEvent,就用拿它的泛型类型
if (event instanceof PayloadApplicationEvent < ? > payloadEvent) {
ResolvableType eventType = payloadEvent . getResolvableType ();
if (eventType != null ) {
payloadType = eventType . as ( PayloadApplicationEvent . class ). getGeneric ();
}
}
// 遍历当前监听器支持的事件类型
for ( ResolvableType declaredEventType : this . declaredEventTypes ) {
Class < ? > eventClass = declaredEventType . toClass ();
// 支持的事件类型与 payload 的类型一样
if ( ! ApplicationEvent . class . isAssignableFrom (eventClass) &&
payloadType != null && declaredEventType . isAssignableFrom (payloadType) ) {
return declaredEventType ;
}
// 支持的事件类型就是 event 对应的类型
if ( eventClass . isInstance (event) ) {
return declaredEventType ;
}
}
return null ;
}
shouldHandle():根据包装的事件、执行监听器需要的参数判断是否应该执行监听器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 private boolean shouldHandle ( ApplicationEvent event , @ Nullable Object [] args) {
if (args == null ) {
return false ;
}
// 获取监听器的执行条件
// 也就是 @EventListener 注解上的 condition 属性值
String condition = getCondition () ;
// 如果有值
if ( StringUtils . hasText (condition) ) {
Assert . notNull ( this . evaluator , "EventExpressionEvaluator must not be null" );
// 这个值是 SPEL 表达式,计算这个表达式,判断是否满足条件
return this . evaluator . condition (
condition, event, this . targetMethod , this . methodKey , args);
}
// 没有值直接返回 true
return true ;
}
doInvoke():执行事件监听器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 @ Nullable
protected Object doInvoke ( @ Nullable Object ... args ) {
// 获取监听器方法所在类对应的 Bean
Object bean = getTargetBean () ;
// Detect package-protected NullBean instance through equals(null) check
if ( bean . equals ( null ) ) {
return null ;
}
// 设置访问权限
ReflectionUtils . makeAccessible ( this . method );
try {
// Kotlin 相关,忽略
if ( KotlinDetector . isSuspendingFunction ( this . method ) ) {
return CoroutinesUtils . invokeSuspendingFunction ( this . method , bean, args);
}
// 反射调用方法
return this . method . invoke (bean, args);
}
catch ( IllegalArgumentException ex ) {
// --snip--
}
}
看到这里,顿时恍然大悟,搞了半天,最终还是利用反射去执行的监听器方法。😞
handleResult():如果监听器方法还有返回值,继续处理返回值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 @ SuppressWarnings ({ "deprecation" , "unchecked" })
protected void handleResult ( Object result) {
// 响应式相关
if (reactiveStreamsPresent && new ReactiveResultHandler () . subscribeToPublisher (result) ) {
if ( logger . isTraceEnabled () ) {
logger . trace ( "Adapted to reactive result: " + result);
}
}
else if (result instanceof CompletionStage < ? > completionStage) {
// 返回的是否是 CompletionStage 类型,比如 CompletableFuture
completionStage . whenComplete ((event, ex) -> {
if (ex != null ) {
handleAsyncError (ex);
}
else if (event != null ) {
// 将结果作为事件,又发布
publishEvents (event);
}
});
}
else if (result instanceof org . springframework . util . concurrent . ListenableFuture < ? > listenableFuture) {
// Spring 6.0 已标记为过期,忽略
// 使用 CompletableFuture 代替
listenableFuture . addCallback ( this :: publishEvents, this :: handleAsyncError);
}
else {
// 将结果作为事件,又发布
publishEvents (result) ;
}
}
调用 publishEvents() 方法,将当前事件监听器方法的返回值作为事件再次发布:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 private void publishEvents ( @ Nullable Object result) {
// 如果返回数组,
if (result != null && result . getClass (). isArray () ) {
Object [] events = ObjectUtils . toObjectArray (result);
for ( Object event : events) {
publishEvent (event) ;
}
}
else if (result instanceof Collection < ? > events) {
for ( Object event : events) {
publishEvent (event) ;
}
}
else {
publishEvent (result) ;
}
}
private void publishEvent ( @ Nullable Object event) {
if (event != null ) {
Assert . notNull ( this . applicationContext , "ApplicationContext must not be null" );
this . applicationContext . publishEvent (event);
}
}
也就是说,Spring 的事件监听机制支持“事件链(我编的词 😂)”。
修改原先的示例,试一下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 @ SpringBootApplication
public class SimpleSpringEventListenerTest {
public static void main ( String [] args ) {
ConfigurableApplicationContext context = SpringApplication . run ( SimpleSpringEventListenerTest . class , args);
context . publishEvent ( new UserRegisterEvent ( "成功注册用户: mofan" ));
context . close ();
}
@ Slf4j
@ Component
private static class UserRegisterEventListener {
@ EventListener
public EventChain doEvent ( UserRegisterEvent event ) {
log . info ( "监听到用户注册事件: {}" , event . info ());
return new EventChain ( "事件链" );
}
@ EventListener
public void doChain ( EventChain chain ) {
log . info ( "监听到事件链: {}" , chain . info ());
}
}
private record UserRegisterEvent ( String info) {
}
private record EventChain ( String info) {
}
}
运行 main() 方法后,控制台打印出:
监听到用户注册事件: 成功注册用户: mofan
监听到事件链: 事件链
7. 总结
Spring 的事件机制并不难,其实现基本与先前的猜想一致:
容器启动阶段遍历所有的 Bean,解析 @EventListener 注解,包装成事件监听器
发布事件后,遍历所有的事件监听器,找到支持对应事件类型的监听器,反射调用方法,完成监听器的执行
基本原理不难,但经过 SpringBoot 的层层封装后使得整条执行链路变得很长。如果对容器的启动过程、Spring 中的工具类不熟,那整个源码阅读过程就会变得异常艰辛。
还是那句话,哪有什么岁月静好,都是 SpringBoot 在为你负重前行。👻