SpringIoC容器的初始化 【打通refresh方法的全链路】

本章节目录:

  (一)后 置 处 理 器  PostProcessor

  (二)Aware 接  口  及  其  子  接  口

    (三)事 件 监 听 器 模 式

    (四)Refresh 方 法 源 码 详 解

 


 

(一)后 置 处 理 器  PostProcessor

PostProcessor:

  本身也是一种需要注册到容器里的Bean

      其里面的方法会在特定的时机被容器调用

      实现不改变容器或者Bean核心逻辑的情况下对Bean进行拓展

      对Bean进行包装,影响其行为、修改Bean的内容等

PostProcessor的种类:

  大类分为容器级别的后置处理器以及Bean级别的后置处理器

      BeanDefinitionRegistryPostProcessor

     BeanFactoryPostProcessor

     BeanPostProcessor

 

BeanDefinitionRegistryPostProcessor的使用:

  下面代码意为:在BeanDefinitionRegistry注册BeanDefinition之前调用方法。执行完方法后我们就可以在容器中获取到该Bean

 


@Configuration
public class CustomizedBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        Class<?> clazz = User.class;//新建User的Class对象
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(clazz);//将Class对象获取到创建BeanDefinition的工具类
        GenericBeanDefinition definition = (GenericBeanDefinition)builder.getRawBeanDefinition();//通过工具类创建BeanDefinition
        registry.registerBeanDefinition("user",definition);//调用注册器 注册BeanName为“user”,BeanDefinition为刚刚新建的对象。

    }
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {}
}

 

 

BeanPostProcessor的使用:

  下面代码意为:在Bean注册创建之前(之后)调用方法。

@Configuration
public class CustomizedBeanPostProcessor implements BeanPostProcessor {
    //Bean创建前调用
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println(beanName + "调用了postProcessBeforeInitialization()");
        return bean;//返回Bean提供后续创建
    }

    //Bean初始化好之后调用
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println(beanName + "调用了postProcessAfterInitialization()");
        return bean;
    }
}

 

 

 

 


 

 

(二)Aware  接  口  及  其  子  接  口

 

 

Aware:

   从Bean里获取到的容器实例并对其进行操作

  该接口是个空的接口,并没有什么作用,只能当作标签使用

  该接口的主要作用体现在它的子类中

 

Aware的关系图:(常用的子接口)

 

 

 

 

 

 

ApplicationContextAware接口主要一个方法setApplicationContext() :实现了该接口的Bean在容器创建这个Bean的实例时,将容器本身的实例作为参数传递给这个Bean使用

 

BeanFactory接口:获取当前的BeanFactory提供调用服务

 

ResourceLoaderAware:主要就是用来获取资源加载器的

 

BeanNameAware接口主要一个方法setBeanName(String name):实现了该接口的Bean,可以将Bean的名字传递进来供该接口使用。

 

 

 

 

 

 

 

 


 

 

(三)事 件 监 听 器 模 式

关于事件监听器设计模式的介绍:事 件 监 听 器 模 式

 

标准事件

  Spring的ApplicationContext 提供了支持事件和代码中监听器的功能。

  我们可以创建bean用来监听在ApplicationContext 中发布的事件。ApplicationEvent类和在ApplicationContext接口中处理的事件,

  如果一个bean实现了ApplicationListener接口,当一个ApplicationEvent 被发布以后,bean会自动被通知。

Spring的事件驱动模型

  事件驱动模型的三大组成部分:

    事件:ApplicationEvent抽象类

    事件监听器:ApplicationListener

    事件发布器:ApplicationEventPublisher 以及 ApplicationEventMulticaster

 

为什么事件发布器需要ApplicationEventPublisher 接口和ApplicationEventMulticaster接口呢?

  站在设计者的角度上来考虑问题呢,像Bean和容器本身就只想发布事件而不想维护事件监听器,所以Spring将事件源做了进一步分割,抽象出事件发布器接口,将ApplicationEventMulticaster作为代理。

  就像ApplicationContext用我们的DefaultListableBeanFactory作为代理一样。让ApplicationEventPublisher的实现类来实现publishEvent方法里面的逻辑,那publish里面就主要去实现调用ApplicationEventMulticaster的实现类的multicastEvent方法来发布事件就好了。

  AbstractApplicationContext的refresh方法里面也是这么使用两者的。

 

ApplicationEvent的关系图:

 

 

ApplicationEvent继承了jdk中的EventObject类,ApplicationEvent并不是单纯的表示为容器事件类。

 

