微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

4 Spring源码 --- 监听器的原理

目标:

1. 监听器如何使用

2. 监听器的原理

3. 监听器的类型

4. 多播器的概念和作用

5. 接口类型的监听器是如何注册的?

6. 注解类型的监听器和如何注册的?

7. 如果想在所有的bean都加载完成以后做一些事情,怎么办?

 

 一. 监听器的使用

为什么要学习监听器呢?学习监听器主要学习监听器的设计思想。 比如,我们之前研究过的nacos,他就是使用监听器进行集成的。所以了解监听器的原理,就很重要了。

首先, 我们要知道监听器如何使用。 

1.1 Spring事件的原理

原理: 是观察者模式

Spring的事件监听有三个组成部分:

1. 事件(ApplicationEvent):要广播,发送的消息. 监听器监听的事情
2. 监听器(ApplicationListener): 观察者模式中的观察者,监听器监听特定事件,并在内部定义了事件发生后的相应逻辑.
3. 事件发布器(ApplicationEventMulticaster):对应于观察者模式中的被观察者/主题.负责通知观察者. 对外提供发布事件和增删事件监听器的接口.维护事件和事件监听器之间的关系.并在事件发生时负责通知事件监听器.

 

1.2 认识监听器

上面认识了监听器. 接下来看一个例子. 通过例子来理解.

就好比现在有一个消息,比如说: 下单后减库存. 减库存就是一个事件,这个事件需要一个事件播放器,将事件播放出去. 然后另一端事件监听器,接收到信息,进行处理.

比如:下面的demo

一个订单Order :

package com.lxl.www.events;

/**
 * Description
 *
 * DATE 2020/11/17.
 *
 * @author lxl.
 */
public class Order {
    private Integer id;

    public Integer getId() {
        return id;
    }

    void setId(Integer id) {
        this.id = id;
    }
}

接下来,有一个订单事件. 订单的操作,带来的库存的增减. 就是一个订单事件

package com.lxl.www.events;

import org.springframework.context.ApplicationEvent;

import java.io.Serializable;

*
 * Description
 * 订单的事件
 *
 * 事件的分类: 分为自定义事件和内置事件
 * DATE 2020/11/17.
 *
 * @author lxl.
  OrderEvent  extends ApplicationEvent implements Serializable {

    private static final long serialVersionUID = 1L;

     String name;
    public OrderEvent(Object event,String name) {
        super();
        this.name = name;
    }

     String getName() {
         setName(String name) {
         name;
    }
}

第三: 事件监听器,事件监听器用来监听事件. 当OrderEvent发布减库存消息的时候,事件监听器就能听到.

package com.lxl.www.events;

import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

*
 * Description
 * OrderEvent的事件监听器
 *
 *
 * DATE 2020/11/17.
 *
 * @author lxl.
 */
@Component
class OrderEventListenter implements ApplicationListener<OrderEvent> {
    *
     * 当某一个事件发布的时候,就会触发事件监听器
     * @param event the event to respond to
     
    @Override
    void onApplicationEvent(OrderEvent ) {
        if (event.getName().equals("减库存")) {
            System.out.println(事件监听器  监听到  减库存);
        }
    }
}

是不是和mq相差不多.

mq也是一个订阅者,一个发布者. 

下面写一个main方法,运行看看监听器的效果

package com.lxl.www.events;

import org.springframework.beans.factory.parsing.sourceExtractor;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

*
 *  监听器的使用
  MainClass {
    static  main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MainConfig.);

        *
         * 使用场景: 比如有一个订单,由用户下单了,那么对应的就要减库存.其实下单和减库存不需要是串行.
         * 通常,我们会使用一个mq去处理减库存的情况. 也就是采用异步的方式.
         *
         * 那么,监听器的远离和mq是类似的. 我们可以手动设置采用同步还是异步的方式处理.
         
        Order order = new Order();
        order.setId(1);
        System.下单// 发布事件. 当在这里发布事件,那么就会被事件监听器监听到
        ctx.publishEvent(new OrderEvent(order,));
        System.日志.....);
    }
}

输出结果

下单
事件监听器  监听到  减库存
日志.....

监听器使用的设计模式是: 观察者模式.

 

1.3 监听器的类型

监听器有两种类型: 一种是内置的监听器,一种是自定义监听器. 

1.3.1 内置监听器

 spring设置了一个内置监听器的父类.

abstract  ApplicationContextEvent extends ApplicationEvent {

    *
     * Create a new ContextStartedEvent.
     * @param source the {@code ApplicationContext} that the event is raised for
     * (must not be {@code null})
     */
     ApplicationContextEvent(ApplicationContext source) {
        super(source);
    }

    *
     * Get the {@code ApplicationContext} that the event was raised for.
      final ApplicationContext getApplicationContext() {
         (ApplicationContext) getSource();
    }

}

实现了ApplicationContextEvent的类就是内置的监听器. 我们使用快捷键ctrl + H,查看都有哪些类实现了 ApplicationContextEvent

 

一共有5各类实现了ApplicationContextEvent.  

Event  说明
ContextRefreshEvent

当容器被实例化或者refresh时发布.如调用refresh()方法. 此处的实例化是指所有的bean都已被加载,后置处理器都被激活,所有单例bean都已被实例化,所有的容器对象

都已经准备好可使用. 如果容器支持热重载,则refresh()可以被触发多次(XmlWebApplicationContext支持热刷新,而GenericApplicationContext不支持热刷新)

ContextStartedEvent 当容器启动时发布,即调用start()方法,已启用意味着所有的lifecycle都已显示收到了start的信号
ContextStoppedEvent 当容器停止时发布. 即调用stop()方法,既所有的lifecycle bean都已显示接收了stop信号,关闭的容器可以通过start()方法重启
ContextClosedEvent 当容器关闭时发布. 即调用close()方法,关闭意味着所有的单例bean都已被销毁. 关闭的容器不能被重启或refresh()

 

 1. ContextRefreshEvent: 当容器被实例化或者refresh时发布

我们来看看一下源码.

从refresh()源码进入.

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
         进入构造函数,首先调用自身的构造方法this();
         调用自身的构造方法之前,要先调用父类的构造方法
        this();
         register配置注册
        register(componentClasses);
        // ioc容器刷新接口--非常重要
        refresh();
    }
