Spring 中的事件发布与监听
Posted T.Y.Bao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring 中的事件发布与监听相关的知识,希望对你有一定的参考价值。
主要代码在org.springframework.context
,org.springframework.context.event
包中
事件发布与监听主要包含以下角色:
- 事件:
ApplicationEvent
- 事件监听器:
ApplicationListener
SmartApplicationListener
GenericApplicationListener
- 事件发布器:
ApplicationEventPublisher
- 事件广播器:
ApplicationEventMulticaster
引入ApplicationListener
有两种方式:
- spring spi
- 手动注入bean
手动注入bean有两种方式:
- 类上注解
@Component
等注解+实现ApplicationListener
接口 - 类上注解
@Component
等注解+方法上注解@EventListener
案例如下:
// bean注入方式一,实现ApplicationListener+@Component注入bean
@Component
public class HelloEventListener implements SmartApplicationListener
@Override
public boolean supportsEventType(Class<? extends ApplicationEvent> eventType)
return false;
@Override
public void onApplicationEvent(ApplicationEvent event)
// bean注入方式二,@EventListener+@Component
@Component
public class Test
@EventListener
public void listen(Object obj)
System.out.println("listening");
@EventListener(classes=ApplicationEvent.class,condition="springEL")
public void listen(ApplicationEvent event)
System.out.println("listening");
关于@EventListener
注解方法注入是通过EventListenerMethodProcessor
的一个SmartInitializingSingleton
,同时该类也是一个BeanFactoryPostProcessor
,但扫描@EventListener
方法和注入逻辑不在该接口的postProcess
方法中,而是SmartInitializingSingleton
接口的afterSingletonsInstantiated
方法。
关于SmartInitializingSingleton
的接口作用注释如下:
Callback interface triggered at the end of the singleton pre-instantiation phase during
BeanFactory
bootstrap. This interface can be implemented by singleton beans in order to perform some initialization after the regular singleton instantiation algorithm, avoiding side effects with accidental early initialization (e.g. from ListableBeanFactory.getBeansOfType calls). In that sense, it is an alternative toInitializingBean
which gets triggered right at the end of a bean’s local construction phase.
看到其作用和 InitializingBean
类似,用于构造函数后的初始化操作。
public class EventListenerMethodProcessor
implements SmartInitializingSingleton, ApplicationContextAware, BeanFactoryPostProcessor
// 负责设置EventListenerFactory
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
// 回调beanFactory赋值
this.beanFactory = beanFactory;
// 拿到所有的EventListenerFactory
Map<String, EventListenerFactory> beans = beanFactory.getBeansOfType(EventListenerFactory.class, false, false);
List<EventListenerFactory> factories = new ArrayList<>(beans.values());
AnnotationAwareOrderComparator.sort(factories);
// 设置eventListenerFactories
this.eventListenerFactories = factories;
@Override
public void afterSingletonsInstantiated()
...
processBean(beanName, type);
...
private void processBean(final String beanName, final Class<?> targetType)
if (
// 不包含@EventListener的类的备忘录是否有该类型
!this.nonAnnotatedClasses.contains(targetType) &&
// 该类型的type, method or field 是否能被注解@EventListener
AnnotationUtils.isCandidateClass(targetType, EventListener.class) &&
// 不能是org.springframework开头的类,或者被注解了@Component,注意是或者
!isSpringContainerClass(targetType)
)
// 提取所有的方法
Map<Method, EventListener> annotatedMethods = null;
try
annotatedMethods = MethodIntrospector.selectMethods(targetType,
(MethodIntrospector.MetadataLookup<EventListener>) method ->
AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class));
...
if (CollectionUtils.isEmpty(annotatedMethods))
// 备忘录,加入已扫描的没有注解@EventListener的类
this.nonAnnotatedClasses.add(targetType);
...
else
// Non-empty set of methods
ConfigurableApplicationContext context = this.applicationContext;
Assert.state(context != null, "No ApplicationContext set");
List<EventListenerFactory> factories = this.eventListenerFactories;
Assert.state(factories != null, "EventListenerFactory List not initialized");
for (Method method : annotatedMethods.keySet())
for (EventListenerFactory factory : factories)
if (factory.supportsMethod(method))
Method methodToUse = AopUtils.selectInvocableMethod(method, context.getType(beanName));
// 生成ApplicationListener
ApplicationListener<?> applicationListener =
factory.createApplicationListener(beanName, targetType, methodToUse);
if (applicationListener instanceof ApplicationListenerMethodAdapter)
((ApplicationListenerMethodAdapter) applicationListener).init(context, this.evaluator);
context.addApplicationListener(applicationListener);
break;
...
事务消息监听器
spring-tx
包下提供TransactionalApplicationListener
接口和@TransactionalEventListener
注解。
TransactionalApplicationListener
接口:An ApplicationListener that is invoked according to a TransactionPhase. NOTE: Transactional event listeners only work with thread-bound transactions managed by a PlatformTransactionManager.
以上是关于Spring 中的事件发布与监听的主要内容,如果未能解决你的问题,请参考以下文章
企业级spring-boot案例-Spring事件发布与监听
企业级spring-boot案例-Spring事件发布与监听
企业级spring-boot案例-Spring事件发布与监听