为了给容器专门定制一个事件类还专门设置了一个子类ApplicationContextEvent(抽象类)

 

   ApplicationContextEvent的实现子类如下:

    1. 上下文更新事件(ContextRefreshedEvent):该事件会在ApplicationContext被初始化或者更新时发布。也可以在调用ConfigurableApplicationContext 接口中的refresh()方法时被触发。
    2. 上下文开始事件(ContextStartedEvent)     :当容器调用ConfigurableApplicationContext的Start()方法开始/重新开始容器时触发该事件。
    3. 上下文停止事件(ContextStoppedEvent)   :当容器调用ConfigurableApplicationContext的Stop()方法停止容器时触发该事件。
    4. 上下文关闭事件(ContextClosedEvent)     :当ApplicationContext被关闭时触发该事件。容器被关闭时,其管理的所有单例Bean都被销毁。

 

ApplicationListener的关系图:

 

ApplicationListener继承自JDK的EventListenner。JDK要求所有的监听器都继承自EventListener。

 

ApplicationEventMulticaster的关系图:

 

 

 进入到AbstractApplicationEventMulticaster类中,可以看到里头的成员变量,看类型的名字(ListenerRetriever)就知道它是用来保存注册进来的Listener的(详细可跟进ListenerRetriever类中的成员变量applicationListeners)

 

 

AbstractApplicationEventMulticaster是抽象类,如果本地容器中没有该类的实现则默认使用实现类:SimpleApplicationEventMulticaster。

SimpleApplicationEventMulticaster类中有成员变量(Executor  taskExecutor) 该成员变量为任务执行器,有执行器则意味着该类支持多线程去处理监听器的方法。

 

 


 

 

(四)Refresh  方  法  源  码  详  解

 

AbstractApplicationContext.Refresh()方法(大致流程):

preareRefresh 刷新前的工作准备
obtainFreshBeanFactory 获取子类刷新后的内部beanFactory实例
prepareBeanFactory 为容器注册必要的系统级别的Bean
postProcessBeanFactory 允许容器的子类去注册postProcessor
invokeBeanFactoryPostProcessors 调用容器注册的容器级别的后置处理器
registerBeanPostProcessors 向容器注册Bean级别的后置处理器
initMessageSource 初始化国际化配置
initApplicationEventMulticaster 初始化事件发布者组件
onRefresh 在单例Bean初始化之前预留给子类初始化其他特殊bean的口子
registerListeners 向前面的事件发布者组件注册事件监听者
finishBeanFactoryInitialization 设置系统级别的服务,实例化所有非懒加载的单例
finishRefresh 触发初始化完成的回调方法,并发布容器刷新完成的事件给监听者
resetCommonCaches 重置Spring内核中的共用缓存

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

public void refresh() throws BeansException, IllegalStateException {
        //给容器refresh加锁,避免容器处在refresh阶段时,容器进行了初始化或者销毁的操作
        synchronized (this.startupShutdownMonitor) {
            // 调用容器准备刷新的方法,获取容器的当前时间,同时给容器设置同步标识,具体方法
            prepareRefresh();

            // 告诉子类启动refreshBeanFactory()方法,Bean定义资源文件的载入从
            //子类的refreshBeanFactory()方法启动,里面有抽象方法
            //针对xml配置,最终创建内部容器,该容器负责Bean的创建于管理,此步会进行BeanDefinition的注册
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // 注册一些容器中需要的系统Bean。例如classloader,beanfactoryPostProcessor等
            prepareBeanFactory(beanFactory);

            try {
                // 允许容器的子类去注册postProcessor(钩子方法)
                postProcessBeanFactory(beanFactory);

                // 调用作为上下文中的bean注册的工厂处理器。
                //激活在容器中注册为bean的BeanFactoryPostProcessors
                //对于注解容器,org.springframework.context.annotation.ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
                //方法扫描应用中所有BeanDefinition并注册到容器之中
                invokeBeanFactoryPostProcessors(beanFactory);

                // 注册拦截bean创建的bean处理器。
                registerBeanPostProcessors(beanFactory);

                // 初始化此上下文的消息源。
                //找到"messageSource"的Bean提供给ApplicationContext使用
                //使得ApplicationContext具有国际化能力
                initMessageSource();

                // 为此上下文初始化事件多播程序。
                //初始化ApplicationEventMulticaster该类作为事件发布者
                //可以存储所有事件监听者信息,并根据不同的事件,通知不 同的事件监听者。
                initApplicationEventMulticaster();

                // 在特定的上下文子类中初始化其他特殊bean。
                //预留给AbstractApplicationContext的子类用于初始化其他特殊的bean,
                //该方法需要在所有单例bean初始化之前调用
                //比如Web容器就会去初始化一些和主题展示相关的Bean(ThemeSource)
                onRefresh();

                // 检查侦听器bean并注册它们(检查监听器的bean并注册他们)
                //(往先前初始化的ApplicationEventMulticaster中注册监听器)
                registerListeners();


                //设置自定义的类型转换器ConversionService
                //设置自定义AOP相关的类LoadTimeWeaverAware
                // 实例化所有剩余的(非lazy-init)单例。
                finishBeanFactoryInitialization(beanFactory);

                // 最后一步:发布相应的事件。
                //初始化容器的生命周期事件处理器,(默认使用DefaultLifecycleProcessor),调用拓展了SmartLifecycle
                //当Spring容器加载所有bean并完成初始化之后,会接着回调实现该接口的类中对应的方法(start()方法,)
                //并发布容器刷新完毕事件ContextRefreshedEvent给对应的事件监听者
                finishRefresh();
            }

            catch (BeansException ex) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
                }
                // 销毁已经创建的单例,以避免悬浮资源。
                destroyBeans();

                // 重置“活跃”的旗帜。
                cancelRefresh(ex);

                // 将异常传播给调用者。
                throw ex;
            }

            finally {
                // Reset common introspection caches in Spring's core, since we
                // might not ever need metadata for singleton beans anymore...
                //重置Spring内核中的共用的缓存,因为我们可能再也不需要单例bean的元数据了...
                resetCommonCaches();
            }
        }
    }

 