*
     * refresh是spring最核心的方法,里面包含了整个spring ioc的全过程,包括spring加载bean到销毁bean的全过程
     * 学习spring,就是学习里面的13个方法,如果13个方法都学完了,基本上就打通了
     * @throws BeansException
     * @throws IllegalStateException
      refresh() throws BeansException,IllegalStateException {
        synchronized (.startupShutdownMonitor) {
             1. 准备刷新上下文环境
            prepareRefresh();

             Tell the subclass to refresh the internal bean factory.
            2. 获取告诉子类初始化bean工厂,不同工厂不同实现
            ConfigurableListablebeanfactory beanfactory = obtainFreshbeanfactory();

        ......
 Last step: publish corresponding event.
                //最后容器刷新 发布刷新时间(spring cloud是从这里启动的 )
                finishRefresh();
            }
      
      ......

    }
    }

进入到finishRefresh()方法

protected  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();
    // 发布容器启动完毕事件
        publishEvent(new ContextRefreshedEvent(this));

         Participate in LiveBeansView MBean,if active.
        LiveBeansView.registerapplicationContext();
    }

我们看到有一个发布事件. 这个事件的作用是通知容器已经启动完毕. 注意看,里面发布的是什么事件? new ContextRefreshedEvent(this). 发布的是ContextRefreshedEvent事件.

下面有一个问题:  怎么样可以在所有的bean创建完以后做扩展代码呢?

上面我们说到了,当所有的bean都创建完以后,会调用publishEvent(new ContextRefreshedEvent(this));发布容器启动完毕的事件.

这时我们可以自定义一个监听器,用来监听ContextRefreshedEvent事件.

*
 * 自定义一个事件监听器,用来监听ContextRefreshedEvent事件
  ContextRefreshedEventListener {

  *
   * 声明这是一个事件监听器,监听的是ContextRefreshedEvent事件.
   * @param event
   
  @EventListener(ContextRefreshedEvent.)
  void onApplicationEvent(ContextRefreshedEvent ) {
      ....
     在所有的bean创建完以后,写一些逻辑代码

  }
}

然后,在里面写上我们需要在容器都创建完毕之后执行的逻辑代码.

 

2. ContextClosedEvent: 当容器关闭时发布

还是先来看源码,spring是在何时发布的这个事件.

 doClose() {
         Check whether an actual close attempt is necessary...
        this.active.get() && this.closed.compareAndSet(false,true)) {
            if (logger.isDebugEnabled()) {
                logger.debug(Closing " + );
            }

            LiveBeansView.unregisterapplicationContext();

            try {
                // Publish shutdown event.
                publishEvent(new ContextClosedEvent(this));
            }
            catch (Throwable ex) {
                logger.warn(Exception thrown from ApplicationListener handling ContextClosedEvent Stop all Lifecycle beans,to avoid delays during individual destruction.
            this.lifecycleProcessor != null) {
                 {
                    .lifecycleProcessor.onClose();
                }
                 (Throwable ex) {
                    logger.warn(Exception thrown from LifecycleProcessor on context close Destroy all cached singletons in the context's beanfactory.
            destroyBeans();

             Close the state of this context itself.
            closebeanfactory();

             Let subclasses do some final clean-up if they wish...
            onClose();

             Reset local application listeners to pre-refresh state.
            this.earlyApplicationListeners != .applicationListeners.clear();
                this.applicationListeners.addAll(.earlyApplicationListeners);
            }

             Switch to inactive.
            set(false);
        }
    }

在doClose()的时候,发布了publishEvent(new ContextClosedEvent(this));事件

我们看一看具体发布的是什么事件呢? 就是ContextClosedEvent事件

假如: 我们想要在容器关闭的时候做一些扩展,就可以写一个监听器,在容器关闭的时候监听ContextClosedEvent事件

  

 Spring内置的事件,我们就不用再自己定义了. 我们需要做的就是定义一个监听器,监听事件就可以了.

 

 1.3.2 自定义监听器

不是spring定义的监听器,也就是我们自己定义的监听器就是自定义监听器. 下面来看看自定义监听器的两种类型. 

类型一: 基于接口 

@Component
class HelloEventListener implements ApplicationListener<OrderEvent> {

  @Override
  ) {
      )) {
        System.减库存....);
      }
  }
}

事件监听器需要实现ApplicationListener接口,这是一个泛型接口,泛型的类型就是事件的类型.

其次,这个监听器需要是spring容器托管的bean,因此加上了@Component注解,里面只有一个方法onApplicationEvent,就是事件触发时执行的内容

类型二: 基于注解

 OrderEventListener {

  @EventListener(OrderEvent.class)
  ) {
    )) {
      System.);
    }
  }

方法上面添加注解@EventListener(OrderEvent.class) 监听的是哪个事件呢?OrderEvent.class

 我们在定义监听器的时候,可以选择是基于接口的方式还是基于注解的方式.

 二. 监听器源码

 首先,监听器的声明,调用,都是在refresh()方法里面进行,我们先来看看refresh()的整体脉络. 其中标红的部分是和监听器有关系的模块.

 

 这里面的第五步,第九步,第十一步,都详细的分析过. 下面主要看看和监听器有关的几步.

 2.1 准备上下文环境prepareRefresh()

在准备上下文环境的时候,我们看看做了哪些事情

 

 1. 设置了容器当期的状态,是激活状态

2. 初始化了属性源initPropertySources();.

在AbstractApplicationContext类中没有实现这个方法. 这是一个类定义方法. 比如:我们可以自定义一个类,然后重写initPropertySource,在改方法中设置一个环境变量abc,那么在容器启动的时候,就会去环境变量中检查,是否环境变量中有这个属性,如果没有就会抛出异常.

3. 接下来就是验证上面环境变量中指定的属性是否存在了. getEnvironment().validaterequiredProperties(); 不存在就抛出异常MissingrequiredPropertiesException

4. 然后接下来,和事件有关的一步,创建了早期的事件监听器

      创建早期的事件监听器.
         Store pre-refresh ApplicationListeners...
        this.earlyApplicationListeners == ) {
            this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
        }
        else {
            .applicationListeners.clear();
            .earlyApplicationListeners);
        }

这里有一个问题,什么是早期的事件监听器呢? 早对应的就是晚了. 早期指的是多早呢?

早期事件指的是事件监听器还没有注册到事件多播器的时候.

早期定义的事件不需要手动的publishEvent,在RegisterListener()阶段会自动发布早期事件.

什么是早期的事件监听器呢? 早对应的就是晚了. 早期指的是多早呢?

早期事件指的是事件监听器还没有注册到事件多播器的时候.

早期定义的事件不需要手动的publishEvent,在RegisterListener()阶段会自动发布早期事件.

在这里就定义了一个集合,这个集合就是后面事件监听器集合. 在这里只是进行的初始化

 

5. 初始化保存早期事件的集合

this.earlyApplicationEvents = new LinkedHashSet<>();

