这是我参与8月更文挑战的第20天,活动详情查看:8月更文挑战
2.4 postProcessBeanFactory(beanFactory); 这是一个扩展方法, 可以初始化剩余的Aware.
我们是AbstractApplicationContext没有实现, 但AbstractRefreshableWebApplicationContext类. 里面就定义了postProcessBeanFactory(beanFactory)
在里面注册了ServletContextAwareProcessor
beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig));
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
beanFactory.ignoreDependencyInterface(ServletConfigAware.class);
上面我们知道在 BeanFactory 里定义了需要调用的很多Aware. 但是有几个Aware还没有说到.
比如: ServletContextAware's {@code setServletContext} : ServletContextAware, 可以获得当前的ServletContextAware
添加了这个Aware以后, 我们就可以实现一个ServletContextAware的接口.
到这里, 我们就知道所有的aware都在哪里被调用了.
2.5 调用bean工厂的后置处理器, 解析配置类
这一步就略过了,之前重点说过这一步
2.6 registerBeanPostProcessors(beanFactory); 注册bean后置处理器, 这里主要是和AOP有关系
这里和监听器关系不太大, 也暂时略过
2.7 initMessageSource(); 初始化国际化资源处理器
2.8 initApplicationEventMulticaster();创建事件多播器
事件多播器管理所有的事件监听器. 并广播事件给对应的监听器
当我们调用ctx.publishEvent(new OrderEvent(order, "减库存"))的时候. 就会去通知所有监听了OrderEvent事件的事件监听器,
那么, 是由谁去负责通知呢?
就是由EventMulticaster(事件多播器)将事件播报出去的.
首先, 判断有没有最定义的事件多播器. 如果有, 那么直接将其添加到容器中. 如果没有, 就新建一个SimpleApplicationEventMulticaster类型的事件多播器, 然后将其添加到beanFactory中.
那么, 事件多播器都做了什么事情呢? 具体来看一看SimpleApplicationEventMulticaster类.
这是SimpleApplicationEventMulticaster的继承结构. 继承了AbstractApplicationEventMulticaster, 而AbstractApplicationEventMulticaster又实现了ApplicationEventMulticaster. 我们看看在ApplicationEventMulticaster中都对应了哪些接口
public interface ApplicationEventMulticaster {
void addApplicationListener(ApplicationListener<?> listener);
void addApplicationListenerBean(String listenerBeanName);
void removeApplicationListener(ApplicationListener<?> listener);
void removeApplicationListenerBean(String listenerBeanName);
void removeAllListeners();
void multicastEvent(ApplicationEvent event);
void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType);
}
看名字就知道了, 做了两件事, 一个是管理事件监听器, 另一个是广播事件.
我们看AbstractApplicationEventMulticaster如何实现这几个接口的
/**
* AbstractApplicationEventMulticaster管理了所有的监听器.
* 当我们注册一个监听器以后, 就会通过addApplicationListener方法添加到事件多播器中.
* @param listener the listener to add
*/
@Override
public void addApplicationListener(ApplicationListener<?> listener) {
synchronized (this.retrievalMutex) {
// 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();
}
}
这是添加事件监听器.
在SimpleApplicationEventMulticaster里面, 定义了广播事件监听器
@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 );
}
}
}
这里有两种方式, 一种是同步的方式, 另一种是异步的方式. 根据设置的eventType来决定的. 其实异步的方式就是建立了一个新的线程
我么你来看一下调用事件监听器广播事件
invokeListener# doInvokeListener
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
// 最终调用的是监听器的onApplicationEvent方法. 这个方法就是每一个监听器都会自定义的方法.
listener.onApplicationEvent(event );
}
catch (ClassCastException ex) {
String msg = ex.getMessage();
if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
// Possibly a lambda-defined listener which we could not resolve the generic event type for
// -> let's suppress the exception and just log a debug message.
Log logger = LogFactory.getLog(getClass());
if (logger.isTraceEnabled()) {
logger.trace("Non-matching event type for listener: " + listener, ex);
}
}
else {
throw ex;
}
}
}
最终调用的是监听器的onApplicationEvent方法. 这个方法就是每一个监听器都会自定义的方法.
listener.onApplicationEvent(event);
2.9 onRefresh();这是一个扩展方法. 这里没有具体实现.spring boot也是从这个方法进行启动
2.10 注册监听器registerListeners();
注册监听器这里一共做了三件事:
1. 将事件监听器注册到多播器上
2. 广播早期的事件
3. 清空早期事件.
到此步骤之前, 上面都是有早期事件的, 后面就没有早期事件了,因为这一步就都清空了. 后面也不会在进行自动广播了, 自动广播的就是早期事件.
protected void registerListeners() {
// Register statically specified listeners first.
/**
* 第一步, 获取所有的事件监听器集合.
* 通常, 这个时候, 事件监听器集合是空的, 除非手动调用allApplicationListeners()注册事件监听器
*/
for (ApplicationListener<?> listener : getApplicationListeners()) {
// 将监听器注册到多播器上
getApplicationEventMulticaster().addApplicationListener(listener);
}
/**
* 第二步: 注册接口方式的监听器
* 获取beanDefinition中 ApplicationListener 类型的监听器. 也就是说, 使用接口方式定义的监听器
* 就可以在这里被注册到多播器的
* 这里是从BeanDefinition中拿的, 我们自定义了 OrderEventListenter 监听器, 那么会不会拿到呢?
* 我们知道监听器的实现有两种方式, 一种是接口方式, 一种是注解方式.
* 如果OrderEventListenter采用的是接口方式, 那么就可以拿到. 因为它实现了ApplicationListener.拿到了,
* 就把监听器注册到多播器上.
* 如果是注解方式, 那就拿不到了
*
*/
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false); for (String listenerBeanName : listenerBeanNames) {
// 把监听器注册到多播器上
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
/**
* 第三步: 获取早期的事件, 然后广播早期事件.
* 这些早期事件是在第一步 prepareRefresh 注册的.
*
*/
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
// 在这里将早期事件清空, 清空完以后, 就没有早期事件了.
this.earlyApplicationEvents = null; if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
如上源码所示:
第一步. 获取所有的事件监听器集合, 通常这个时候, 事件监听器的集合都是空的, 除非我们手动调用allApplicationListeners()注册事件监听器
第二步: 注册接口方式的监听器. 注意,是接口方式的. 通常我们自定义的监听器. 有两种类型, 接口方式和注解方式. 如果使用的是接口方式. 那么就是在这里被注册的.如果是注解方式.不在这里注册.
getBeanNamesForType(ApplicationListener.class, true, false);
扫描获取ApplicationListener类型的监听器.
然后将其注册到多播器上. 我们知道多播器的两个主要功能, 管理监听器和广播事件.
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
第三步: 获取早期事件, 然后广播早期事件. 早期事件我们之前已经说过了, 是在第一步prepareRefresh()方法里注册的.
随后, 立即清空早期事件集合. 然后广播事件. 这样早期定义好的事件就都被广播出去了, 并且只能执行一次, 不会被再次执行.
/**
* 第三步: 获取早期的事件, 然后广播早期事件.
* 这些早期事件是在第一步 prepareRefresh 注册的.
*
*/
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents; // 在这里将早期事件清空, 清空完以后, 就没有早期事件了.
this.earlyApplicationEvents = null; if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
2.11 实例化剩余的单实例bean
这个方法就是循环遍历BeanDefinitionMap, 调用getBean, 去生产剩余的bean, 之前详细研究过这个步骤, 这里就不说了
2.12 完成refresh()操作, 发布刷新事件
protected void finishRefresh() {
// Clear context-level resource caches (such as ASM metadata from scanning).
// 清除上下文缓存
clearResourceCaches();
// Initialize lifecycle processor for this context.
// 注册lifecycleProcessor声明周期处理器
// 作用: 当ApplicationContext启动或停止时, 他会通过LifecycleProcessor来与所有声明的bean进行交互
initLifecycleProcessor();
// Propagate refresh to lifecycle processor first.
// 为实现了SmartLifeCycle并且isAutoStartup, 自动启动的Lifecycle调用start()方法
getLifecycleProcessor().onRefresh();
// Publish the final event.
// 发布容器refresh完毕的事件.
// 发布的是什么事件呢? 是ContextRefreshedEvent事件.
publishEvent(new ContextRefreshedEvent(this)); // Participate in LiveBeansView MBean, if active.
LiveBeansView.registerApplicationContext(this);
}
在这一步: 发布了容器Refreshed事件. 也就是容器启动完成的事件.
到这里, 我们来看看publicshEvent的具体实现
/**
* 发布事件给所有的监听器
* Publish the given event to all listeners.
* @param event the event to publish (may be an {@link ApplicationEvent}
* or a payload object to be turned into a {@link PayloadApplicationEvent})
* @param eventType the resolved event type, if known
* @since 4.2
*/
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
Assert.notNull(event, "Event must not be null");
// Decorate event as an ApplicationEvent if necessary
ApplicationEvent applicationEvent;
/**
* 第一步: 获取事件
*/
if (event instanceof ApplicationEvent) {
// 处理接口类型的事件
applicationEvent = (ApplicationEvent) event;
}
else {
applicationEvent = new PayloadApplicationEvent<>(this, event);
if (eventType == null) {
eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
}
}
/**
* 第二步: 发布事件
*/
// Multicast right now if possible - or lazily once the multicaster is initialized
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
}
else {
/*
* 调用事件多播器, 将这个事件发布出去
* 事件多播器是什么时候注册的呢?
* 就是在refresh()初始化的时候, 调用initApplicationEventMulticaster(); 初始化的事件多播器
*/ getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}
/**
* 第三步: 发布事件给父类容器
*/
// Publish event via parent context as well...
// 发布事件给父类容器
if (this.parent != null) {
if (this.parent instanceof AbstractApplicationContext) {
((AbstractApplicationContext) this.parent).publishEvent(event , eventType);
}
else {
this.parent.publishEvent(event );
}
}
}
这里做了如下几件事
-
获取事件
-
广播事件
-
广播事件给父类监听器.
详细代码可以看注释
接下来看一下,具体的multicastEvent(...)
@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 );
}
}
}
这里首先会去获取线程池. 看看有没有重新定义线程池, 如果有这里executor就不是空的.
广播事件有两种形式, 一种是同步, 一种是异步. 如果executor线程池不空, 就以异步的形式广播, 否则就以同步的形式广播.
那么,我们如何自定义同步或者异步呢? 也是有两种方式
第一种方式: 自定义事件多波器, 并指定taskExcutor
@Bean(name = "applicationEventMulticaster")
public ApplicationEventMulticaster simpleApplicationEventMulticaster() {
SimpleApplicationEventMulticaster eventMulticaster
= new SimpleApplicationEventMulticaster();
//ThreadPoolTaskExecutor
// 这里指定了 taskExecutor, 就会使用异步的方式去执行
eventMulticaster.setTaskExecutor(new SimpleAsyncTaskExecutor());
return eventMulticaster;
}
第二种方式, 在事件监听器上使用注解@Async
@Component
@Async public class OrderEventListenter implements ApplicationListener<OrderEvent> {
/**
* 当某一个事件发布的时候, 就会触发事件监听器
* @param event the event to respond to
*/
@Override
public void onApplicationEvent(OrderEvent event) {
if (event.getName().equals("减库存")) {
System.out.println("事件监听器 监听到 减库存");
}
}
}
接下来看看如何广播事件的.
/**
* Invoke the given listener with the given event.
* @param listener the ApplicationListener to invoke
* @param event the current event to propagate
* @since 4.1
*/
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
ErrorHandler errorHandler = getErrorHandler();
if (errorHandler != null) {
try {
doInvokeListener(listener, event );
}
catch (Throwable err) {
errorHandler.handleError(err);
}
}
else {
doInvokeListener(listener, event );
}
}
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
// 最终调用的是监听器的onApplicationEvent方法. 这个方法就是每一个监听器都会自定义的方法.
listener.onApplicationEvent(event );
}
catch (ClassCastException ex) {
String msg = ex.getMessage();
if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
// Possibly a lambda-defined listener which we could not resolve the generic event type for
// -> let's suppress the exception and just log a debug message.
Log logger = LogFactory.getLog(getClass());
if (logger.isTraceEnabled()) {
logger.trace("Non-matching event type for listener: " + listener, ex);
}
}
else {
throw ex;
}
}
}
其实,具体执行的逻辑, 就是我们在监听器中定义的onApplicationEvent(event)方法中的逻辑实现.
三. 注册接口方式的监听器
在上面的源码分析中, 注册接口方式的监听器, 其实是由两个地方.
第一个: 在第十步registerListener()
protected void registerListeners() {
.....
/**
* 第二步: 注册接口方式的监听器
* 获取beanDefinition中 ApplicationListener 类型的监听器.
* 也就是说, 使用接口方式定义的监听器就可以在这里被注册到多播器的
* 这里是从BeanDefinition中拿的, 我们自定义了 OrderEventListenter 监听器, 那么会不会拿到呢?
* 我们知道监听器的实现有两种方式, 一种是接口方式, 一种是注解方式.
* 如果OrderEventListenter采用的是接口方式, 那么就可以拿到. 因为它实现了ApplicationListener.
* 拿到了, 就把监听器注册到多播器上.
* 如果是注解方式, 那就拿不到了
*
*/
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
// 把监听器注册到多播器上 getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
.....
}
另一个: 是在第三步进行属性填充的时候注册的
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
......
/**
* 注册事件监听器探测器后置处理器接口, ApplicationListenerDetector 解析接口方式的监听器
*/ beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this ));
......
}
在准备属性的方法里, 有一个注册时间监听器探测器后置处理. 在这个监听器的探测器里面, 进行了注册.
来看看ApplicationListenerDetector
class ApplicationListenerDetector implements DestructionAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor {
....../**
* 初始化后的bean后置处理器
*
* 这个方法是在 registerListener 之后执行的, 在registerListener()方法里注册过一次接口方式的监听器.
* 在这里还会在注册一次.
*
* 问题: 为什么同一个监听器, 要在两个地方注册呢?
* 第一次添加的是监听器的名字, 第二次添加的是bean实体. 那为什么要添加两次呢?
* 这是为了处理带有@Lazy懒加载方式的bean. 懒加载的bean是不会在初始化容器的时候创建bean的.
*
* 比如, 我给监听器类加上一个@Lazy, 那么他就不会走bean的后置处理器, 因为bean的后置处理器, 是在bean创建过程中调用的.
* 那什么时候会被调用呢? 在真正使用的时候. 比如调用 ctx.publishEvent(new OrderEvent(order, "减库存"));
* 马上就要用到了, 所以, 这时候回去调bean的后置处理器. 执行代码看一下效果
*
*
* @param bean the new bean instance
* @param beanName the name of the bean
* @return
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (bean instanceof ApplicationListener) {
// potentially not detected as a listener by getBeanNamesForType retrieval
Boolean flag = this.singletonNames.get(beanName);
if (Boolean.TRUE.equals(flag)) {
// singleton bean (top-level or inner): register on the fly
/*
* 注册接口类型的监听器. 将其添加到applicationContext中
* 之所以要在这里在加一次, 是为了处理懒加载情况
*/
this.applicationContext.addApplicationListener((ApplicationListener<?> ) bean);
}
else if (Boolean.FALSE.equals(flag)) {
// 这里是处理早期事件.
if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) {
// inner bean with other scope - can't reliably process events
logger.warn("Inner bean '" + beanName + "'implements ApplicationListener interface" +
"but is not reachable for event multicasting by its containing ApplicationContext" +
"because it does not have singleton scope.Only top-level listener beans are allowed" +
"to be of non-singleton scope.");
}
this.singletonNames.remove(beanName);
}
}
return bean;
}
.......
}
我们看到在ApplicationListenerDetector中定义了方法postProcessAfterInitialization. 这个方法会在创建属性的第三步执行完以后调用. 第三步是初始化. 看名字也知道是初始化之后调用的后置处理器. 在这里, 注册了接口类型的监听器
this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);
那么, 为什么要有两次注册呢?
其实这里是为了解决懒加载的问题. 因为,如果一个类是懒加载的类, 那么他只有真正被调用的时候才回去加载. 所以, 也就是在类进行初始化以后才会被调用. 因此在初始化之后再次加载了接口类型的监听器.
四. 解析注解方式的监听器
整个流程走完, 我们都只看到接口方式的监听器注册的地方. 那么注解类型的监听器是什么时候被创建的呢?
首先, 注解是何时被解析的? 我们知道BeanDefinitionReader在解析创世纪的类的时候, 注册了很多创世纪的类.其中就有两个是用于负责处理@EventListener注解的
再来回顾一下这段代码
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) {
// 获取到beanFactory
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
/**
* 判断beanFactory中是否有AnnotationAwareOrderComparator和ContextAnnotationAutowireCandidateResolver
* 没有则添加
*/
if (beanFactory != null) {
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
if (!(beanFactory.getAutowireCandidateResolver() instanceof
ContextAnnotationAutowireCandidateResolver)) {
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
// BeanDefinitionHolder: 为BeanDefinition设置名字和别名
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
// 如果registry中没有ConfigurationClassPostProcessor配置类后置处理器, 就添加一个
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
// 构建BeanDefinitionHolder, 并添加到beanDefs
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// 如果rigistry中, 没有AutowiredAnnotationBeanPostProcessor Autowired注解bean的后置处理器, 则添加一个
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
// 构建BeanDefinitionHolder, 并添加到beanDefs
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
// 检查对JSR-250的支持, 如果rigistry中没有 CommonAnnotationBeanPostProcessor 通用注解后置处理器, 则添加一个
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
// 构建BeanDefinitionHolder, 并添加到beanDefs
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
// 检查对jpa的支持, 如果不包含 internalPersistenceAnnotationProcessor, 持久化注解处理器, 就添加一个
if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition();
try {
def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
AnnotationConfigUtils.class.getClassLoader()));
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Cannot load optional framework class: " +
PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
}
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
}
/**
* 下面这两个注解是用来解析@EventListener的
*/
// 检查对事件监听的支持, 如果不包含事件监听处理器 internalEventListenerProcessor, 就添加一个
/*
* EventListenerMethodProcessor : 既不是bean的后置处理器, 也不是bean工厂的后置处理器
* 那么EventListenerMethodProcessor是在哪里被调用,并且解析注解方式的监听器呢?
*
* 下面看一下EventListenerMethodProcessor的继承结构图.
* 1. 实现了SmartInitializingSingleton接口 :
* 2. 实现了ApplicationContextAware接口 : 因为要往容器中注入bean, 所以,里面要使用容器的上下文,
* 将容器以Aware的方式set进来
* 3. 实现了BeanFactoryPostProcessor接口 :
*
*
*/
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));
}
// 如果不包含事件监听工厂处理器 internalEventListenerFactory , 就添加一个
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;
}
如上图就是注册的创世纪的处理器. 最后两个就是用来处理@EventListener注解的.
下面来看看EventListenerMethodProcessor事件监听器处理器,
首先, 看一下EventListenerMethodProcessor的继承结构图.
EventListenerMethodProcessor实现了三个接口.
1.实现了SmartInitializingSingleton接口
-
实现了ApplicationContextAware接口 : 因为要往容器中注入bean, 所以,里面要使用容器的上下文, 将容器以Aware的方式set进来
-
实现了BeanFactoryPostProcessor接口
SmartInitializingSingleton接口在哪里被用到了呢?
在refresh()#finishBeanFactoryInitialization(beanFactory); 实例化剩余的单例bean的过程中 在DefaultListableBeanFactory#preInstantiateSingletons()方法. 有两次循环遍历beanNames
@Override
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
// 获取容器中所有bean定义的名字
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
/**
* 第一步: 循环bean定义的name, 创建bean
*/
for (String beanName : beanNames) {
// 获取bean定义
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 生产bean定义的条件: 不是抽象的, 是单例的, 不是懒加载的. 符合这个标准的, 最后才会调用getBean()生产bean
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 这里判断是不是工厂bean, 这里和BeanFactory不是一个意思, 判断当前这个bean是否实现了beanFactory的接口
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
// 将bean转换为FactoryBean 工厂bean
final FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
// 获取bean
getBean(beanName);
}
}
}
else {
// 第二步: 调用getBean
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable beans...
/**
* 第二步: 循环bean定义的name, 解析是否有实现了SmartInitializingSingleton接口的类
* 到这里, bean都已经被创建完了
*/
for (String beanName : beanNames) {
// 从缓存中得到实例instance
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
第一次循环, 是创建bean, 并获取bean
第二次循环, 是在所有的bean都已经创建完以后, 如果singletonInstance是SmartInitializingSingleton的实例, 则调用afterSingletonsInstantiated()方法.
以下是EventListenerMethodProcessor#afterSingletonsInstantiated()方法实现
@Override
public void afterSingletonsInstantiated() {
// 从spring容器中获取EventListenerFactoryBean
ConfigurableListableBeanFactory beanFactory = this.beanFactory;
Assert.state(this.beanFactory != null, "No ConfigurableListableBeanFactory set");
// 获取所有类型的bean
String[] beanNames = beanFactory.getBeanNamesForType(Object.class);
for (String beanName : beanNames) {
if (!ScopedProxyUtils.isScopedTarget(beanName)) {
Class<?> type = null;
try {
type = AutoProxyUtils.determineTargetClass(beanFactory, beanName);
}
catch (Throwable ex) {
// An unresolvable bean type, probably from a lazy bean - let's ignore it.
if (logger.isDebugEnabled()) {
logger.debug("Could not resolve target class for bean with name '" + beanName + "'", ex);
}
}
if (type != null) {
if (ScopedObject.class.isAssignableFrom(type)) {
try {
Class<?> targetClass = AutoProxyUtils.determineTargetClass(
beanFactory, ScopedProxyUtils.getTargetBeanName(beanName));
if (targetClass != null) {
type = targetClass;
}
}
catch (Throwable ex) {
// An invalid scoped proxy arrangement - let's ignore it.
if (logger.isDebugEnabled()) {
logger.debug("Could not resolve target bean for scoped proxy '" +
beanName + "'", ex);
}
}
}
try {
processBean(beanName, type);
}
catch (Throwable ex) {
throw new BeanInitializationException("Failed to process @EventListener " +
"annotation on bean with name '" + beanName + "'", ex);
}
}
}
}
}
这里主要看processBean(beanName, type) 处理bean
private void processBean(final String beanName, final Class<?> targetType) {
// 1. 是否包含注解@EventListener
if (!this.nonAnnotatedClasses.contains(targetType) &&
AnnotationUtils.isCandidateClass(targetType, EventListener.class) &&
!isSpringContainerClass(targetType)) {
Map<Method, EventListener> annotatedMethods = null;
try {
// 2. 查找@EventListener注解, 如果有则拿到标注@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");
// 3. 获取bean工厂. 这个bean工厂是我们在创世纪的时候注册的EventListenerFactory
List<EventListenerFactory> factories = this.eventListenerFactories;
Assert.state(factories != null, "EventListenerFactory List not initialized");
// 4. 循环遍历有注解的方法
for (Method method : annotatedMethods.keySet()) {
for (EventListenerFactory factory : factories) {
if (factory.supportsMethod(method)) {
Method methodToUse = AopUtils.selectInvocableMethod(method, context.getType(beanName));
//5. 创建事件监听器
ApplicationListener<?> applicationListener =
factory.createApplicationListener(beanName, targetType, methodToUse); if (applicationListener instanceof ApplicationListenerMethodAdapter) {
((ApplicationListenerMethodAdapter) applicationListener).
init(context, this.evaluator);
}
// 6. 将监听器注入到多播器中
context.addApplicationListener(applicationListener); break;
}
}
}
if (logger.isDebugEnabled()) {
logger.debug(annotatedMethods.size() + " @EventListener methods processed on bean '" +
beanName + "': " + annotatedMethods);
}
}
}
}
- 首先判断, 是否包含@EventListener注解
2. 查找@EventListener注解, 如果有则拿到标注@EventListener的方法
3. 获取bean工厂. 这个bean工厂是我们在创世纪的时候注册的EventListenerFactory
-
循环遍历有注解的方法
-
创建事件监听器
-
将监听器注入到多播器中
以上就是注解版的监听器是如何注入到多播器中的.
五. 怎样在所有的bean都创建完以后做扩展代码?
第一种方式, 添加内置的监听器, 类加载完以后, 调用监听器
第二种方法. 就是在使用注解方式的时候, 实现SmartInitializingSingleton接口. 然后在bean实例化完成以后, 在调用