1.在执行refresh的时候,首先给内部代码全部套上了synchronized锁,避免当前线程在操作容器的时候,有其他线程操作。

2.调用prepareRefresh()方法,该方法主要为刷新容器做准备

   (1)设置启动时间,提供后续的日志记录和统计工作(2)将容器的状态设置为激活状态(3)设置日志等级(4)initPropertySources()【初始化Environment的propertySources属性】初始化环境默认属性值(property)

   (5)getEnvironment().validateRequiredProperties()【校验是否还有些必要的属性值没有加载到】(6)查看是否有容器启动的时候就加载监听器,若是有则加载到this.earlyApplicationListeners中(7)创建事件的集合

 

3.⭐调用obtainFreshBeanFactory()方法,该方法对于Xml容器来讲是很重要的,方法内部调用了自类(AbstractRefreshableApplicationContext)进行BeanDefinition的注册,对于注解来讲,仅仅是调用了子类(GenericApplicationContext)的refreshBeanFactory,最终返回DefaultListableBeanFactory实例

4.调用prepareBeanFactory()方法,该方法便是为刷新容器做准备的。

 (1)为内部容器(DefaultListableBeanFactory)(beanFactory)设置上外部容器的类加载器  (2)为beanFactory设置上表达式语言处理器(3)为beanFactory设置上默认的属性编辑器

   (4)为beanFactory设置上ApplicationContext后置器 (5)如果某些bean依赖Aware接口的实现类,在自动装配的时候忽略的,后期处理   (6)为beanFactory修正依赖,注册一些自动装配的特殊规则 

   (7)往容器中设置检查内部bean的应用程序监听器  (8)判断beanFactory是否需要LTW织入器,如果是还为其设置上临时的类加载器  (9)如果系统需要则设置一些默认环境bean承载默认的系统环境变量  

 

5. 调用invokeBeanFactoryPostProcessors()方法,该方法扫描应用中所有BeanDefinition并注册到容器之中

6.调用registerBeanPostProcessors()方法,该方法会注册拦截bean创建的bean处理器

7.调用initMessageSource()方法, 使ApplicationContext具有国际化能力

8.调用initApplicationEventMulticaster()方法,初始化事件发布器

9.调用onRefresh()方法,初始化特殊的Bean(该方法需要在所有单例bean初始化之前调用)(比如Web容器就会去初始化一些和主题展示相关的Bean(ThemeSource))(钩子方法)

10.调用registerListeners()方法,注册监听器(往先前初始化的ApplicationEventMulticaster中注册监听器)

11.调用finishBeanFactoryInitialization()方法,实例化所有剩余的(非lazy-init)单例

  (1)判断容器中是否有自动的类型转换器(有则给beanfactory设置上)(2)⭐往容器中注册默认的解析器(例如解析properties文件的PropertyPlaceholderConfigurer)

     (3)获取编织器的bean实例以便进行类加载器的AOP操作(此时还没操作)(4)停止使用临时类加载器进行类型匹配 

    (5)允许缓存所有bean定义元数据,不希望有进一步更改(使得原先刷新好的bean稳定可靠)(6)⭐实例化所有剩余的(non-lazy-init非延时加载的)单例

 

12.调用finishRefresh()方法,该方法主要做一些收尾的工作。发布相应的事件

  (1)清除Resource缓存  (2)为容器初始化生命周期处理器  (3)将刷新的事件传播的生命周期处理器  (4)发布最终事件(容器刷新完成事件) (5)往JMS组件中注册容器 

 

posted @ 2021-02-18 10:12  _kerry  阅读(122)  评论(0编辑  收藏  举报