在第一步: 对事件的操作就是初始化. 一共初始化了两个集合,一个是早期事件监听器集合,一个是早期的事件集合

 

2.2 初始化bean工厂 

 我们现在经常使用的beanfactory有两种,一种是xml方式的,另一种是注解方式的. 其实使用注解的更多一些. xml和注解方式的bean工厂在初始化的时候也是有区别的. 

 从上图可以看出,获取两种方式的bean工厂的区别

1. AbstractRefreshableApplicationContext: 基于xml配置文件的方式
2. GenericApplicationContext: 基于注解的方式.
基于注解实现的里面代码很简单,只是刷新的beanfactory. 没有耦合加载beanDeFinition的流程. 基于xml实现的代码,里面耦合了加载beanDeFinition

先来看看基于注解方式的,基于注解方式只是指定了bean工厂的序列化ID

@Override
    protected final      refreshbeanfactory() throws IllegalStateException {
        if (!this.refreshed.compareAndSet(throw  IllegalStateException(
                    GenericApplicationContext does not support multiple refresh attempts: 
                just call 'refresh' once
); } // 指定bean工厂的序列化ID this.beanfactory.setSerializationId(getId()); }

再来看看基于xml方式的,基于xml方式的 除了指定了bean工厂的序列化id,还耦合加载了beanDeFinition

 refreshbeanfactory() throws BeansException {
         判断bean工厂是否初始化过,如果已经初始化过那么销毁并关闭
         (hasbeanfactory()) {
            destroyBeans();
            closebeanfactory();
        }
         重新创建一个bean工厂
            DefaultListablebeanfactory beanfactory = createbeanfactory();
             设置序列化id
            beanfactory.setSerializationId(getId());
             设置个性化属性
            customizebeanfactory(beanfactory);
            // 加载BeanDeFinition
            loadBeanDeFinitions(beanfactory);
            this.beanfactory = beanfactory;
        }
         (IOException ex) {
            new ApplicationContextException(I/O error parsing bean deFinition source for " + 
              getdisplayName(),ex); } }

 看上面的步骤. 

1. 先看看是否已经有过工厂了,如果已经有了,那么销毁,关闭

2. 重新创建了一个空的新的工厂

3. 设置新工厂的序列化id

4. 设置个性化属性bean

5. 加载bean定义. 我们看到,使用xml方式会加载bean定义

6. 返回bean工厂对象

这一步: 主要是初始化了bean工厂

 

2.3 对bean工厂进行填充属性preparebeanfactory(beanfactory);

 这一步是和监听器有关系的. 我们先来看看源码

 preparebeanfactory(ConfigurableListablebeanfactory beanfactory) {
         Tell the internal bean factory to use the context's class loader etc.
         设置bean工厂的类加载器为当前的application应用的加载器
        beanfactory.setBeanClassLoader(getClassLoader());
         为bean工厂设置标准的SPEL表达式解析器对象(StandardBeanExpressionResolver)
        beanfactory.setBeanExpressionResolver( StandardBeanExpressionResolver(beanfactory.getBeanClassLoader()));
         为bean工厂设置一个PropertiesEditor属性资源编辑器(用于后面给bean对象赋值)
        beanfactory.addpropertyeditorRegistrar(new ResourceEditorRegistrar( Configure the bean factory with context callbacks.
        *
         * 注册一个完整的ApplicationContextAwareProcessor后置处理器,用来处理ApplicationContextAware
         * ApplicationContextAwareProcessor是一个bean的后置处理器. 怎么使用呢?
         *
         * 在bean初始化完成以后,会调用一堆的bean后置处理器.
         * 在初始化的地方,其实只调用了三个bean后置处理器. 那么其他的后置处理器是什么时候调用的呢?
         * 就是在这里,这里注册了 ApplicationContextAwareProcessor.
         * 在ApplicationContextAwareProcessor#invokeAwareInterfaces方法调用了其他的aware
         * 那么invokeAwareInterfaces方法是在哪里调用呢?
         * 是在ApplicationContextAwareProcessor#postProcessBeforeInitialization调用的
         * postProcessBeforeInitialization是在bean初始化之前会调用的后置处理器
         *
         * 然后在通过addBeanPostProcessor()方法,将bean的后置处理器添加到beanPostProcessors集合中
         */
        beanfactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

        *
         * 忽略部分接口的函数方法,在populateBean(创建bean的第二步:属性赋值)时
         * 因为下面接口都有set***方法,这些方法不特殊处理将会自动注入到容器中.
         *
         * 忽略了这么多的Aware,这是怎么回事呢? 因为Aware里面的方法都是以set开头的. 当在创建bean,设置属性的时候,* 会给带有set+属性名的方法赋值. 而Aware的这些方法要忽略掉,为什么忽略掉呢?
         *
         * 比如:EnvironmentAware 里面设置了一些环境变量,这些环境变量是不需要进行属性装配的,所以要把他们排除掉
         
        beanfactory.ignoreDependencyInterface(EnvironmentAware.);
        beanfactory.ignoreDependencyInterface(EmbeddedValueResolverAware.);
        beanfactory.ignoreDependencyInterface(ResourceLoaderAware.);
        beanfactory.ignoreDependencyInterface(ApplicationEventPublisherAware.);
        beanfactory.ignoreDependencyInterface(MessageSourceAware.);
        beanfactory.ignoreDependencyInterface(ApplicationContextAware. beanfactory interface not registered as resolvable type in a plain factory.
         MessageSource registered (and found for autowiring) as a bean.
        *
         * 将beanfactory类型的实例注册解析
         *
         * 当注册了依赖解析以后,例如当注册了对beanfactory.class的解析依赖后,* 当bean属性注入的时候,一旦检测到属性beanfactory类型. 便会将beanfactory的实例注册解析
         * 为什么呢?
         * 比如:
         * @Autowired
         * ApplicationContext applicationContext 为什么能够自动装配,通过@Autowired引入呢? 就是在这里装配的.
         * 这个也是在注入属性popularBean的时候体现的
         *
         
        beanfactory.registerResolvableDependency(beanfactory.beanfactory);
        beanfactory.registerResolvableDependency(ResourceLoader.class,1)">);
        beanfactory.registerResolvableDependency(ApplicationEventPublisher.);
        beanfactory.registerResolvableDependency(ApplicationContext. Register early post-processor for detecting inner beans as ApplicationListeners.
        // 注册事件监听器探测器后置处理器接口,ApplicationListenerDetector 解析接口方式的监听器
        beanfactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

         Detect a LoadTimeweaver and prepare for weaving,if found.
         (beanfactory.containsBean(LOAD_TIME_weaveR_BEAN_NAME)) {
            beanfactory.addBeanPostProcessor( LoadTimeweaverAwareProcessor(beanfactory));
             Set a temporary ClassLoader for type matching.
            beanfactory.setTempClassLoader( ContextTypeMatchClassLoader(beanfactory.getBeanClassLoader()));
        }

         Register default environment beans.
        beanfactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
            beanfactory.registerSingleton(ENVIRONMENT_BEAN_NAME,getEnvironment());
        }
        beanfactory.containsLocalBean(SYstem_PROPERTIES_BEAN_NAME)) {
            beanfactory.registerSingleton(SYstem_PROPERTIES_BEAN_NAME,getEnvironment().getSystemProperties());
        }
        beanfactory.containsLocalBean(SYstem_ENVIRONMENT_BEAN_NAME)) {
            beanfactory.registerSingleton(SYstem_ENVIRONMENT_BEAN_NAME,getEnvironment().getSystemEnvironment());
        }
    }

1. 设置bean工厂的类加载器为: 当前的application应用的加载器

2. 为bean工厂设置标准的SPEL表达式解析器对象,这个解析器对象是谁呢? 就是StandardBeanExpressionResolver

3. 为bean工厂设置一个PropertiesEditor属性资源编辑器,用于后面给bean对象赋值

4. 给bean工厂注册一个ApplicationContextAwareProcessor后置处理器. 这里说说这个后置处理器类. 这个类有什么作用呢?

在bean初始化完成以后,会调用一堆的bean后置处理器

在doCreateBean()中找到第三步: 初始化bean

protected Object initializeBean(final String beanName,final Object bean,@Nullable RootBeanDeFinition mbd) {
        if (System.getSecurityManager() != ) {
            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                 在初始化完成以后,调用aware
                invokeAwareMethods(beanName,bean);
                return ;
            },getAccessControlContext());
        }
         {
            // 在初始化的时候,会调用很多的aware.
            invokeAwareMethods(beanName,bean);
        }

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
             在初始化之前调用bean的后置处理器
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean,beanName);
        }

         调用初始化方法
            invokeInitMethods(beanName,wrappedBean,mbd);
        }
         (Throwable ex) {
             BeanCreationException(
                    (mbd != null ? mbd.getResourceDescription() : ),beanName,Invocation of init method Failed 再初始化之后调用bean的后置处理器
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean,1)"> wrappedBean;
    }

