IOC容器启动过程

创建Maven工程用于调试,引入spring-context依赖
在这里插入图片描述
引入配置类,创建一个bean
在这里插入图片描述
定义测试类,new AnnotationConfigApplicationContext(SpringConfig.class)这一句测试代码就可以驱动IoC启动
在这里插入图片描述
仿真进入构造方法

1.调用构造方法

在这里插入图片描述

2.进入this

this()执行之前会先执行父类的构造方法,完成工厂创建
在这里插入图片描述
此时beanFactory已经创建
在这里插入图片描述

1.AnnotatedBeanDefinitionReader

在这里插入图片描述

其逻辑很简单,就是向IoC中注册1个BeanFactoryPostProcessor和4个BeanPostProcessor,Spring就是通过这些PostProcessor扩展点实现对各种注解的解析、处理,让开发只需要简单的几个注解就可以实现很多复杂功能,屏蔽了注解背后处理的复杂逻辑,这也是目前Spring开发趋势:注解驱动开发。
这几个PostProcessor大致作用:

ConfigurationClassPostProcessor:完成@Configuration、@Import、@ComponentScan、@Component、@Bean等注解支持,该类主要完成完成BeanDefinition的采集工作,就是解析各种注解,把需要纳入Spring管理的Bean都采集到一起生成BeanDefinition存储起来,供后续生成对象提供所需的材料;

AutowiredAnnotationBeanPostProcessor:完成@Autowired、@Value注解支持,实现Spring中依赖注入的核心逻辑;

CommonAnnotationBeanPostProcessor:支持JSR-250的一些注解,如:@Resource、@PostConstruct、@PreDestroy等;

EventListenerMethodProcessor和DefaultEventListenerFactory:这两个类主要完成对Spring4.2之后引入的@EventListener等事件注解支持;

上面5个PostProcessor中,最重要的是前两个,一个负责完成从各个地方把需要纳入IoC管理的Bean都收集到一起;另一个则完成对这些收集的Bean进行依赖注入。Spring IoC基本工作就是管理Bean以及依赖注入,所以IoC启动流程分析中,这两个类占有很大的比重。

2.ClassPathBeanDefinitionScanner

Spring项目中配置<context:component-scan base-package=“com.example.demo”/>或@ComponentScan(basePackages=“a.b.c”),这背后的工作就是靠ClassPathBeanDefinitionScanner完成,其主要就是完成对指定包路径下的Bean进行扫描,把含有特定注解的Bean生成BeanDefinition注册到IoC容器中。
ClassPathBeanDefinitionScanner是Spring中非常重要的一个类,决定了哪些类需要被纳入IoC容器。我们可以继承ClassPathBeanDefinitionScanner实现框架定制化功能,比如MyBatis 的Mapper扫描就是一个典型应用案例,MyBatis 的MapperScannerConfigurer的内部就使用到一个ClassPathBeanDefinitionScanner的子类,实现将Mapper接口文件注入到IoC容器中。
案例:
在这里插入图片描述

注意:AnnotationConfigApplicationContext中定义的:this.scanner = new ClassPathBeanDefinitionScanner(this);,这个其实一般情况下是没有使用的,只有手工调用AnnotationConfigApplicationContext#scan()才会使用到scanner。大部分Bean的采集工作是AnnotatedBeanDefinitionReader中向IoC注册的ConfigurationClassPostProcessor这个BeanFactory后置处理器完成的,它在处理@ComponentScan注解时会重新创建一个ClassPathBeanDefinitionScanner实例,而不是使用AnnotationConfigApplicationContext.scanner这个,这里要特别注意下,避免修改却发现没有起作用的尴尬。

3.构造方法第二个方法:register(componentClasses)

就是将传入的配置类解析成解析成BeanDefinition,注册到IoC容器中,后续ConfigurationClassPostProcessor这个BeanFactory后置处理器在IoC开始真正初始化时,可以获取到这些配置类的BeanDefinition集合,启动解析。
配置类已经加到Map
在这里插入图片描述

4.构造方法第三个方法:refresh

refresh方法定义在AbstractApplicationContext,负责初始化 ApplicationContext 容器,容器必须调用 refresh 才能正常工作,采用模板模式,定义好IoC启动的流程以及每个步骤的作用,并提供基础实现,其它子类可以重写进行扩展。

1. prepareRefresh();

  • 这一步创建和准备了 Environment 对象,它作为 ApplicationContext 的一个成员变量
  • Environment 对象的作用之一是为后续 @Value,值注入时提供键值
  • Environment 分成三个主要部分
  • systemProperties - 保存 java 环境键值
  • systemEnvironment - 保存系统环境键值
  • 自定义 PropertySource - 保存自定义键值,例如来自于 *.properties 文件的键值
    *在这里插入图片描述

2.ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

