Spring容器的创建刷新过程

以AnnotionConfigApplicationContext为例,在new一个AnnotionConfigApplicationContext的时候,其构造函数内就会调用父类的refresh方法

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
this();
register(annotatedClasses);
refresh();// <-- 调用AbstractApplicationContext的refresh方法
}

所以呢,Spring容器的创建过程主要在这个refresh方法里边。

public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 1、Prepare this context for refreshing.
prepareRefresh(); ///2、Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); ///3、Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory); try {
//4、 Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory); //5、 Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory); //6、 Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory); //7、 Initialize message source for this context.
initMessageSource(); //8、 Initialize event multicaster for this context.
initApplicationEventMulticaster(); //9、 Initialize other special beans in specific context subclasses.
onRefresh(); //10、 Check for listener beans and register them.
registerListeners(); //11、 Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory); //12、 Last step: publish corresponding event.
finishRefresh();
} catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + ex);
} // Destroy already created singletons to avoid dangling resources.
destroyBeans(); // Reset 'active' flag.
cancelRefresh(ex); // Propagate exception to caller.
throw ex;
} finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}

我给源码的每一步都加了序号(1~12),下面来详细看看每一步都做了些什么。

1、prepareRefresh() 刷新前准备
  1. 设置一些状态标记,如启动时间startupDate,closed/active状态

  2. initPropertySources() 设置init属性,此方法交给子类去实现

  3. getEnvironment().validateRequiredProperties()

    如果无Environment,则new StandardEnvironment()

    再调用validateRequiredProperties() 校验参数

  4. earlyApplicationEvents= new LinkedHashSet();保存容器中的一些早期的事件

2、obtainFreshBeanFactory() 获取BeanFactory
  1. refreshBeanFactory() 刷新BeanFactory

    GenericApplicationContext的构造方法中new了一个DefaultListableBeanFactory

    通过this.beanFactory.setSerializationId(getId());设置一个唯一的id

  2. getBeanFactory() 返回刚才GenericApplicationContext创建的BeanFactory对象

3、prepareBeanFactory(beanFactory) BeanFactory的准备工作
  1. 设置BeanFactory的类加载器、表达式解析器【StandardBeanExpressionResolver】、ResourceEditorRegistrar

  2. 添加BeanPostProcessor【ApplicationContextAwareProcessor】

  3. 设置不需要自动装配的接口

    包括【EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware】

  4. 注册可以解析的自动装配的接口

    包括【BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext】

  5. 添加BeanPostProcessor【ApplicationListenerDetector】

  6. 添加AspectJ【类加载时织入LoadTimeWeaver】

  7. 给BeanFactory中注册一些能用的组件

    1. environment【ConfigurableEnvironment】

    2. systemProperties【Map<String, Object>】

    3. systemEnvironment【Map<String, Object>】

4、postProcessBeanFactory(beanFactory) BeanFactory后置处理

子类通过重写这个方法来在BeanFactory创建并预准备完成以后做进一步的设置

到这里,BeanFactory的创建及后置处理工作就结束了

5、invokeBeanFactoryPostProcessors(beanFactory) 执行BeanFactory后置方法

BeanFactoryPostProcessors是BeanFactory的后置处理器,在BeanFactory标准初始化之后、全部bean信息都被加载,但是还没有被实例化的时候执行。

invokeBeanFactoryPostProcessors方法中,主要处理2种类型的接口:

BeanDefinitionRegistryPostProcessor 和 BeanFactoryPostProcessor

■先执行BeanDefinitionRegistryPostProcessor的方法,过程如下:

  1. 获取所有实现了BeanDefinitionRegistryPostProcessor接口的class

    beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false)
  2. 先执行实现了PriorityOrdered优先级接口的BeanDefinitionRegistryPostProcessor

    postProcessor.postProcessBeanDefinitionRegistry(registry)
  3. 同理,再执行实现了Order顺序接口的BeanDefinitionRegistryPostProcessor;最后执行其他实现了BeanDefinitionRegistryPostProcessor的