我们看到,在初始化bean的时候,调了很多Aware, invokeAwareMethods(beanName,bean);

*
     * 这里主要有三类aware
     * @param beanName
     * @param bean
      invokeAwareMethods(final String beanName,final Object bean) {
        *
         * 在这里调用的aware只有三类,我们去beanfactory中看,他有一大堆的aware要调用,* 那么其他的aware是在哪里调用的呢?
         */
         (bean instanceof Aware) {
             实现了BeanNameAware的bean
             (bean instanceof BeanNameAware) {
                ((BeanNameAware) bean).setBeanName(beanName);
            }
             实现了BeanClassLoaderAware接口
            BeanClassLoaderAware) {
                ClassLoader bcl = getBeanClassLoader();
                if (bcl != ) {
                    ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
                }
            }
             实现了beanfactoryAware
            beanfactoryAware) {
                ((beanfactoryAware) bean).setbeanfactory(AbstractAutowireCapablebeanfactory.);
            }
        }
    }

如上代码,我们看到,其实知道用了3中类型的Aware. 分别是BeanNameAware,BeanClassLoaderAware 和 beanfactoryAware.

那么其他的Aware呢? 我们看beanfactory接口的注释可以看到,会调用很多Aware

 

在初始化的地方,其实只调用了三个bean后置处理器. 那么其他的后置处理器是什么时候调用的呢?

就是在这里,这里注册了 ApplicationContextAwareProcessor.

在ApplicationContextAwareProcessor#invokeAwareInterfaces方法调用了其他的aware

*
     * 判断bean是否实现了各种Aware
     * @param bean
      invokeAwareInterfaces(Object bean) {
         (bean instanceof EnvironmentAware) {
            ((EnvironmentAware) bean).setEnvironment(.applicationContext.getEnvironment());
        }
         (bean instanceof EmbeddedValueResolverAware) {
            ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(.embeddedValueResolver);
        }
         (bean instanceof ResourceLoaderAware) {
            ((ResourceLoaderAware) bean).setResourceLoader(.applicationContext);
        }
        ApplicationEventPublisherAware) {
            ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher( (bean instanceof MessageSourceAware) {
            ((MessageSourceAware) bean).setMessageSource( (bean instanceof ApplicationContextAware) {
            ((ApplicationContextAware) bean).setApplicationContext(.applicationContext);
        }
    }

 而这个方法,什么时候执行呢? 在初始化之前调用Bean的后置处理器执行的ApplicationContextAwareProcessor#postProcessBeforeInitialization

@Override
    @Nullable
    postProcessBeforeInitialization(Object bean,String beanName) throws BeansException {
        if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
                bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
                bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){
             bean;
        }

        AccessControlContext acc = ;

        ) {
            acc = .applicationContext.getbeanfactory().getAccessControlContext();
        }

        if (acc !=  {
                invokeAwareInterfaces(bean);
                 {
            invokeAwareInterfaces(bean);
        }

         bean;
    }

 然后在通过addBeanPostProcessor()方法,将bean的后置处理器添加到beanPostProcessors集合中.

5. 忽略部分接口的函数方法. 这些接口主要是Aware.  

beanfactory.ignoreDependencyInterface(EnvironmentAware.class);
beanfactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanfactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanfactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanfactory.ignoreDependencyInterface(MessageSourceAware.class);
beanfactory.ignoreDependencyInterface(ApplicationContextAware.class);

 忽略了这么多的Aware,这是怎么回事呢?为什么忽略掉呢? 因为Aware里面的方法都是以set开头的. 当在创建bean,

会给带有set+属性名的方法赋值.在populateBean(创建bean的第二步:属性赋值)时 因为下面接口都有set***方法,这些方法不特殊处理将会自动注入到容器中.

比如:EnvironmentAware 里面设置了一些环境变量,所以要把他们排除掉

6. 将beanfactory类型的实例注册解析

beanfactory.registerResolvableDependency(beanfactory.class,beanfactory);
beanfactory.registerResolvableDependency(ResourceLoader.class,this);
beanfactory.registerResolvableDependency(ApplicationEventPublisher.class,this);
beanfactory.registerResolvableDependency(ApplicationContext.class,this);
注册了依赖解析以后,
当bean属性注入的时候,一旦检测到属性beanfactory类型. 便会将beanfactory的实例注册解析
为什么呢?
比如:
@Autowired
ApplicationContext applicationContext; .
为什么能够自动装配,通过@Autowired引入呢? 就是在这里装配的
这个也是在注入属性popularBean的时候体现的

7. 注册一个解析接口方式的监听器的 BeanPostProcessor. 

beanfactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

我们来看看ApplicationListenerDetector 类,其下的 postProcessAfterInitialization方法,是在createBean的第三步初始化之后执行的bean的后置处理器.

 @Override
     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);
             (Boolean.TRUE.equals(flag)) {
                 singleton bean (top-level or inner): register on the fly
                
                 * 注册接口类型的监听器. 将其添加到applicationContext中
                 * 之所以要在这里在加一次,是为了处理懒加载情况
                 */
                this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);
            }
            else  (Boolean.FALSE.equals(flag)) {
                 这里是处理早期事件.
                if (logger.isWarnEnabled() && !.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.);
                }
                .singletonNames.remove(beanName);
            }
        }
         bean;
    }

