SpringBoot源码之容器刷新 refreshContext 方法详解


highlight: androidstudio

上一篇我们聊了Springboot的run方法,今天我们聊下关于容器刷新(refresh)

本文很长,请各位同学要忍一下~~~

好了,废话不多说,直接开干 !!!

1.refresh 主方法 (重要)

``` java public void refresh() throws BeansException, IllegalStateException { //加锁 防止出现其他线程也来刷新容器 synchronized(this.startupShutdownMonitor) { // 1.1 上下文刷新前的一些准备工作。如记录容器的启动时间、标记“已启动”状态、处理配置文件中的占位符等 this.prepareRefresh(); /* 1.2 创建 BeanFactory(DefaultListableBeanFactory) 并设置序列化id, 其用来加载 Bean 定义、注册 Bean 等 */ ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory(); // 1.3 设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean this.prepareBeanFactory(beanFactory);

try {
        /* 
        1.4
        允许在上下文 子类中对 beanFactory进行 (后置处理) 
       【这里需要知道 BeanFactoryPostProcessor 这个知识点,Bean 如果实现了此接口,
        那么在容器初始化以后,Spring 会负责调用里面的 postProcessBeanFactory 方法。】
        这里是提供给子类的扩展点,到这里的时候,所有的 Bean 都加载、注册完成了,但是都还没有初始化
        具体的子类可以在这步的时候添加一些特殊的 BeanFactoryPostProcessor 的实现类或做点什么事
        */
        this.postProcessBeanFactory(beanFactory);

        //1.5 Bean工厂的后置处理器,BeanFactoryPostProcessor(触发时机:bean定义 注册之后; bean实例化之前)  
        //简单来说就是调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 方法
        this.invokeBeanFactoryPostProcessors(beanFactory);

        // 1.6 注册 BeanPostProcessor 的实现类,注意看和 BeanFactoryPostProcessor 的区别
        // 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
        // 两个方法分别在 Bean 初始化之前和初始化之后得到执行。注意,到这里 Bean 还没初始化
        this.registerBeanPostProcessors(beanFactory);

        //国际化相关 (略)
        this.initMessageSource();

        //1.7 初始化当前 ApplicationContext 的事件广播器 (略)
        this.initApplicationEventMulticaster();

        //1.8 具体的子类可以在这里初始化一些特殊的 Bean
        this.onRefresh();

        //1.9 注册事件监听器,监听器需要实现 ApplicationListener 接口  (略)
        this.registerListeners();

        //2.0 初始化所有的 singleton beans(lazy-init 的除外)(重要)
        this.finishBeanFactoryInitialization(beanFactory);

        // 发布 ApplicationContext 初始化完成事件
        this.finishRefresh();

    } catch (BeansException var9) {
        if (this.logger.isWarnEnabled()) {
            this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
        }
        //销毁bean
        this.destroyBeans();
        //清除缓存
        this.cancelRefresh(var9);
        //抛出异常
        throw var9;
    } finally {
        //重置 Spring 中的常见内省缓存,因为我们可能不再需要单例 bean 的元数据......
        this.resetCommonCaches();
    }

}

} ```

2. 接下来 将把以上流程展开

1.1 prepareRefresh

  • 上下文刷新前的一些准备工作。如记录容器的启动时间、标记“已启动”状态、处理配置文件中的占位符等 ```java protected void prepareRefresh() { // 记录启动时间 this.startupDate = System.currentTimeMillis(); this.closed.set(false); // 标记状态 this.active.set(true); if (this.logger.isDebugEnabled()) { if (this.logger.isTraceEnabled()) { this.logger.trace("Refreshing " + this); } else { this.logger.debug("Refreshing " + this.getDisplayName()); } }

    this.initPropertySources(); //校验必须配置 this.getEnvironment().validateRequiredProperties(); if (this.earlyApplicationListeners == null) { this.earlyApplicationListeners = new LinkedHashSet(this.applicationListeners); } else { this.applicationListeners.clear(); this.applicationListeners.addAll(this.earlyApplicationListeners); }

    this.earlyApplicationEvents = new LinkedHashSet(); } ```

1.2 obtainFreshBeanFactory

  • 创建 BeanFactory(DefaultListableBeanFactory) 并设置序列化id,其用来加载 Bean 定义、注册 Bean 等

java protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { // 关闭旧的 BeanFactory (如果有),创建新的 BeanFactory(DefaultListableBeanFactory) 并设置序列化id,其用来加载 Bean 定义、注册 Bean 等 this.refreshBeanFactory(); // getBeanFactory BeanFactory实际为 DefaultListableBeanFactory 。 return this.getBeanFactory(); }

image.png

image.png

这里我们附一张 DefaultListableBeanFactory 类图,关于他 可以自行谷歌一下

image.png

1.3 prepareBeanFactory

  • 设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean (prepareBeanFactory)

```java protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { //设置类加载器 beanFactory.setBeanClassLoader(this.getClassLoader()); //beanFactory的表达式语言处理器,Spring3增加了表达式语言的支持,
//默认可以使用#{bean.xxx}的形式来调用相关属性值 beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())); //设置PropertyEditorRegistrar,通过PropertyEditor将xml解析出来的bean属性(字符串)和相应的java类型做转换 beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, this.getEnvironment()));

/*
   添加后置处理器ApplicationContextAwareProcessor,在Bean初始化后自动执行各Aware接口的set方法

   实现了 Aware 接口的 beans 在初始化的时候,这个 processor 将会回调,
   这个我们很常用,如我们会为了获取 ApplicationContext 而 implement ApplicationContextAware
   注意:它不仅仅回调 ApplicationContextAware,
   还会负责回调 EnvironmentAware、ResourceLoaderAware 等,看下源码就清楚了

*/
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

//忽略依赖了这几个接口的bean
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
/*
为特殊的几个 bean 赋值
包括BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext
*/
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);

//在 bean 实例化后,如果是 ApplicationListener 的子类,
//那么将其添加到 listener 列表中,可以理解成:注册 事件监听器
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

//如果存在loadTimeWeaver这个Bean,则增加对应的后置处理器
if (beanFactory.containsBean("loadTimeWeaver")) {
    beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
    beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}

//添加默认的系统环境bean  (如果没有的话)
if (!beanFactory.containsLocalBean("environment")) {
    beanFactory.registerSingleton("environment", this.getEnvironment());
}

if (!beanFactory.containsLocalBean("systemProperties")) {
    beanFactory.registerSingleton("systemProperties", this.getEnvironment().getSystemProperties());
}

if (!beanFactory.containsLocalBean("systemEnvironment")) {
    beanFactory.registerSingleton("systemEnvironment", this.getEnvironment().getSystemEnvironment());
}

} ```

1.4 postProcessBeanFactory (后置处理器)

java //空方法 专门为子类提供用于扩展 ,此时所有的 Bean 都加载、注册完成了,但是都还没有初始化, //这一步可以修改 bean 定义或者增加自定义的 bean。 protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { }

此时所有的 Bean 都加载、注册完成了,但是都还没有初始化

1.5 invokeBeanFactoryPostProcessors (重要)

  • 该方法作用: 调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 方法
  • 如何扩展? : (可以实现 BeanDefinitionRegistryPostProcessor接口 和 BeanFactoryPostProcessor接口 来扩展)

```java protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { //开始执行beanFactoryPostProcessor对应实现类,需要知道的是beanFactoryPostProcessor是spring的扩展接口,在刷新容器之前,该接口可以用来修改bean元数据信息 PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, this.getBeanFactoryPostProcessors()); if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean("loadTimeWeaver")) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); }

} ```

紧接着我们看看 invokeBeanFactoryPostProcessors 做了什么

```java public static void invokeBeanFactoryPostProcessors( ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors) {

Set processedBeans = new HashSet<>();

//可以看到 这个方法是先处理 BeanDefinitionRegistryPostProcessor的实现, //然后再处理BeanFactoryPostProcessor的实现, //这也是为什么我们定义的扩展点 BeanDefinitionRegistryPostProcessorPoint先打印, //BeanFactoryPostProcessorPoint后打印的原因 if (beanFactory instanceof BeanDefinitionRegistry) { BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; List regularPostProcessors = new ArrayList<>(); List registryProcessors = new ArrayList<>(); //开始遍历三个内部类,如果属于BeanDefinitionRegistryPostProcessor子类,加入到bean注册的集合,否则加入到regularPostProcessors for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) { if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { BeanDefinitionRegistryPostProcessor registry

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值