Configuration类中通过@Import(ImportBeanDefinitionRegistrar)引入的类就是在这里被调用registerBeanDefinitions方法的…【processor:ConfigurationClassPostProcessor】

public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry)

■再执行BeanFactoryPostProcessor的方法,过程如下:

  1. 获取所有实现了BeanFactoryPostProcessor接口的class

    beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false)
  2. 先执行实现了PriorityOrdered优先级接口的BeanFactoryPostProcessor

    postProcessor.postProcessBeanFactory(beanFactory)
  3. 同理,再执行实现了Order顺序接口的BeanFactoryPostProcessor;最后执行其他实现了BeanDefinitionRegistryPostProcessor的

6、registerBeanPostProcessors(beanFactory) 注册bean的后置处理器
  1. 获取所有实现了BeanPostProcessor接口的class

    beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
  2. 把获取的类按照 是否实现了 PriorityOrdered、Ordered接口、及其他 分成3类

  3. 按照优先级依次调用

    beanFactory.addBeanPostProcessor(postProcessor);
  4. 最后注册一个ApplicationListenerDetector

    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));

这个Detector的作用是:

在Bean创建完成后检查是否是ApplicationListener,如果是则加到context中applicationContext.addApplicationListener((ApplicationListener<?>) bean)

7、initMessageSource() 初始化MessageSource组件

MessageSource组件主要用来实现国际化、消息解析处理。

在initMessageSource中,首先看容器中是否有id为messageSource的,类型是MessageSource的组件。如果没有则new DelegatingMessageSource() 放进去。

后面在处理国际化时,可以注入MessageSource对象,然后使用如下代码进行国际化

String getMessage(String code, Object[] args, Locale locale)
8、initApplicationEventMulticaster() 初始化事件多波器

在此方法中,首选从BeanFactory中获取id为“applicationEventMulticaster”的ApplicationEventMulticaster。如果没有就new SimpleApplicationEventMulticaster(beanFactory)放进去。[多波器,有的也叫派发器]

9、onRefresh() 留给子类重写
10、registerListeners() 注册事件监听器
  1. 从容器中拿到所有的ApplicationListener

  2. 将每个监听器添加到事件多波器中

    getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName)
  3. 处理前面步骤留下的earlyApplicationEvents,earlyApplicationEvents在步骤1.4中初始化为空的LinkedHashSet

    getApplicationEventMulticaster().multicastEvent(earlyEvent)
11、finishBeanFactoryInitialization(beanFactory) 初始化所有剩下的单实例bean