我们看这个方法,方法一进来就判断,是否是实现了ApplicationListener接口. 也就是说,上面我们输了注册监听器有两种方式,一种是接口方式,另一种是注解方式. 这里解析的是实现接口的方式.

在这里,我们要先建立一个印象,因为后面还会说到他. 为什么呢? 因为接口方式的监听器在两个地方被调用,一个是这里,另一个是在refresh()后面的流程registerListener()的时候. 那么,为什么要有两次调用监听器呢? 我们后面再说

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())的时候. 就会去通知所有监听了OrderEvent事件的事件监听器,那么,是由谁去负责通知? 

就是由EventMulticaster(事件多播器)将事件播报出去的.

 首先,判断有没有最定义的事件多播器. 如果有,那么直接将其添加到容器中. 如果没有,就新建一个SimpleApplicationEventMulticaster类型的事件多播器,然后将其添加beanfactory中.

那么,事件多播器都做了什么事情呢? 具体来看一看SimpleApplicationEventMulticaster类. 

 这是SimpleApplicationEventMulticaster的继承结构. 继承了AbstractApplicationEventMulticaster,而AbstractApplicationEventMulticaster又实现了ApplicationEventMulticaster. 我们看看在ApplicationEventMulticaster中都对应了哪些接口

interface ApplicationEventMulticaster {
    void addApplicationListener(ApplicationListener<?> listener);
     addApplicationListenerBean(String listenerBeanName);
    void removeApplicationListener(ApplicationListener<?> removeApplicationListenerBean(String listenerBeanName);
     removeAllListeners();  
    void multicastEvent(ApplicationEvent );
    一个是管理事件监听器,另一个是广播事件. 

我们看AbstractApplicationEventMulticaster如何实现这几个接口的

*
     * AbstractApplicationEventMulticaster管理了所有的监听器.
     * 当我们注册一个监听器以后,就会通过addApplicationListener方法添加到事件多播器中.
     * @param listener the listener to add
     void addApplicationListener(ApplicationListener<?> listener) {
        synchronized (.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);
             (singletonTarget instanceof ApplicationListener) {
                .defaultRetriever.applicationListeners.remove(singletonTarget);
            }
            .defaultRetriever.applicationListeners.add(listener);
            .retrieverCache.clear();
        }
    }

 这是添加事件监听器.

在SimpleApplicationEventMulticaster里面,定义了广播事件监听器

void multicastEvent(final ApplicationEvent null ? eventType : resolveDefaultEventType());
        获取线程池
        Executor executor = getTaskExecutor();
         从多播器中获取所有的监听器
        for (ApplicationListener<?> listener : getApplicationListeners( 拿到了监听器
            if (executor !=  异步调用广播事件
                executor.execute(() -> invokeListener(listener,1)">));
            }
            // 同步调用广播事件
                invokeListener(listener,event);
            }
        }
    }

 这里有两种方式,一种是同步的方式,另一种是异步的方式. 根据设置的eventType来决定的. 其实异步的方式就是建立了一个新的线程

我么你来看一下调用事件监听器广播事件

invokeListener#doInvokeListener

doInvokeListener(ApplicationListener listener,ApplicationEvent // 最终调用的是监听器的onApplicationEvent方法. 这个方法就是每一个监听器都会自定义方法.
            listener.onApplicationEvent(event);
        }
         (ClassCastException ex) {
            String msg = ex.getMessage();
            if (msg == null || matchesClassCastMessage(msg,1)">.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());
                 (logger.isTraceEnabled()) {
                    logger.trace(Non-matching event type for listener:  listener,ex);
                }
            }
            throw ex;
            }
        }
    }

 最终调用的是监听器的onApplicationEvent方法. 这个方法就是每一个监听器都会自定义方法.

listener.onApplicationEvent(event);

 2.9 onRefresh();这是一个扩展方法. 这里没有具体实现.spring boot也是从这个方法进行启动

2.10 注册监听器registerListeners();

 注册监听器这里一共做了三件事:

1. 将事件监听器注册到多播器上

2. 广播早期的事件

3. 清空早期事件.

到此步骤之前,上面都是有早期事件的,后面就没有早期事件了,因为这一步就都清空了. 后面也不会在进行自动广播了, 自动广播的就是早期事件.

 registerListeners() {
         Register statically specified listeners first.
        /**
         * 第一步,获取所有的事件监听器集合.
         * 通常,这个时候,事件监听器集合是空的,除非手动调用allApplicationListeners()注册事件监听器
         */
        for (ApplicationListener<?> listener : getApplicationListeners()) {
             将监听器注册到多播器上
            getApplicationEventMulticaster().addApplicationListener(listener);
        }

        
        /**
         * 第二步: 注册接口方式的监听器
         * 获取beanDeFinition中 ApplicationListener 类型的监听器. 也就是说,使用接口方式定义的监听器
      * 就可以在这里注册到多播器的 * 这里是从BeanDeFinition中拿的,我们自定义了 OrderEventListenter 监听器,那么会不会拿到呢? * 我们知道监听器的实现有两种方式,一种是注解方式. * 如果OrderEventListenter采用的是接口方式,那么就可以拿到. 因为它实现了ApplicationListener.拿到了,
     * 就把监听器注册到多播器上. * 如果是注解方式,那就拿不到了 * */
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.true,1)">);
for (String listenerBeanName : listenerBeanNames) { 把监听器注册到多播器上 getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName); } /** * 第三步: 获取早期的事件,然后广播早期事件. * 这些早期事件是在第一步 prepareRefresh 注册的. * */ Set<ApplicationEvent> earlyEventsToProcess = .earlyApplicationEvents; 在这里将早期事件清空,清空完以后,就没有早期事件了. this.earlyApplicationEvents = ; CollectionUtils.isEmpty(earlyEventsToProcess)) { (ApplicationEvent earlyEvent : earlyEventsToProcess) { getApplicationEventMulticaster().multicastEvent(earlyEvent); } } }

