Spring基本原理之IoC
Contents
一、概述
IoC:控制反转(Inversion of Control)容器,是一种设计思想。在 Java 开发中,IoC 意味着将定义好的对象交给容器管理,而不是交给自己控制。
DI:依赖注入(Dependency Injection):组件之间的以来关系由容器在运行时期决定,即由容器动态的将某个依赖关系注入到组件之中。
二、Bean 的创建
2.1 IoC 容器的初始化
2.1.1 Spring IoC 的初始化主要有四个步骤:
- Bean 定义的定位,包括 xml 中,或者一个注解,或者文件其他形式。这些都被用Resource来定位,读取Resource获取BeanDefinition 注册到 Bean定义注册表中。
- 第一次向容器getBean操作会触发Bean的创建过程,实列化一个Bean时 ,根据BeanDefinition中类信息等实列化Bean.
- 将实列化的Bean放到单列Bean缓存内。
- 此后再次获取向容器getBean就会从缓存中获取。
2.1.2核心方法 refresh() :
|
|
1.prepareRefresh 准备刷新
- 设置启动时间,设计容器激活标志(active=true);
- 初始化 properties 资源,比如一些属性的占位符(@Value注解等);
- 验证必须存在的properties(validateRequiredProperties);
- 初始earlyApplicationEnvents.用于收集已经产生的ApplicationEnvents.
2.obtainFreshBeanFactory 获取容器
- 调用子类的refeshBeanFactory(), SpringBoot中采用默认的实现,设置BeanFactory的SerializationId,设置refreshed标志为true。
- 获取BeanFactory;
- XmlWebApplicationContext ,AnnotationConfigApplicationContext 会在这一步加载BeanDefinition
3.prepareBeanFactory 为了接下来使用BeanFactory 做准备
- 为内部的BeanFactory设置类加载器
- 设置表达式解析器,属性编辑器。
- 注册:BeanPostProcessor(ApplicationContextAwareProcessor,ApplicationListenerDetector)
- ApplicationContextAwareProcessor:对Spring 中各种Aware接口的支持,在初始化Bean前,调用Bean实现的Aware接口方法。
- ApplicationListenerDetector:用于收集实现了ApplicationListener接口的Bean
- 注册指定的依赖类型和对应的value
- 例如: beanFactory.registerResolvableDependency(ResourceLoader.class, this); 那么在类中自动注入ResourceLoader类型的对象,就会拿到当前IOC容器。
- 例如:这里的 ApplicationContext 也会拿到 IoC 容器。
- 注入一些其它信息的bean,比如environment、systemProperties等
4.postProcessBeanFactory 后处理BeanFactory
用于在BeanFactory
完成标准的初始化之后修改BeanFactory。不同容器根据自己的需求添加特殊的后置处理器;
EmbeddedWebApplicationContext
容器在这里添加了对 ServletContextAware
支持的 Bean 后置处理器(WebApplicationContextServletContextAwareProcessor
)。(而ClassPathXml和AnnotationConfig都没有后置处理器)
BeanFactoryPostProcessor是spring对外提供的接口,用来拓展spring,能够在spring容器加载了所有bean的信息之后、bean实例化之前执行,修改bean的定义属性。常用场景包括spring中占位符的处理、我们自定义的敏感信息的解密处理。
5.postProcessBeanFactory 后处理BeanFactory
实例化并且执行所有已经注册到BeanFactory中的 BeanFactoryPostProcessor。支持按照Order排序。
- 调用PostProcessorRegistrationDelegate的静态方法invokeBeanFactoryPostProcessors,执行顺序如下:
1.执行ApplicationContext初始化器注册的BeanDefinitionRegistryPostProcessor类型的处理器
2.执行实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor。
3.执行实现了Ordered的BeanDefinitionRegistryPostProcessor
4.执行所有后置处理器的 BeanFactoryPostProcessor 的接口方法
5.获取所有的BeanFactoryPostProcessor,排除已经执行过得后置处理器。
6.按照2-4的顺序 执行所有未执行的BeanFactoryPostProcessor。
- BeanFactoryPostProcessor 接口
针对BeanFactory 的处理,允许使用者修改容器中的bean definitions,例如:ServletComponentRegisteringPostProcessor提供对@WebFilter,@WebServlet,@WebListener注解的扫描,并注册到容器中。ConfigurationClassPostProcessor 对所有的@Configuration类进行动态代理的增强。注意使用时不能对任何BeanDefinition 进行实列化操作
- BeanDefinitionRegistryPostProcessor 接口
如图,继承自BeanFactoryPostProcessor,针对BeanDefinitionRegistry的后置处理器,会先于BeanFactoryPostProcessor 执行。
同时,ConfigurationClassPostProcessor后置处理器实现了 PriorityOrdered 与 BeanDefinitionRegistryPostProcessor接口,优先级最高的后置处理器,在SpringBoot自动配置的实现中起到举足轻重的作用。对@Configuration,@Bean,@ComponentScan,@Import,@ImportResource,@PropertySource注解解析。
6.registerBeanPostProcessors 注册bean后置处理器
委托给PostProcessorRegistrationDelegate的静态方法registerBeanPostProcessors执行
BeanPostProcessors 接口,该接口在Bean的实例化过程中被调用,在对一个对象进行初始化前后被调用。
实现了 EnvironmentAware,EmbeddedValueResolverAware,ResourceLoaderAware,ApplicationContextAware等Aware就是这个时候 被执行的。
MergedBeanDefinitionPostProcessor 接口,该接口继承了BeanPostProcessors接口, 会在 bean 实列化 之后 属性注入前 执行。例如 对@Autowired @Resource @Value 注解的解析。
7.initMessageSource 和 initApplicationEventMulticaster
在Spring容器中初始化一些国际化相关的属性;在容器中初始化Application事件广播器。
8.onRefresh
onRefresh是一个模板方法,留给子类容器扩赞,不同的容器做不同的事情。
例如:容器AnnotationConfigEmbeddedWebApplicationContext
中会调用createEmbeddedServletContainer
方法去创建内置的Servlet
容器。
EmbeddedServletContainerAutoConfiguration
类中定义了 Spring boot 支持的三种 Servlet容器。Tomcat, Jetty 和 Undertow。
9.registerListeners
将所有的 ApplicationListener 实现类注册 到 ApplicationEventMulticaster中,觉得是观察者模式。
10.finishBeanFactoryInitialization
实列化所有 非懒加载的 类。
11.finishRefresh
- 完成容器的初始化过程,发布相应事件。
- 发布 ContextRefreshedEvent事件。
- 发布容器启动事件。
2.2 Bean的注入方式
常用的注入方式:SET注入,构造器注入,静态工厂,实例工厂,注解方式
具体参考 Bean注入方式详解
三、Bean 生命周期以及创建过程
3.1 Bean 生命周期
如图,总的来说可以包括四个部分:实例化 ——–> 属性赋值 ——–> 初始化 ——–> 销毁。
3.2 Bean 实例化流程
对应源码:AbstactApplicationContext.finishBeanFactoryInitialization —-> DefaultListenableBeanFactory.preInstantiateSingletons —-> AbstractBeanFactory.doGetBean
- 遍历所有被加载到缓存中的 beanName,触发所有剩余的非懒加载单例 bean 的实例化。
- 首先通过 beanName 尝试从缓存中获取,如果存在则跳过实例化过程;否则,进行 bean 的实例化。
-
根据 BeanDefinition,BeanFactory 使用反射通过构造函数创建 bean 实例。
注意:此时的 BeanFactory 在容器的初始化阶段第 6 步注册了BeanPostProcessor,用在Bean 的初始化阶段
-
根据 BeanDefinition,进行 bean 实例属性填充。
-
执行 bean 实例的初始化。
5.1 触发 Aware 方法。
5.2 触发 BeanPostProcessor 的 postProcessBeforeInitialization 方法。
5.3 如果 bean 实现了 InitializingBean 接口,则触发 afterPropertiesSet() 方法。
5.4 如果 bean 设置了 init-method 属性,则触发 init-method 指定的方法。
5.5 触发 BeanPostProcessor 的 postProcessAfterInitialization 方法。
-
将创建好的 bean 实例放到缓存中,用于之后使用。
Author 拾光
LastMod 2022-06-14