核心逻辑在beanFactory.preInstantiateSingletons()方法中。这里面做的事情主要有:

  1. 循环编译所有的beanNames,获取RootBeanDefinition

  2. 如果bean 不是抽象的,是单实例的,是懒加载

  3. 判断是否 是实现FactoryBean接口的Bean

    如果是,先做一些处理,再调getBean

    如果不是,则直接调用getBean(beanName)

  4. getBean(beanName) –> doGetBean(name, null, null, false)

    1. 先获取缓存中保存的单实例Bean【singletonObjects.get(beanName)】。如果能获取到说明这个Bean之前被创建过(所有创建过的单实例Bean都会被缓存在ConcurrentHashMap<String, Object>(256)中)

    2. 如果缓存中获取不到,则开启下面的创建流程

    3. 先将bean标记为已创建 markBeanAsCreated(beanName)

    4. 获取Bean的定义信息RootBeanDefinition

    5. 获取当前Bean依赖的其他Bean[mbd.getDependsOn()],如果有则调用getBean()把依赖的Bean先创建出来

    6. 开启单实例Bean的创建流程 createBean(beanName, mbd, args)

      1. 准备重写的方法

      2. 尝试返回代理对象

        // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
        Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
      3. 执行InstantiationAwareBeanPostProcessor

        先触发:postProcessBeforeInstantiation();

        如果BeforeInstantiation有返回值,再接着执行postProcessAfterInitialization();

        如果resolveBeforeInstantiation返回的不为null,则bean就创建好了

      4. 前面resolveBeforeInstantiation返回的不为null,则返回该bean;为null接着调Object beanInstance = doCreateBean(beanName, mbdToUse, args);创建Bean【step5】

  5. 创建doCreateBean(beanName, mbdToUse, args)

    1. 创建instanceWrapper = createBeanInstance(beanName, mbd, args)

      利用工厂方法 或 对象的构造器 创建出Bean实例

    2. 调用MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition(mbd, beanType, beanName);

    3. 给bean属性赋值 populateBean(beanName, mbd, instanceWrapper)

      1. 赋值前,拿到所有的InstantiationAwareBeanPostProcessor后置处理器,调用postProcessAfterInstantiation()

      2. 再拿到所有的InstantiationAwareBeanPostProcessor后置处理器,调用postProcessPropertyValues()

      3. 赋值 applyPropertyValues(beanName, mbd, bw, pvs);

        为属性利用setter方法等进行赋值

  6. 初始化bean,调用initializeBean(beanName, exposedObject, mbd)

    1. 执行xxxAware方法 invokeAwareMethods(beanName, bean),包括【BeanNameAware\BeanClassLoaderAware\BeanFactoryAware】

    2. 执行Bean后置处理器的before方法 applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName) 循环调用 beanProcessor.postProcessBeforeInitialization(result, beanName)

    3. 执行bean的初始化方法 invokeInitMethods(beanName, wrappedBean, mbd);

    4. 执行bean的后置处理器的after方法 applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName) 循环调用 beanProcessor.postProcessAfterInitialization(result, beanName)

      Spring的AOP注解实现原理:

      @EnableAspectJAutoProxy引入了继承自AbstractAutoProxyCreator的AnnotationAwareAspectJAutoProxyCreator

      在AbstractAutoProxyCreator中实现了postProcessAfterInitialization方法,在方法内调用wrapIfNecessary(bean, beanName, cacheKey)方法创建代理对象返回出去,后续放入容器的就是这个代理对象

    5. 注册bean的销毁方法 registerDisposableBeanIfNecessary(beanName, bean, mbd);

  7. 将bean加入到singletonObjects中

  8. 所有bean创建完之后,判断bean是否是SmartInitializingSingleton的实例。如果是,就执行afterSingletonsInstantiated()

12、finishRefresh() 容器创建完成
  1. initLifecycleProcessor() 初始化和生命周期有关的后置处理器

    默认从容器中找是否有lifecycleProcessor的组件【LifecycleProcessor】;如果没有new DefaultLifecycleProcessor();加入到容器;

  2. 执行onfresh方法

    getLifecycleProcessor().onRefresh()
  3. 发布容器刷新完成事件

    publishEvent(new ContextRefreshedEvent(this))
  4. 调用LiveBeansView.registerApplicationContext(this)