如上源码所示: 

第一步. 获取所有的事件监听器集合,通常这个时候,事件监听器的集合都是空的,除非我们手动调用allApplicationListeners()注册事件监听器

第二步: 注册接口方式的监听器. 注意,是接口方式的. 通常我们自定义的监听器.  有两种类型,接口方式和注解方式. 如果使用的是接口方式. 那么就是在这里注册的.如果是注解方式.不在这里注册.

getBeanNamesForType(ApplicationListener.class,true,false);
扫描获取ApplicationListener类型的监听器.

然后将其注册到多播器上. 我们知道多播器的两个主要功能,管理监听器和广播事件.

getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);

第三步: 获取早期事件,然后广播早期事件. 早期事件我们之前已经说过了,是在第一步prepareRefresh()方法注册的.

随后,立即清空早期事件集合. 然后广播事件. 这样早期定义好的事件就都被广播出去了,并且只能执行一次,不会被再次执行.

*
 * 第三步: 获取早期的事件,然后广播早期事件. 
 * 这些早期事件是在第一步 prepareRefresh 注册的.
 * 
 
Set<ApplicationEvent> earlyEventsToProcess = .earlyApplicationEvents;
;
CollectionUtils.isEmpty(earlyEventsToProcess)) {
     (ApplicationEvent earlyEvent : earlyEventsToProcess) {
        getApplicationEventMulticaster().multicastEvent(earlyEvent);
    }
}

2.11 实例化剩余的单实例bean

 这个方法就是循环遍历BeanDeFinitionMap,调用getBean,去生产剩余的bean,之前详细研究过这个步骤,这里就不说了

2.12 完成refresh()操作, 发布刷新事件 

 finishRefresh() {
     Clear context-level resource caches (such as ASM Metadata from scanning).
        clearResourceCaches();

     Initialize lifecycle processor for this context.
     注册lifecycleProcessor声明周期处理器
        initLifecycleProcessor();

     Propagate refresh to lifecycle processor first.
        getLifecycleProcessor().onRefresh();

    // Publish the final event.
    // 发布容器refresh完毕的事件.
    // 发布的是什么事件呢? 是ContextRefreshedEvent事件.
    publishEvent(new ContextRefreshedEvent(this));

    terapplicationContext();
}

在这一步: 发布了容器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
     void publishEvent(Object event,1)">Event must not be null Decorate event as an ApplicationEvent if necessary
        ApplicationEvent applicationEvent;

        /**
         * 第一步: 获取事件
         */
         instanceof ApplicationEvent) {
             处理接口类型的事件
            applicationEvent = (ApplicationEvent) ;
        }
         {
            applicationEvent = new PayloadApplicationEvent<>(this,1)">);
            if (eventType == ) {
                eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
            }
        }

        /**
         * 第二步: 发布事件
         */
         Multicast right Now if possible - or lazily once the multicaster is initialized
        this.earlyApplicationEvents != ) {
            .earlyApplicationEvents.add(applicationEvent);
        }
        
             * 调用事件多播器,将这个事件发布出去
             * 事件多播器是什么时候注册的呢? 
        * 就是在refresh()初始化的时候,调用initApplicationEventMulticaster(); 初始化的事件多播器
getApplicationEventMulticaster().multicastEvent(applicationEvent,eventType); } /** * 第三步: 发布事件给父类容器 */ Publish event via parent context as well... 发布事件给父类容器 this.parent != .parent instanceof AbstractApplicationContext) { ((AbstractApplicationContext) this.parent).publishEvent(event,eventType); } { this.parent.publishEvent(); } } }

这里做了如下几件事

1. 获取事件

2. 广播事件

3. 广播事件给父类监听器.

详细代码可以看注释

接下来看一下,具体的multicastEvent(...)

void multicastEvent(final ApplicationEvent ));
        获取线程池
        Executor executor = 从多播器中获取所有的监听器
         拿到了监听器
            ) {
                // 异步调用广播事件
                executor.execute(() -> invokeListener(listener,1)">// 同步调用广播事件
                invokeListener(listener,1)">);
            }
        }
    }

这里首先会去获取线程池. 看看有没有重新定义线程池,如果有这里executor就不是空的.

广播事件有两种形式, 一种是同步,一种是异步. 如果executor线程池不空,就以异步的形式广播,否则就以同步的形式广播. 

那么,我们如何自定义同步或者异步呢? 也是有两种方式

第一种方式: 自定义事件多波器,并指定taskExcutor

  @Bean(name = applicationEventMulticaster)
     ApplicationEventMulticaster simpleApplicationEventMulticaster() {
        SimpleApplicationEventMulticaster eventMulticaster
                =  SimpleApplicationEventMulticaster();

        ThreadPoolTaskExecutor
       这里指定了 taskExecutor,就会使用异步的方式去执行
        eventMulticaster.setTaskExecutor( SimpleAsyncTaskExecutor());
         eventMulticaster;
    }

第二种方式,在事件监听器上使用注解@Async

@Component
@Async
);
        }
    }
}

接下来看看如何广播事件的. 

*
     * Invoke the given listener with the given event.
     * @param listener the ApplicationListener to invoke
     * @param event the current event to propagate
     * @since 4.1
     void invokeListener(ApplicationListener<?> listener,1)">) {
        ErrorHandler errorHandler = getErrorHandler();
        if (errorHandler !=  {
                doInvokeListener(listener,event);
            }
             (Throwable err) {
                errorHandler.handleError(err);
            }
        }
         doInvokeListener(listener,1)">);
        }
    }

 

void doInvokeListener(ApplicationListener listener,1)"> ex;
            }
        }
    }

其实,具体执行的逻辑,就是我们在监听器中定义的onApplicationEvent(event)方法中的逻辑实现.

 

三. 注册接口方式的监听器

在上面的源码分析中,注册接口方式的监听器,其实是由两个地方. 

一个: 在第十步registerListener()

 registerListeners() {
        .....
        *
         * 第二步: 注册接口方式的监听器
         * 获取beanDeFinition中 ApplicationListener 类型的监听器. 
      * 也就是说,使用接口方式定义的监听器就可以在这里注册到多播器的 * 这里是从BeanDeFinition中拿的,那么就可以拿到. 因为它实现了ApplicationListener.
      * 拿到了,就把监听器注册到多播器上. * 如果是注解方式,那就拿不到了 *
把监听器注册到多播器上
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName); } ..... }

 另一个: 是在第三步进行属性填充的时候注册

 preparebeanfactory(ConfigurableListablebeanfactory beanfactory) {
        ......
        *
         * 注册事件监听器探测器后置处理器接口,ApplicationListenerDetector 解析接口方式的监听器
         */
        beanfactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

        ......
    }

