4.1 Spring源码 --- 监听器的原理(一)

785 阅读18分钟

这是我参与8月更文挑战的第19天,活动详情查看:8月更文挑战

目标:

  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;
    }

    public 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.
 */
public class OrderEvent  extends ApplicationEvent implements Serializable {

    private static final long serialVersionUID = 1L;

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.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
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("事件监听器  监听到  减库存");
        }
    }
}

是不是和mq相差不多.

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

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

package com.lxl.www.events;

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

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

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

        // 发布事件. 当在这里发布事件, 那么就会被事件监听器监听到
        ctx.publishEvent(new OrderEvent(order, "减库存"));
        System.out.println("日志.....");
    }
}

输出结果

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

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

 

1.3 监听器的类型

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

1.3.1 内置监听器

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

public abstract class ApplicationContextEvent extends ApplicationEvent {

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

    /**
     * Get the {@code ApplicationContext} that the event was raised for.
     */
    public final ApplicationContext getApplicationContext() {
        return (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
     */
    @Override
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.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 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();
     // 发布容器启动完毕事件
        publishEvent(new ContextRefreshedEvent(this)); // Participate in LiveBeansView MBean, if active.
        LiveBeansView.registerApplicationContext(this);
    }

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

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

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

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

/**
 * 自定义一个事件监听器, 用来监听ContextRefreshedEvent事件
 */
@Component
public class ContextRefreshedEventListener {

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

  }
}

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

 

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

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

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

            LiveBeansView.unregisterApplicationContext(this);

            try {
                 // Publish shutdown event.
                publishEvent(new ContextClosedEvent(this )); 
            }
            catch (Throwable ex) {
                logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
            }

            // Stop all Lifecycle beans, to avoid delays during individual destruction.
            if (this.lifecycleProcessor != null) {
                try {
                    this.lifecycleProcessor.onClose();
                }
                catch (Throwable ex) {
                    logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
                }
            }

            // 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.
            if (this.earlyApplicationListeners != null) {
                this.applicationListeners.clear();
                this.applicationListeners.addAll(this.earlyApplicationListeners);
            }

            // Switch to inactive.
            this.active.set(false);
        }
    }

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

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

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

  

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

 

 1.3.2 自定义监听器

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

类型一: 基于接口 

@Component
public class HelloEventListener implements ApplicationListener<OrderEvent>  {

  @Override
  public void onApplicationEvent(OrderEvent event) {
      if (event.getName().equals("减库存")) {
        System.out.println("减库存....");
      }
  }
}

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

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

类型二: 基于注解

@Component
public class OrderEventListener {

   @EventListener(OrderEvent. class) public void onApplicationEvent(OrderEvent event) {
    if (event.getName().equals("减库存")) {
      System.out.println("减库存....");
    }
  }

} 

在方法上面添加注解 @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...
        if (this.earlyApplicationListeners == null) {
            this.earlyApplicationListeners = new LinkedHashSet<>(this .applicationListeners); 
        }
        else {
            // Reset local application listeners to pre-refresh state.
            this.applicationListeners.clear();
            this.applicationListeners.addAll(this.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 void     refreshBeanFactory() throws IllegalStateException {
        if (!this.refreshed.compareAndSet(false, true)) {
            throw new IllegalStateException(
                    "GenericApplicationContext does not support multiple refresh attempts: 
                just call 'refresh' once");
        }
         // 指定bean工厂的序列化ID
        this .beanFactory.setSerializationId(getId()); 
    }

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

@Override
    protected final void refreshBeanFactory() throws BeansException {
        // 判断bean工厂是否初始化过, 如果已经初始化过那么销毁并关闭
        if (hasBeanFactory()) {
           destroyBeans();
            closeBeanFactory();
        }
        try {
            // 重新创建一个bean工厂
            DefaultListableBeanFactory beanFactory = createBeanFactory(); // 设置序列化id
            beanFactory.setSerializationId(getId());
            // 设置个性化属性
            customizeBeanFactory(beanFactory);
             // 加载BeanDefinition
            loadBeanDefinitions(beanFactory); this.beanFactory = beanFactory;
        }
        catch (IOException ex) {
            throw 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);

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

protected void 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(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
        // 为bean工厂设置一个PropertiesEditor属性资源编辑器(用于后面给bean对象赋值)
        beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

        // 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.class);
        beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
        beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
        beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

        // 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.class, beanFactory);
        beanFactory.registerResolvableDependency(ResourceLoader.class, this);
        beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
        beanFactory.registerResolvableDependency(ApplicationContext.class, this);

        // 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.
        if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            // Set a temporary ClassLoader for type matching.
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }

        // Register default environment beans.
        if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
            beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
        }
        if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
            beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
        }
        if (!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() != null) {
            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                // 在初始化完成以后, 调用aware
                invokeAwareMethods(beanName, bean);
                return null;
            }, getAccessControlContext());
        }
        else {
             // 在初始化的时候, 会调用很多的aware.  invokeAwareMethods(beanName, bean); 
        }

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

        try {
            // 调用初始化方法
            invokeInitMethods(beanName, wrappedBean, mbd);
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    (mbd != null ? mbd.getResourceDescription() : null),
                    beanName, "Invocation of init method failed", ex);
        }
        if (mbd == null || !mbd.isSynthetic()) {
            // 再初始化之后调用bean的后置处理器
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }

        return wrappedBean;
    }

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

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

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

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

 

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

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

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

/**
     * 判断bean是否实现了各种Aware
     * @param bean
     */
    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);
        }
    }

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

@Override
    @Nullable
    public Object 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)){
            return bean;
        }

        AccessControlContext acc = null;

        if (System.getSecurityManager() != null) {
            acc = this.applicationContext.getBeanFactory().getAccessControlContext();
        }

        if (acc != null) {
            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                invokeAwareInterfaces(bean); return null;
            }, acc);
        }
        else {
            invokeAwareInterfaces(bean); 
        }

        return 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);
当注册了依赖解析以后, 例如当注册了对BeanFactory.class的解析依赖后,
当bean属性注入的时候, 一旦检测到属性为beanFactory类型. 便会将BeanFactory的实例注册解析
为什么呢?
比如:
@Autowired
ApplicationContext applicationContext; .
为什么能够自动装配, 通过@Autowired引入呢? 就是在这里装配的
这个也是在注入属性popularBean的时候体现的

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

beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

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

 @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;
    }

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

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