这一步获取(或创建) BeanFactory,它也是作为 ApplicationContext 的一个成员变量

  • BeanFactory 的作用是负责 bean 的创建、依赖注入和初始化,bean 的各项特征由 BeanDefinition 定义
  • BeanDefinition 作为 bean 的设计蓝图,规定了 bean 的特征,如单例多例、依赖关系、初始销毁方法等
  • BeanDefinition 的来源有多种多样,可以是通过 xml 获得、配置类获得、组件扫描获得,也可以是编程添加
  • 所有的 BeanDefinition 会存入 BeanFactory 中的 beanDefinitionMap 集合
    在这里插入图片描述

两个方法,
在这里插入图片描述
refresh中设置了序列化id
在这里插入图片描述
getBeanFactory会调用父类一开始创建的beanFactory(进入this时创建的)
在这里插入图片描述

3.prepareBeanFactory(beanFactory);

  • 这一步会进一步完善 BeanFactory,为它的各项成员变量赋值
  • beanExpressionResolver 用来解析 SpEL,常见实现为 StandardBeanExpressionResolver
  • propertyEditorRegistrars 会注册类型转换器
  • 它在这里使用了 ResourceEditorRegistrar 实现类
  • 并应用 ApplicationContext 提供的 Environment 完成 ${ } 解析
  • registerResolvableDependency 来注册 beanFactory 以及 ApplicationContext,让它们也能用于依赖注入
  • beanPostProcessors 是 bean 后处理器集合,会工作在 bean 的生命周期各个阶段,此处会添加两个:
  • ApplicationContextAwareProcessor 用来解析 Aware 接口
  • ApplicationListenerDetector 用来识别容器中 ApplicationListener 类型的 bean

在这里插入图片描述
在这里插入图片描述

4.postProcessBeanFactory(beanFactory);

  • 默认空实现,留给子类扩展使用,可以修改beanDefinition信息
  • 可以参照:AbstractRefreshableWebApplicationContext#postProcessBeanFactory()
  • 一般 Web 环境的 ApplicationContext 都要利用它注册新的 Scope,完善 Web 下的 BeanFactory
  • 这里体现的是模板方法设计模式

5.invokeBeanFactoryPostProcessors(beanFactory);

调用BeanFactory后置处理器(包括BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor)
前面巴拉巴拉一大堆,基本还是各种配置、填充工作,这一步就到了IoC容器开始真正干活的阶段了。invokeBeanFactoryPostProcessors(beanFactory)方法主要就是完成对所有注册进来的BeanFactory后置处理器执行调用,包括BeanFactoryPostProcessor及其子类BeanDefinitionRegistryPostProcessor。这里就会有个前面提到的Spring中非常重要的一个类:ConfigurationClassPostProcessor开始被执行,它执行完成后,所有需要Spring管理的Bean都会被解析成BeanDefinition注册进来。@Configuration、@Bean、@Import、@ComponentScan、@Component等等相关配置注解会被处理,相关的Bean也被解析成BeanDefinition注册进来。

  • 这一步会调用 beanFactory 后处理器
  • beanFactory 后处理器,充当 beanFactory 的扩展点,可以用来补充或修改 BeanDefinition
  • 常见的 beanFactory 后处理器有
  • ConfigurationClassPostProcessor – 解析 @Configuration、@Bean、@Import、@PropertySource 等
  • PropertySourcesPlaceHolderConfigurer – 替换 BeanDefinition 中的 ${ }
  • MapperScannerConfigurer – 补充 Mapper 接口对应的 BeanDefinition
    在这里插入图片描述
    经过这个步骤,dog类也被加到了beanDefinitionMap中
    在这里插入图片描述

6.registerBeanPostProcessors(beanFactory);

registerBeanPostProcessors方法主要是将BeanDefinition对应的BeanPostProcessor实例化并通过beanFactory.addBeanPostProcessor()方法注册进来

  • 这一步是继续从 beanFactory 中找出 bean 后处理器,添加至 beanPostProcessors 集合中
  • bean 后处理器,充当 bean 的扩展点,可以工作在 bean 的实例化、依赖注入、初始化阶段,常见的有:
  • AutowiredAnnotationBeanPostProcessor 功能有:解析 @Autowired,@Value 注解
  • CommonAnnotationBeanPostProcessor 功能有:解析 @Resource,@PostConstruct,@PreDestroy
    在这里插入图片描述
    在这里插入图片描述
    增加了3个
    在这里插入图片描述

7.initMessageSource();

这一步是为 ApplicationContext 添加 messageSource 成员,实现国际化功能

  • 去 beanFactory 内找名为 messageSource 的 bean,如果没有,则提供空的 MessageSource 实现
    在这里插入图片描述

8.initApplicationEventMulticaster();

  • 这一步为 ApplicationContext 添加事件广播器成员,即 applicationContextEventMulticaster
  • 它的作用是发布事件给监听器
  • 去 beanFactory 找名为 applicationEventMulticaster 的 bean 作为事件广播器,若没有,会创建默认的事件广播器
  • 之后就可以调用 ApplicationContext.publishEvent(事件对象) 来发布事件
    在这里插入图片描述

9.onRefresh();

  • 这一步是空实现,留给子类扩展
  • SpringBoot 中的子类在这里准备了 WebServer,即内嵌 web 容器
  • 体现的是模板方法设计模式