在准备属性方法里,有一个注册时间监听器探测器后置处理. 在这个监听器的探测器里面,进行了注册.

来看看ApplicationListenerDetector

 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
      (bean instanceof ApplicationListener) {
             singleton bean (top-level or inner): register on the fly
                'implements ApplicationListener interfacebut is not reachable for event multicasting by its containing ApplicationContextbecause it does not have singleton scope.Only top-level listener beans are allowed bean;
    }
.......
}

我们看到在ApplicationListenerDetector中定义了方法postProcessAfterInitialization. 这个方法会在创建属性的第三步执行完以后调用. 第三步是初始化. 看名字也知道是初始化之后调用的后置处理器. 在这里,注册了接口类型的监听器

this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);

那么,为什么要有两次注册呢?

其实这里是为了解决懒加载的问题. 因为,如果一个类是懒加载的类,那么他只有真正被调用的时候才回去加载. 所以,也就是在类进行初始化以后才会被调用. 因此在初始化之后再次加载了接口类型的监听器. 

四. 解析注解方式的监听器

整个流程走完,我们都只看到接口方式的监听器注册的地方. 那么注解类型的监听器是什么时候被创建的呢?

首先,注解是何时被解析的? 我们知道BeanDeFinitionReader在解析创世纪的类的时候,注册了很多创世纪的类.其中就有两个是用于负责处理@EventListener注解的

再来回顾一下这段代码

static Set<BeanDeFinitionHolder>  registerannotationConfigProcessors(
            BeanDeFinitionRegistry registry,@Nullable Object source) {

         获取beanfactory
        DefaultListablebeanfactory beanfactory = unwrapDefaultListablebeanfactory(registry);
        *
         * 判断beanfactory中是否有AnnotationAwareOrderComparator和ContextAnnotationAutowireCandidateResolver
         * 没有则添加
         if (beanfactory != (beanfactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
                beanfactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
            }
            (beanfactory.getAutowireCandidateResolver() instanceof 
                  ContextAnnotationAutowireCandidateResolver)) { beanfactory.setAutowireCandidateResolver(
ContextAnnotationAutowireCandidateResolver()); } } BeanDeFinitionHolder: 为BeanDeFinition设置名字和别名 Set<BeanDeFinitionHolder> beanDefs = new LinkedHashSet<>(8 如果registry中没有ConfigurationClasspostProcessor配置类后置处理器,就添加一个 registry.containsBeanDeFinition(CONfigURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDeFinition def = new RootBeanDeFinition(ConfigurationClasspostProcessor.); def.setSource(source); 构建BeanDeFinitionHolder,并添加到beanDefs beanDefs.add(registerPostProcessor(registry,def,CONfigURATION_ANNOTATION_PROCESSOR_BEAN_NAME)); } 如果rigistry中,没有AutowiredAnnotationBeanPostProcessor Autowired注解bean的后置处理器,则添加一个 registry.containsBeanDeFinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDeFinition def = new RootBeanDeFinition(AutowiredAnnotationBeanPostProcessor. Check for JSR-250 support,and if present add the CommonAnnotationBeanPostProcessor. 检查对JSR-250的支持,如果rigistry中没有 CommonAnnotationBeanPostProcessor 通用注解后置处理器,1)">if (jsr250Present && !registry.containsBeanDeFinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDeFinition def = new RootBeanDeFinition(CommonAnnotationBeanPostProcessor. Check for JPA support,and if present add the PersistenceAnnotationBeanPostProcessor. 检查对jpa的支持,如果不包含 internalPersistenceAnnotationProcessor,持久化注解处理器,1)">if (jpaPresent && !registry.containsBeanDeFinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDeFinition def = RootBeanDeFinition(); { def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,AnnotationConfigUtils..getClassLoader())); } (ClassNotFoundException ex) { IllegalStateException( Cannot load optional framework class:
                    PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,ex); } def.setSource(source); beanDefs.add(registerPostProcessor(registry,PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)); }
/** * 下面这两个注解是用来解析@EventListener的 */ 检查对事件监听的支持,如果不包含事件监听处理器 internalEventListenerProcessor,1)"> * EventListenerMethodProcessor : 既不是bean的后置处理器,也不是bean工厂的后置处理器 * 那么EventListenerMethodProcessor是在哪里被调用,并且解析注解方式的监听器呢? * * 下面看一下EventListenerMethodProcessor的继承结构图. * 1. 实现了SmartinitializingSingleton接口 : * 2. 实现了ApplicationContextAware接口 : 因为要往容器中注入bean,里面要使用容器的上下文,
      * 将容器以Aware的方式set进来 * 3. 实现了beanfactoryPostProcessor接口 : * *
registry.containsBeanDeFinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) { RootBeanDeFinition def = new RootBeanDeFinition(EventListenerMethodProcessor.); def.setSource(source); beanDefs.add(registerPostProcessor(registry,EVENT_LISTENER_PROCESSOR_BEAN_NAME)); } 如果不包含事件监听工厂处理器 internalEventListenerFactory,1)">EVENT_LISTENER_FACTORY_BEAN_NAME)) { RootBeanDeFinition def = new RootBeanDeFinition(DefaultEventListenerFactory. beanDefs; }

 如上图就是注册的创世纪的处理器. 最后两个就是用来处理@EventListener注解的.

下面来看看EventListenerMethodProcessor事件监听器处理器,

首先, 看一下EventListenerMethodProcessor的继承结构图.

 

 EventListenerMethodProcessor实现了三个接口. 

1.实现了SmartinitializingSingleton接口

2. 实现了ApplicationContextAware接口 : 因为要往容器中注入bean,将容器以Aware的方式set进来 

3. 实现了beanfactoryPostProcessor接口

SmartinitializingSingleton接口在哪里被用到了呢? 

在refresh()#finishbeanfactoryInitialization(beanfactory); 实例化剩余的单例bean的过程中

