这个系列分为5篇
1. @Component,@Service等注解是如何被解析的
2. @Enableq驱动原理(最晚20200705)
3. @EnableAutoConfiguration处理逻辑
4. spring,springBoot事件
5.自定义springboot starter(最晚20200726)
spring事件机制,有3个核心部分,事件,监听方式,广播器,下面我们分别介绍。
spring的事件的API对应ApplicationEvent。它继承了ava.util.EventObject。显示调用父类构造器传递事件源。
public abstract class ApplicationEvent extends EventObject { ///省略其他代码 public ApplicationEvent(Object source) { super(source); this.timestamp = System.currentTimeMillis(); } //省略其他代码 }复制代码
事件名 | 注释 |
ContextRefreshedEvent | Spring应用上下文就绪事件 |
ContextStartedEvent | Spring应用上下文启动事件 |
ContextStopedEvent | Spring应用上下文停止事件 |
ContextClosedEvent | Spring应用上下文关闭事件 |
允许泛型事件自定义,如果有兴趣可以参看: org.springframework.context.PayloadApplicationEvent
1. 实现ApplicationListener接口 或 @EventListener,可监听1到多种事件,支持泛型事件
2. @EventListener方法上@Async,可使用@EventListener方法异步化,但是被注解的方法的返回值应该为void,其实返回值没有意义。
表@EventListener的同步与异步区别
方法类型 | 访问修饰符 | 返回类型 | 参数数量 | 参数类型 | 备注 |
同步 | public | 任意类型 | 0或1 | 监听事件类 型或其子类 |
会将返回值 作为事件向 后传播 |
异步 | public | void | 0或1 | 监听事件类 型或其子类 |
如果出错不 会传播给调 用者。 不会向后传 播事件 |
EventListenerMethodProcessor 就是处理@EventListener注解的入口类
找主要方法
1.将@
EventListener方法转换为
ApplicationListener示例
2.实现
BeanFactoryPostProcessor用于检索
EventListenerFactory
避免AOP增强,EventListenerFactory
在查看, EventListenerMethodProcessor的类图
ApplicationContextAware 用于注入ApplicationContext。
BeanFactoryPostProcessor根据类注释可知用于获取EventListenerFactory。
这里最需要关注的应该是SmartInitializingSingleton#afterSingletonsInstantiated方法。
查看该方法的注释
public interface SmartInitializingSingleton { /** * 预实例化完成之后调用,保证所有常规单例Bean创建完毕 * 调用ListableBeanFactory#getBeansOfType没有任何副作用 * 注意: * 对于延迟加载的单例Bean,不会触发这个回调。 * 并且其他作用域的Bean,也不会触发这个回调。 * 谨慎使用,应仅用于引导功能。 */ void afterSingletonsInstantiated(); }复制代码
afterSingletonsInstantiated 从方法注释上可以看出,这个方法可以用于引导功能。
查看源码EventListenerMethodProcessor ,逻辑就是找BeanName和Bean对应的Type,具体逻辑委托给 processBean,下面是processBean的源码
public class EventListenerMethodProcessor { //省略其他部分 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)) { this.nonAnnotatedClasses.add(targetType); if (logger.isTraceEnabled()) { logger.trace("No @EventListener annotations found on bean class: " + targetType.getName()); } } else { // Non-empty set of methods ConfigurableApplicationContext context = this.applicationContext; Assert.state(context != null, "No ApplicationContext set"); List<EventListenerFactory> factories = this.eventListenerFactories; Assert.state(factories != null, "EventListenerFactory List not initialized"); for (Method method : annotatedMethods.keySet()) { for (EventListenerFactory factory : factories) { if (factory.supportsMethod(method)) { Method methodToUse = AopUtils.selectInvocableMethod(method, context.getType(beanName)); //通过EventListenerFactory转换为ApplicationListenerMethodAdapter 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); } } } } }复制代码
AopUtils.selectInvocableMethod 是不允许访问,私有方法,静态方法,代理的方法,也就印证了 @EventListener 必须用public修饰
概要逻辑
1.这个方法的逻辑就是将@EventListener的方法,
EventListenerFactory转换为
3.该事件监听器注册上线文中。
1. EventListenerMethodProcessor 是@EventListener的生命周期处理器,实现了 SmartInitializingSingleton接口的afterSingletonsInstantiated 方法,进行了:
EventListenerFactory转换为
2. DefaultEventListenerFactory是@EventListener方法与ApplicationListener的适配工厂
3. ApplicationListenerMethodAdapter为适配类。
广播器为ApplicationEventMulticaster,它的默认实现为SimpleApplicationEventMulticaster
它主要有2个责任,维护ApplicationListener关联关系这个比较简单,我们关注下广播消息。
@Override public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) { ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event)); Executor executor = getTaskExecutor(); for (ApplicationListener<?> listener : getApplicationListeners(event, type)) { if (executor != null) { executor.execute(() -> invokeListener(listener, event)); } else { invokeListener(listener, event); } } }复制代码
调用getApplicationListeners,遍历调用onApplicationEvent(ApplicationEvent)。
查看getApplicationListeners方法在其父类 AbstractApplicationEventMulticaster中。
protected Collection<ApplicationListener<?>> getApplicationListeners( ApplicationEvent event, ResolvableType eventType) { Object source = event.getSource(); Class<?> sourceType = (source != null ? source.getClass() : null); ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType); // Quick check for existing entry on ConcurrentHashMap... ListenerRetriever retriever = this.retrieverCache.get(cacheKey); if (retriever != null) { return retriever.getApplicationListeners(); } if (this.beanClassLoader == null || (ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) && (sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) { // Fully synchronized building and caching of a ListenerRetriever synchronized (this.retrievalMutex) { retriever = this.retrieverCache.get(cacheKey); if (retriever != null) { return retriever.getApplicationListeners(); } retriever = new ListenerRetriever(true); Collection<ApplicationListener<?>> listeners = retrieveApplicationListeners(eventType, sourceType, retriever); this.retrieverCache.put(cacheKey, retriever); return listeners; } } else { // No ListenerRetriever caching -> no synchronization necessary return retrieveApplicationListeners(eventType, sourceType, null); } }复制代码
内部维护一个final Map<ListenerCacheKey, ListenerRetriever> retrieverCache 维护事件类型与数据源的类型
ListenerCacheKey为eventType(对应泛型或者事件类本身) 和sourceType(ApplicationEvent构造器中的source),(对应ApplicationEvent)。
1. SimpleApplicationEventMulticaster承担2个职责,关联ApplicationListener,广播ApplicationEvent。
2。 SimpleApplicationEventMulticaster 内部维护一个final Map<ListenerCacheKey, ListenerRetriever> retrieverCache 维护事件类型与数据源的类型
3. ListenerCacheKey为eventType(对应泛型或者事件类本身) 和sourceType(ApplicationEvent构造器中的source)
4. ListenerRetriever是AbstractApplicationEventMulticaster的内部类,对应ApplicationListener集合
5 .ApplicationEventMulticaster广播事件,multicastEvent(ApplicationEvent)和multicastEvent(ApplicationEvent,ResolvableType)
内部调用getApplicationListeners,遍历调用onApplicationEvent(ApplicationEvent)
补充说明:
通过ApplicationEventPublisherAware获得的ApplicationEventPublisher,是什么?
解决这个,就需要查看ApplicationContextAwareProcessor#postProcessBeforeInitialization
内部调用了 invokeAwareInterfaces方法,处理各种Aware接口的注入逻辑。
private void invokeAwareInterfaces(Object bean) { if (bean instanceof EnvironmentAware) { ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment()); } if (bean instanceof EmbeddedValueResolverAware) { ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver); } if (bean instanceof ResourceLoaderAware) { ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext); } if (bean instanceof ApplicationEventPublisherAware) { ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext); } if (bean instanceof MessageSourceAware) { ((MessageSourceAware) bean).setMessageSource(this.applicationContext); } if (bean instanceof ApplicationContextAware) { ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext); } }复制代码
看到这里,答案就有了。ApplicationEventPublisherAware所获得的ApplicationEventPublisher实例就是当前的ApplicationContext。
SpringBoot事件继承ApplicationEvent,也是SpringApplicationEvent的子类
SpringBoot事件源是SpringApplication,内部事件根据EventPublishingRunListener的生命周期回调方法依次发布。
ApplicationStartingEvent 1.5出现
ApplicationEnvironmentPreparedEvent
ApplicationPreparedEvent
ApplicationStartedEvent
ApplicationReadyEvent, spring应用上下文之后发布
ApplicationFailedEvent, spring应用上下文之后发布
SpringApplication关联的SpringApplication关联ApplicationListener
1.class-path下,META-INF/spring.factories资源中的ApplicationListener对象集合
2.SpringApplication#addListeners(...)或SpringApplicationBuilder#listeners(...)显示装配
SimpleApplicationEventMulticaster,是特定的,2.0以后不与spring framework共用。