10. registerListeners();

  • 这一步会从多种途径找到事件监听器,并添加至 applicationEventMulticaster
  • 事件监听器顾名思义,用来接收事件广播器发布的事件,有如下来源
  • 事先编程添加的
  • 来自容器中的 bean
  • 来自于 @EventListener 的解析
  • 要实现事件监听器,只需要实现 ApplicationListener 接口,重写其中 onApplicationEvent(E e) 方法即可
    在这里插入图片描述

11.finishBeanFactoryInitialization(beanFactory);

在执行finishBeanFactoryInitialization(beanFactory); 方法前,所有的配置类都已经变成了 beanDefinition 保存 beanFactory 的 beanDefinitionMap 中。现在执行 finishBeanFactoryInitialization(beanFactory)方法是为了让 所有的 beanDefinition 变成 bean。

大体的流程是:遍历 beanDefinitionMap 中的每一个 beanDefinition,从里面拿出 className,以 className 为依据,去 beanFactory 的 singletonObject 属性中去拿对应名字的 bean。如果能拿到,那就表示该 beanDefinition 已经变成 bean了,否则就用 beanDefinition 创建新 bean 并保存到 singletonObject 中。

  • 这一步会将 beanFactory 的成员补充完毕,并初始化所有非延迟单例 bean
  • conversionService 也是一套转换机制,作为对 PropertyEditor 的补充
  • embeddedValueResolvers 即内嵌值解析器,用来解析 @Value 中的 ${ },借用的是 Environment 的功能
  • singletonObjects 即单例池,缓存所有单例对象
  • 对象的创建都分三个阶段,每一阶段都有不同的 bean 后处理器参与进来,扩展功能
    在这里插入图片描述

关键方法:preInstantiateSingletons

在这里插入图片描述
preInstantiateSingletons方法内部:

1.获取到所有BeanDefinition名称,后面用于遍历处理

在这里插入图片描述

2.遍历每个bean,触发实例化

在这里插入图片描述

3.执行getBean doGetBean

在这里插入图片描述

在这里插入图片描述

4.执行CreateBean

在这里插入图片描述

5.执行docreateBean

在这里插入图片描述

1.调用无参构造方法通过反射创建对象

在这里插入图片描述

2.获取构造器

在这里插入图片描述

3.populateBean方法

populateBean方法完成依赖注入任务,主要包括三种方式的依赖注入:自动注入、注解注入和PropertyValues注入。
在这里插入图片描述
回调InstantiationAwareBeanPostProcessor#postProcessProperties方法
AutowiredAnnotationBeanPostProcessor,就是在这个方法中完成@Autowired、@Value注解的依赖注入
CommonAnnotationBeanPostProcessor:支持JSR-250的一些注解,如:@Resource、@PostConstruct、@PreDestroy等
在这里插入图片描述
注解方式实现的依赖注入主要借助于MergedBeanDefinitionPostProcessor和InstantiationAwareBeanPostProcessor这两类扩展类实现。比如@Autowired、@Value依赖注入的实现类是AutowiredAnnotationBeanPostProcessor,以及@Resource等JSR-250相关依赖注入的实实现类是CommonAnnotationBeanPostProcessor,他们都实现了MergedBeanDefinitionPostProcessor和InstantiationAwareBeanPostProcessor这两个接口。一般是在MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition方法中完成注解信息解析,然后缓存到Map等集合中,在InstantiationAwareBeanPostProcessor#postProcessProperties回调方法中,从缓存中查找依赖注入信息,然后进行依赖注入。
最后完成PropertyValues的依赖注入
在这里插入图片描述

4.initMethod方法

在这里插入图片描述
initializeBean()这个方法主要完成Bean的初始化工作,以及在初始化前后都存在BeanPostProcessor扩展点进行方法回调。

在这里插入图片描述

  • @PostConstruct这种比较常用的注解方式,是在InitDestroyAnnotationBeanPostProcessor#postProcessBeforeInitialization方法中被调用的,所以它执行时机是最早的;

  • 实现InitializingBean这种方式次之,具体见invokeInitMethods方法;

  • 最后执行的是@Bean(initMethod = “xxx”)这种方式配置的initMethod; //完成刷新并发布内容
    池中增加了这两个自定义的bean
    在这里插入图片描述

12.finishRefresh();

  • 这一步会为 ApplicationContext 添加 lifecycleProcessor 成员,用来控制容器内需要生命周期管理的 bean
  • 如果容器中有名称为 lifecycleProcessor 的 bean 就用它,否则创建默认的生命周期管理器
  • 准备好生命周期管理器,就可以实现
  • 调用 context 的 start,即可触发所有实现 LifeCycle 接口 bean 的 start
  • 调用 context 的 stop,即可触发所有实现 LifeCycle 接口 bean 的 stop
  • 发布 ContextRefreshed 事件,整个 refresh 执行完成

在这里插入图片描述
参考链接:https://baijiahao.baidu.com/s?id=1724327365978008424&wfr=spider&for=pc
https://www.bilibili.com/read/cv5637654?spm_id_from=333.999.0.0

猜你喜欢

转载自blog.csdn.net/weixin_46666822/article/details/124428779