封面来源:碧蓝航线 愚者的天平 活动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); ResolvableType hashMapType = myMapType.getSuperType(); ResolvableType firstGenericType = hashMapType.getGeneric(0 ); Class<?> firstGenericClazz = firstGenericType.resolve(); assertThat(firstGenericClazz).isEqualTo(String.class); 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 fooType = type.as(Foo.class); assertThat(fooType.toString()).contains("Foo<java.lang.String>" ); 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>>" ); 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); 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>>" ); 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 { }
实现了三个经典的拓展点,关于这些拓展点的使用方式、加载时机、执行时机可以参考 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 private ApplicationContextFactory applicationContextFactory = ApplicationContextFactory.DEFAULT;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) { for (ApplicationContextFactory candidate : SpringFactoriesLoader.loadFactories(ApplicationContextFactory.class, getClass().getClassLoader())) { T result = action.apply(candidate, webApplicationType); if (result != null ) { return result; } } 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 { @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); this .reader = new AnnotatedBeanDefinitionReader (this ); this .scanner = new ClassPathBeanDefinitionScanner (this ); } public AnnotationConfigApplicationContext () { StartupStep createAnnotatedBeanDefReader = getApplicationStartup().start("spring.context.annotated-bean-reader.create" ); 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) { Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet <>(8 ); 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)); } 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)); 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; for (Method method : annotatedMethods.keySet()) { for (EventListenerFactory factory : factories) { if (factory.supportsMethod(method)) { Method methodToUse = AopUtils.selectInvocableMethod(method, context.getType(beanName)); ApplicationListener<?> applicationListener = factory.createApplicationListener(beanName, targetType, methodToUse); if (applicationListener instanceof ApplicationListenerMethodAdapter alma) { alma.init(context, this .evaluator); } context.addApplicationListener(applicationListener); 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(); 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 { 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() + "]" ); } } }
总的来说,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) { 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 ; 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; } applicationEvent = new PayloadApplicationEvent <>(this , event, payloadType); } if (eventType == null ) { eventType = ResolvableType.forInstance(applicationEvent); if (typeHint == null ) { typeHint = eventType; } } if (this .earlyApplicationEvents != null ) { this .earlyApplicationEvents.add(applicationEvent); } else if (this .applicationEventMulticaster != null ) { this .applicationEventMulticaster.multicastEvent(applicationEvent, eventType); } 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) { 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; synchronized (this .defaultRetriever) { listeners = new LinkedHashSet <>(this .defaultRetriever.applicationListeners); listenerBeans = new LinkedHashSet <>(this .defaultRetriever.applicationListenerBeans); } for (ApplicationListener<?> listener : listeners) { if (supportsEvent(listener, eventType, sourceType)) { if (retriever != null ) { filteredListeners.add(listener); } allListeners.add(listener); } } 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 { }
它刚好是 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()); if (count > 1 ) { throw new IllegalStateException ( "Maximum one parameter is allowed for event listener method: " + method); } if (ann != null ) { Class<?>[] classes = ann.classes(); if (classes.length > 0 ) { List<ResolvableType> types = new ArrayList <>(classes.length); for (Class<?> eventType : classes) { types.add(ResolvableType.forClass(eventType)); } return types; } } if (count == 0 ) { throw new IllegalStateException ( "Event parameter is mandatory for event listener method: " + method); } 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 @Override public boolean supportsEventType (ResolvableType eventType) { for (ResolvableType declaredEventType : this .declaredEventTypes) { if (eventType.hasUnresolvableGenerics() ? declaredEventType.toClass().isAssignableFrom(eventType.toClass()) : declaredEventType.isAssignableFrom(eventType)) { return true ; } if (PayloadApplicationEvent.class.isAssignableFrom(eventType.toClass())) { if (eventType.hasUnresolvableGenerics()) { return true ; } 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) { 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) { } }
最终其实是调用了 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(); if (!ApplicationEvent.class.isAssignableFrom(declaredEventClass) && event instanceof PayloadApplicationEvent<?> payloadEvent) { Object payload = payloadEvent.getPayload(); 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 ; 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(); if (!ApplicationEvent.class.isAssignableFrom(eventClass) && payloadType != null && declaredEventType.isAssignableFrom(payloadType)) { return declaredEventType; } 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 ; } String condition = getCondition(); if (StringUtils.hasText(condition)) { Assert.notNull(this .evaluator, "EventExpressionEvaluator must not be null" ); return this .evaluator.condition( condition, event, this .targetMethod, this .methodKey, args); } 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) { Object bean = getTargetBean(); if (bean.equals(null )) { return null ; } ReflectionUtils.makeAccessible(this .method); try { if (KotlinDetector.isSuspendingFunction(this .method)) { return CoroutinesUtils.invokeSuspendingFunction(this .method, bean, args); } return this .method.invoke(bean, args); } catch (IllegalArgumentException ex) { } }
看到这里,顿时恍然大悟,搞了半天,最终还是利用反射去执行的监听器方法。😞
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.whenComplete((event, ex) -> { if (ex != null ) { handleAsyncError(ex); } else if (event != null ) { publishEvents(event); } }); } else if (result instanceof org.springframework.util.concurrent.ListenableFuture<?> listenableFuture) { 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 在为你负重前行。👻