在DefaultListablebeanfactory#preInstantiateSingletons()方法. 有两次循环遍历beanNames

 preInstantiateSingletons() throws BeansException {
         (logger.isTraceEnabled()) {
            logger.trace(Pre-instantiating singletons in );
        }

         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<>(.beanDeFinitionNames);

         Trigger initialization of all non-lazy singleton beans...
        /**
         * 第一步: 循环bean定义的name,创建bean
          */
         (String beanName : beanNames) {
             获取bean定义
            RootBeanDeFinition bd = getMergedLocalBeanDeFinition(beanName);
             生产bean定义的条件: 不是抽象的,是单例的,不是懒加载的. 符合这个标准的,最后才会调用getBean()生产bean
            if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                 这里判断是不是工厂bean,这里和beanfactory不是一个意思,判断当前这个bean是否实现了beanfactory的接口
                 (isfactorybean(beanName)) {
                    Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                     (bean instanceof factorybean) {
                         将bean转换为factorybean 工厂bean
                        final factorybean<?> factory = (factorybean<?>) bean;
                        boolean isEagerInit;
                        null && factory instanceof Smartfactorybean) {
                            isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
                                            ((Smartfactorybean<?>) factory)::isEagerInit,getAccessControlContext());
                        }
                         {
                            isEagerInit = (factory instanceof Smartfactorybean &&
                                    ((Smartfactorybean<?>) factory).isEagerInit());
                        }

                         (isEagerInit) {
                             获取bean
                            getBean(beanName);
                        }
                    }
                }
                 第二步: 调用getBean
                    getBean(beanName);
                }
            }
        }

         Trigger post-initialization callback for all applicable beans...
        /**
         * 第二步: 循环bean定义的name,解析是否有实现了SmartinitializingSingleton接口的类
         * 到这里,bean都已经被创建完了
         */
         从缓存中得到实例instance
            Object singletonInstance = getSingleton(beanName);
             (singletonInstance instanceof SmartinitializingSingleton) {
                final SmartinitializingSingleton smartSingleton = (SmartinitializingSingleton) singletonInstance;
                ) {
                    AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                        smartSingleton.afterSingletonsInstantiated();
                        ;
                    },getAccessControlContext());
                }
                 {
                    smartSingleton.afterSingletonsInstantiated();
                }
            }
        }
    }

第一次循环,是创建bean,并获取bean

第二次循环,是在所有的bean都已经创建完以后,如果singletonInstance是SmartinitializingSingleton的实例,则调用afterSingletonsInstantiated()方法

以下是EventListenerMethodProcessor#afterSingletonsInstantiated()方法实现 

 afterSingletonsInstantiated() {
        spring容器获取EventListenerfactorybean
        ConfigurableListablebeanfactory beanfactory = .beanfactory;
        Assert.state(this.beanfactory != null,1)">No ConfigurableListablebeanfactory set 获取所有类型的bean
        String[] beanNames = beanfactory.getBeanNamesForType(Object.ScopedProxyUtils.isScopedTarget(beanName)) {
                Class<?> type = ;
                 {
                    type = AutoproxyUtils.determineTargetClass(beanfactory,beanName);
                }
                 (Throwable ex) {
                     An unresolvable bean type,probably from a lazy bean - let's ignore it.
                     (logger.isDebugEnabled()) {
                        logger.debug(Could not resolve target class for bean with name ''if (type != ) {
                    if (Scopedobject..isAssignableFrom(type)) {
                         {
                            Class<?> targetClass = AutoproxyUtils.determineTargetClass(
                                    beanfactory,ScopedProxyUtils.getTargetBeanName(beanName));
                            if (targetClass != ) {
                                type = targetClass;
                            }
                        }
                         (Throwable ex) {
                             An invalid scoped proxy arrangement - let's ignore it.
                             (logger.isDebugEnabled()) {
                                logger.debug(Could not resolve target bean for scoped proxy '" + 
                    beanName + { processBean(beanName,type); } (Throwable ex) { new BeanInitializationException(Failed to process @EventListener " + annotation on bean with name '
void processBean(final String beanName,final Class<?> targettype) {
        // 1. 是否包含注解@EventListener
        this.nonAnnotatedClasses.contains(targettype) &&
                AnnotationUtils.isCandidateClass(targettype,EventListener.class) &&
                !isspringContainerClass(targettype)) {

            Map<Method,EventListener> annotatedMethods = ;
            // 2. 查找@EventListener注解,如果有则拿到标注@EventListener的方法
                annotatedMethods = MethodIntrospector.selectMethods(targettype,(MethodIntrospector.MetadataLookup<EventListener>) method ->
                                AnnotatedElementUtils.findMergedAnnotation(method,1)"> (Throwable ex) {
                 An unresolvable type in a method signature,probably from a lazy bean - let's ignore it.
                 (logger.isDebugEnabled()) {
                    logger.debug(Could not resolve methods for bean with name ' (CollectionUtils.isEmpty(annotatedMethods)) {
                .nonAnnotatedClasses.add(targettype);
                No @EventListener annotations found on bean class:  targettype.getName());
                }
            }
             Non-empty set of methods
                ConfigurableApplicationContext context = .applicationContext;
                Assert.state(context != No ApplicationContext set);

                // 3. 获取bean工厂. 这个bean工厂是我们在创世纪的时候注册的EventListenerFactory
                List<EventListenerFactory> factories = .eventListenerFactories;
                Assert.state(factories != EventListenerFactory List not initialized);
                // 4. 循环遍历有注解的方法
                 (Method method : annotatedMethods.keySet()) {
                     (EventListenerFactory factory : factories) {
                         (factory.supportsMethod(method)) {
                            Method methodToUse = AopUtils.selectinvocableMethod(method,context.getType(beanName));

                            //5. 创建事件监听器
                            ApplicationListener<?> applicationListener =
                                    factory.createApplicationListener(beanName,targettype,methodToUse);
                             (applicationListener instanceof ApplicationListenerMethodAdapter) {
                                ((ApplicationListenerMethodAdapter) applicationListener).
                        init(context,1)">.evaluator); }
// 6. 将监听器注入到多播器中 context.addApplicationListener(applicationListener); break; } } } (logger.isDebugEnabled()) { logger.debug(annotatedMethods.size() + @EventListener methods processed on bean ' beanName + ': annotatedMethods); } } } }

1. 首先判断,是否包含@EventListener注解

2. 查找@EventListener注解,如果有则拿到标注@EventListener的方法

3. 获取bean工厂. 这个bean工厂是我们在创世纪的时候注册的EventListenerFactory

4. 循环遍历有注解的方法

5. 创建事件监听器

6. 将监听器注入到多播器中

 

 以上就是注解版的监听器是如何注入到多播器中的. 

五. 怎样在所有的bean都创建完以后做扩展代码?

第一种方式,添加内置的监听器,类加载完以后,调用监听器

第二种方法. 就是在使用注解方式的时候,  实现SmartinitializingSingleton接口. 然后在bean实例化完成以后,在调用

 

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