注解说明
Annotation that marks a method as a listener for application events.
以注解的方式将一个方法标记为事件监听器。如果对于spring事件监听机制还不了解的小伙伴点击查看一文彻底搞懂spring事件监听机制
属性说明
public @interface EventListener {
/**
* 同class
*/
@AliasFor("classes")
Class<?>[] value() default {};
/**
* 监听事件的类型
* 如果这个属性长度不为空,则以这个属性的为准
* 如果这个属性长度为空,则以被标注方法的参数为准
*/
@AliasFor("value")
Class<?>[] classes() default {};
/**
* 以spring表达的方式计算事件监听是否需要触发
*/
String condition() default "";
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
通过上述属性,我们可以发现,相比起实现接口的方式创建事件监听器,用注解的方式灵活性更加大,不仅可以指定多个接受事件类型,还可以增加是否触发的条件。
使用示例
@EventListener
public void customListener1(MyEvent event) {
System.out.println("接受事件customListener1");
}
- 1.
- 2.
- 3.
- 4.
相关源码
EventListenerMethodProcessor
/**
* 检测bean里面是否包含 @EventListener
*/
private void processBean(final String beanName, final Class<?> targetType) {
if (!this.nonAnnotatedClasses.contains(targetType) &&
!targetType.getName().startsWith("java") &&
!isSpringContainerClass(targetType)) {
Map<Method, EventListener> annotatedMethods = null;
try {
// 找到所有包含 @EventListener 的方法
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)) {
// 如果这个类一个包含 @EventListener 方法都没有则缓存到 nonAnnotatedClasses 中,减少重复计算
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");
// 可以创建自定义 EventListenerFactory,如果不创建,默认拥有 DefaultEventListenerFactory
List<EventListenerFactory> factories = this.eventListenerFactories;
Assert.state(factories != null, "EventListenerFactory List not initialized");
for (Method method : annotatedMethods.keySet()) {
for (EventListenerFactory factory : factories) {
// 对于每一个方法遍历所有的工厂,找到一个支持的工厂就进入创建并完成遍历
if (factory.supportsMethod(method)) {
// 根据方法创建 applicationListener,并将 applicationListener 添加给容器
Method methodToUse = AopUtils.selectInvocableMethod(method, context.getType(beanName));
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);
}
}
}
}
- 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.
在
EventListenerMethodProcessor的processBean方法中,会遍历已经注册的所有的bean,找到包含有被 @EventListener 标注的方法。这些方法会被遍历已经创建的 EventListenerFactory 找到合适的工厂来生成 applicationListener,并将 applicationListener 注册到容器的事件监听器列表。
ApplicationListenerMethodAdapter
/**
* 解析时间监听器支持的事件类型
*/
private static List<ResolvableType> resolveDeclaredEventTypes(Method method, @Nullable EventListener ann) {
int count = method.getParameterCount();
if (count > 1) {
// 如果方法本身参数超过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) {
// 如果classes属性不为空,则解析classes属性并返回作为事件解析类型
List<ResolvableType> types = new ArrayList<>(classes.length);
for (Class<?> eventType : classes) {
types.add(ResolvableType.forClass(eventType));
}
return types;
}
}
// 如果传入的classes属性为空,并且方法没有参数,也抛出异常
if (count == 0) {
throw new IllegalStateException(
"Event parameter is mandatory for event listener method: " + method);
}
return Collections.singletonList(ResolvableType.forMethodParameter(method, 0));
}
- 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.
ApplicationListenerMethodAdapter的resolveDeclaredEventTypes方法会解析@EventListener标签的classes属性,然后根据这个属性决定事件监听器的监听的事件类型。
如果方法参数个数超过1个,直接抛出异常。这是一个事件触发以后,如果接受的方法参数个数大于1个,spring没办法给方法进行传参。
如果classes属性为空,并且方法参数个数为0个,也抛出异常。这是因为spring无法推断这个监听器需要支持什么类型的事件。
除去上面两种情况,解析都是成功,同时classes属性会优先被选择为监听的事件类型。
private boolean shouldHandle(ApplicationEvent event, @Nullable Object[] args) {
if (args == null) {
return false;
}
String condition = getCondition();
if (StringUtils.hasText(condition)) {
// 如果 condition 属性不为空,则进行spring表达式计算结果并返回
Assert.notNull(this.evaluator, "EventExpressionEvaluator must not be null");
return this.evaluator.condition(
condition, event, this.targetMethod, this.methodKey, args, this.applicationContext);
}
return true;
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
ApplicationListenerMethodAdapter的shouldHandle方法会根据@EventListener标签的condition属性判断是否需要推送消息。
如果condition不为空,则使用spring表达式计算condition得到结果,结果为true的时候才推送事件。如果condition为空,则不判断直接推送。