Spring容器的创建刷新过程的更多相关文章

  1. spring源码学习之:spring容器的applicationContext启动过程

    Spring 容器像一台构造精妙的机器,我们通过配置文件向机器传达控制信息,机器就能够按照设定的模式进行工作.如果我们将Spring容器比喻为一辆汽车,可以将 BeanFactory看成汽车的发动机, ...

  2. Spring - Spring容器概念及其初始化过程

    引言 工作4年多,做了3年的java,每个项目都用Spring,但对Spring一直都是知其然而不知其所以然.鄙人深知Spring是一个高深的框架,正好近期脱离加班的苦逼状态,遂决定从Spring的官 ...

  3. Spring容器的创建原理

    1.new ioc容器(AnnotationConfigApplicationContext 注解ioc) 2.refresh()方法调用 2.1 prepareRefresh()刷新前的预处理 a: ...

  4. 【Spring】简述@Configuration配置类注册BeanDefinition到Spring容器的过程

    概述 本文以SpringBoot应用为基础,尝试分析基于注解@Configuration的配置类是如何向Spring容器注册BeanDefinition的过程 其中主要分析了 Configuratio ...

  5. Spring学习笔记之 Spring IOC容器(一)之 实例化容器,创建JavaBean对象,控制Bean实例化,setter方式注入,依赖属性的注入,自动装配功能实现自动属性注入

    本节主要内容:       1.实例化Spring容器示例    2.利用Spring容器创建JavaBean对象    3.如何控制Bean实例化    4.利用Spring实现bean属性sett ...

  6. Spring 容器

    Spring提供了两个核心接口:BeanFactory和ApplicationContext,其中applicationContext是BeanFactory的子接口. 他们都可代表Spring容器, ...

  7. Spring 读书笔记-----使用Spring容器(一)

    pring有两个核心接口:BeanFactory和ApplicationContext,其中ApplicationContext是BeanFactory的子接口.他们都可代表Spring容器,Spri ...

  8. (转)Spring 读书笔记-----使用Spring容器(一)

    Spring有两个核心接口:BeanFactory和ApplicationContext,其中ApplicationContext是BeanFactory的子接口.他们都可代表Spring容器,Spr ...

  9. Spring容器

    1.Spring简介: a)Spring春天 b)官网:https://spring.io c)设计理念:轮子理念,不要重复创造轮子: d)Spring可以被理解为一个容器,用于管理其他的框架: e) ...

随机推荐

  1. 基于UML的毕业选题系统建模研究

    一.基本信息 标题:基于UML的毕业选题系统建模研究 时间:2018 出版源:电脑迷 领域分类:UML建模技术 二.研究背景 问题定义:为了加强学生设计分析开发软件的相关能力,有效避免结构化模型存在的 ...

  2. EF6学习笔记(四) 弹性连接及命令拦截调试

    EF6学习笔记总目录:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 本章原文地址:Connection Resiliency and Command Interception 原文 ...

  3. MySQL与SQL语句的操作

    MySQL与SQL语句的操作 Mysql比较轻量化,企业用的是Oracle,基本的是熟悉对数据库,数据表,字段,记录的更新与修改 1. mysql基本信息 特殊数据库:information_sche ...

  4. 循环队列 & 栈的共用空间

    循环队列 非常好的数据结构,充分利用率空间,可以用于网络端存储socket消息! /*************************************** 作者: 未闻花语 版本: v1.0 ...

  5. java基础-三元运算符

    1.三元运算符的格式 /* 三元运算符 (条件表达式)?表达式1:表达式2; 如果条件为true,整个表达式结果是表达式1: 如果条件为false,整个表达式结果是表达式2: 注意:三元运算符不能单独 ...

  6. .net core mvc发布项目到IIS上出现500错误

    如题,我把.net core mvc项目以应用程序方式挂到IIS默认网站下,结果出现了如下错误:HTTP Error 500.0 - ANCM In-Process Handler Load Fail ...

  7. C语言小程序——推箱子(窄字符和宽字符)

    C语言小程序——推箱子(窄字符Version) 推箱子.c #include <stdio.h> #include <conio.h> #include <stdlib. ...

  8. Flask中的before_request after_request

    1.@app.before_request 在请求(request)之前做出响应 @app.before_request 也是一个装饰器,他所装饰的函数,都会在请求进入视图函数之前执行 2.@app. ...

  9. u-boot中debug的一些总结

    研究u-boot,首要搞清楚的是代码的流程,运行流程是什么样子的呢?不知道,就看log.这就要把log信息 打开.研究u-boot的文件,发现里面是很多DEBUG宏定义的打印,这个打印着怎么打开呢? ...

  10. Ubuntu 16.04 python和OpenCV安装

    Ubuntu 16.04 python和OpenCV安装:最进在做深度学习和计算机视觉的有关内容,因此要在python中用到opencv.我的电脑装的是Ubuntu 16.04,python 2.7和 ...