一、前言知识
- Spring会将所有交由Spring管理的类,扫描其class文件,将其解析成BeanDefinition,在BeanDefinition中会描述类的信息,例如:这个类是否是单例的,Bean的类型,是否是懒加载,依赖哪些类,自动装配的模型。Spring创建对象时,就是根据BeanDefinition中的信息来创建Bean。
- Spring容器在本文可以简单理解为DefaultListableBeanFactory,它是BeanFactory的实现类,这个类有几个非常重要的属性:
beanDefinitionMap是一个map,用来存放bean所对应的BeanDefinition;
beanDefinitionNames是一个List集合,用来存放所有bean的name;
singletonObjects是一个Map,用来存放所有创建好的单例Bean。
- Spring中有很多后置处理器,但最终可以分为两种,一种是BeanFactoryPostProcessor,一种是BeanPostProcessor。前者的用途是用来干预BeanFactory的创建过程,后者是用来干预Bean的创建过程。后置处理器的作用十分重要,bean的创建以及AOP的实现全部依赖后置处理器。
二、源码解析
2.1 基于注解
流程概述
本文是基于 java-config 技术分析源码,所以这里的入口是AnnotationConfigApplicationContext ,如果是使用 xml 分析,那么入口即为 ClassPathXmlApplicationContext ,它们俩的共同特征便是都继承了 AbstractApplicationContext 类,而大名鼎鼎的 refresh()便是在这个类中定义的。我们接着分析 AnnotationConfigApplicationContext 类,入口如下:
整个Spring容器的启动流程可以绘制成如下流程图:
spring容器的初始化时,通过this()调用了无参构造函数,主要做了以下三个事情:
(1)实例化BeanFactory【DefaultListableBeanFactory】工厂,用于生成Bean对象。
(2)实例化BeanDefinitionReader注解配置读取器,用于对特定注解(如@Service、@Repository)的类进行读取转化成 BeanDefinition 对象,(BeanDefinition 是 Spring 中极其重要的一个概念,它存储了 bean 对象的所有特征信息,如是否单例,是否懒加载,factoryBeanName 等)
(3)实例化ClassPathBeanDefinitionScanner路径扫描器,用于对指定的包目录进行扫描查找 bean 对象。
完整流程
- this()调用
this()会调用AnnotationConfigApplicationContext无参构造方法,而在Java的继承中,会先调用父类的构造方法。所以会先调用AnnotationConfigApplicationContext的父类GeniricApplicationContext的构造方法,在父类中初始化beanFactory,即直接new了一个DefaultListableBeanFactory。
在this()中通过new AnnotatedBeanDefinitionReader(this)实例化了一个Bean读取器,并向容器中添加后置处理器。
- 向容器中添加了2个beanFactory后置处理器:ConfigurationClassPostProcessor 和EventListenerMethodProcessor。
- 向容器中添加了两个bean后置处理器:AutowiredAnnotationBeanPostProcessor 和CommonAnnotationBeanPostProcessor。
- 向容器中添加普通组件:DefaultEventListenerFactory。
通过new ClassPathBeanDefinitionScanner(this)实例化了一个可以对用户指定的包目录进行扫描查找 bean 对象的一个路径扫描器。
- register(annotatedClasses)将传入的配置类annotatedClasses解析成BeanDefinition(实际类型为AnnotatedGenericBeanDefinition),然后放入到BeanDefinitionMap中,这样后面在ConfigurationClassPostProcessor中能解析annotatedClasses,此时只是注册BeanDefinition信息,没有实例化。
- 执行refresh()方法refresh()方法是整个Spring容器的核心,在这个方法中进行了bean的实例化、初始化、自动装配、AOP等功能。
重点方法: AbstractApplicationContext.refresh( )
上文中我们知道了如何去初始化一个 IOC 容器,那么接下来就是让这个 IOC 容器真正起作用的时候了:即先扫描出要放入容器的 bean,将其包装成 BeanDefinition 对象,然后通过反射创建 bean,并完成赋值操作,这个就是 IOC 容器最简单的功能了。但是看上图,明显 Spring 的初始化过程比这个多的多,下面我们就详细分析一下这样设计的意义:
如果用户想在扫描完 bean 之后做一些自定义的操作:假设容器中包含了 a 和 b,那么就动态向容器中注入 c,不满足就注入 d,这种操作 Spring 也是支持的,可以使用它提供的 BeanFactoryPostProcessor 后置处理器,对应的是上图中的invokeBeanFactoryPostProcessors 操作。
如果用户还想在 bean 的初始化前后做一些操作呢?比如生成代理对象,修改对象属性等,Spring 为我们提供了 BeanPostProcessor 后置处理器,实际上 Spring 容器中的大多数功能都是通过 Bean 后置处理器完成的,Spring 也是给我们提供了添加入口,对应的是上图中的registerBeanPostProcessors 操作。
容器创建过程中,如果用户想监听容器启动、刷新等事件,根据这些事件做一些自定义的操作?Spring 也早已为我们考虑到了,提供了添加监听器接口和容器事件通知接口,对应的是上图中的 registerListeners 操作。
refresh()主要用于容器的刷新,Spring 中的每一个容器都会调用 refresh() 方法进行刷新,无论是 Spring 的父子容器,还是 Spring Cloud Feign 中的 feign 隔离容器,每一个容器都会调用这个方法完成初始化。refresh()可划分为上述的12个步骤,其中比较重要的步骤下面会有详细说明。
先总结一下refresh()方法每一步主要的功能:
- prepareRefresh()刷新前的预处理:
- initPropertySources():初始化一些属性设置,子类自定义个性化的属性设置方法;
- getEnvironment().validateRequiredProperties():检验属性的合法性
- earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>():保存容器中的一些早期的事件;
- obtainFreshBeanFactory():获取在容器初始化时创建的BeanFactory:
- refreshBeanFactory():刷新BeanFactory,设置序列化ID;
- getBeanFactory():返回初始化中的GenericApplicationContext创建的BeanFactory对象,即【DefaultListableBeanFactory】类型
- prepareBeanFactory(beanFactory):BeanFactory的预处理工作,向容器中添加一些组件:
- 设置BeanFactory的类加载器、设置表达式解析器等等
- 添加BeanPostProcessor【ApplicationContextAwareProcessor】
- 设置忽略自动装配的接口:EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware;
- 注册可以解析的自动装配类,即可以在任意组件中通过注解自动注入:BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext
- 添加BeanPostProcessor【ApplicationListenerDetector】
- 添加编译时的AspectJ;
- 给BeanFactory中注册的3个组件:environment【ConfigurableEnvironment】、systemProperties【Map<String, Object>】、systemEnvironment【Map<String, Object>】
- postProcessBeanFactory(beanFactory):子类重写该方法,可以实现在BeanFactory创建并预处理完成以后做进一步的设置。
- invokeBeanFactoryPostProcessors(beanFactory):在BeanFactory标准初始化之后执行BeanFactoryPostProcessor的方法,即BeanFactory的后置处理器:
- 先执行BeanDefinitionRegistryPostProcessor: postProcessor.postProcessBeanDefinitionRegistry(registry)
- 获取所有的实现了BeanDefinitionRegistryPostProcessor接口类型的集合
- 先执行实现了PriorityOrdered优先级接口的BeanDefinitionRegistryPostProcessor
- 再执行实现了Ordered顺序接口的BeanDefinitionRegistryPostProcessor
- 最后执行没有实现任何优先级或者是顺序接口的BeanDefinitionRegistryPostProcessors
- 再执行BeanFactoryPostProcessor的方法:postProcessor.postProcessBeanFactory(beanFactory)
- 获取所有的实现了BeanFactoryPostProcessor接口类型的集合
- 先执行实现了PriorityOrdered优先级接口的BeanFactoryPostProcessor
- 再执行实现了Ordered顺序接口的BeanFactoryPostProcessor
- 最后执行没有实现任何优先级或者是顺序接口的BeanFactoryPostProcessor
- registerBeanPostProcessors(beanFactory):向容器中注册Bean的后置处理器BeanPostProcessor,它的主要作用是干预Spring初始化bean的流程,从而完成代理、自动注入、循环依赖等功能
- 获取所有实现了BeanPostProcessor接口类型的集合:
- 先注册实现了PriorityOrdered优先级接口的BeanPostProcessor;
- 再注册实现了Ordered优先级接口的BeanPostProcessor;
- 最后注册没有实现任何优先级接口的BeanPostProcessor;
- 最终注册MergedBeanDefinitionPostProcessor类型的BeanPostProcessor:beanFactory.addBeanPostProcessor(postProcessor);
- 给容器注册一个ApplicationListenerDetector:用于在Bean创建完成后检查是否是ApplicationListener,如果是,就把Bean放到容器中保存起来:applicationContext.addApplicationListener((ApplicationListener<?>) bean);此时容器中默认有6个默认的BeanProcessor(无任何代理模式下)
- initMessageSource():初始化MessageSource组件,主要用于做国际化功能,消息绑定与消息解析:
- initApplicationEventMulticaster():初始化事件派发器,在注册监听器时会用到
- 看BeanFactory容器中是否存在自定义的ApplicationEventMulticaster:如果有,直接从容器中获取;如果没有,则创建一个SimpleApplicationEventMulticaster
- 将创建的ApplicationEventMulticaster添加到BeanFactory中,以后其他组件就可以直接自动注入。
- onRefresh():留给子容器、子类重写这个方法,在容器刷新的时候可以自定义逻辑。
- registerListeners():注册监听器:将容器中所有的ApplicationListener注册到事件派发器中,并派发之前步骤产生的事件:
- finishBeanFactoryInitialization(beanFactory):初始化所有剩下的单实例bean,核心方法是preInstantiateSingletons(),会调用getBean()方法创建对象;
- 获取容器中的所有beanDefinitionName,依次进行初始化和创建对象
- 获取Bean的定义信息RootBeanDefinition,它表示自己的BeanDefinition和可能存在父类的BeanDefinition合并后的对象
- 如果Bean满足这三个条件:非抽象的,单实例,非懒加载,则执行单例Bean创建流程:
- 所有Bean都利用getBean()创建完成以后,检查所有的Bean是否为SmartInitializingSingleton接口的,如果是;就执行afterSingletonsInstantiated();
- finishRefresh():发布BeanFactory容器刷新完成事件:
- nitLifecycleProcessor():初始化和生命周期有关的后置处理器:默认从容器中找是否有lifecycleProcessor的组件【LifecycleProcessor】,如果没有,则创建一个DefaultLifecycleProcessor()加入到容器;
- getLifecycleProcessor().onRefresh():拿到前面定义的生命周期处理器(LifecycleProcessor)回调onRefresh()方法
- publishEvent(new ContextRefreshedEvent(this)):发布容器刷新完成事件;
- liveBeansView.registerApplicationContext(this);
下面我们一起看一下上面标红的重点方法的源码
BeanFactory的预处理
org.springframework.context.support.AbstractApplicationContext#prepareBeanFactory
顾名思义,这个接口是为 beanFactory 工厂添加一些内置组件,预处理过程。
执行BeanFactory的后置处理器
org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors
Spring 在扫描完所有的 bean 转成 BeanDefinition 时候,我们是可以做一些自定义操作的,这得益于 Spring 为我们提供的 BeanFactoryPostProcessor 接口。
其中 BeanFactoryPostProcessor 又有一个子接口BeanDefinitionRegistryPostProcessor ,前者会把 ConfigurableListableBeanFactory 暴露给我们使用,后者会把 BeanDefinitionRegistry 注册器暴露给我们使用,一旦获取到注册器,我们就可以按需注入了,例如搞定这种需求:假设容器中包含了 a 和 b,那么就动态向容器中注入 c,不满足就注入 d。
同时 Spring 是允许我们控制同类型组件的顺序,比如在 AOP 中我们常用的 @Order 注解,这里的 BeanFactoryPostProcessor 接口当然也是提供了顺序,最先被执行的是实现了 PriorityOrdered 接口的实现类,然后再到实现了 Ordered 接口的实现类,最后就是剩下来的常规 BeanFactoryPostProcessor 类。
此时再看上图,是不是发现比较简单了,首先会回调postProcessBeanDefinitionRegistry() 方法,然后再回调 postProcessBeanFactory() 方法,最后注意顺序即可,下面一起看看具体的代码实现吧。
流程小结
注册Bean的后置处理器
org.springframework.context.support.PostProcessorRegistrationDelegate#registerBeanPostProcessors
这一步是向容器中注入 BeanPostProcessor 后置处理器,注意这里仅仅是向容器中注入而非使用。关于 BeanPostProcessor ,它的作用主要是会干预 Spring 初始化 bean 的流程,从而完成代理、自动注入、循环依赖等各种功能。
初始化事件派发器
org.springframework.context.support.AbstractApplicationContext#initApplicationEventMulticaster:
在整个容器创建过程中,Spring 会发布很多容器事件,如容器启动、刷新、关闭等,这个功能的实现得益于这里的ApplicationEventMulticaster 广播器组件,通过它来派发事件通知。
注册ApplicationListener监听器
org.springframework.context.support.AbstractApplicationContext#registerListeners:
这一步主要是将容器中所有的ApplicationListener注册到事件派发器中,并派发之前步骤产生的事件。
初始化所有的单例Bean
org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons:
在前面的步骤中,Spring 的大多数组件都已经初始化完毕了,剩下来的这个步骤就是初始化所有剩余的单实例 bean,Spring主要是通过preInstantiateSingletons()方法把容器中的 bean 都初始化完毕。这里我们就不细讲Bean的创建流程了。
发布BeanFactory容器刷新完成事件
org.springframework.context.support.AbstractApplicationContext#finishRefresh:整个容器初始化完毕之后,会在这里进行一些扫尾工作,如清理缓存,初始化生命周期处理器,发布容器刷新事件等。
总的来说:
IoC(Inverse of Control:控制反转)是一种设计思想,就是 将原本在程序中手动创建对象的控制权,交由Spring框架来管理。 IoC 在其他语言中也有应用,并非 Spirng 特有。
另一方面理解IOC就是容器, IOC 容器实际上就是个Map(key,value), Map 中存放的是各种对象,采用三级缓存的方式管理不通状态下的对象,从创建到销毁的整个bean的生命周期都是由容器来管理。
IOC容器创建过程大致是这样的:
- 实例化BeanFactory【DefaultListableBeanFactory】工厂,用于生成Bean对象。实例化BeanDefinitionReader bean定义信息读取器,加载解析bean对象,创建bean对象的定义信息BeanDefinition。
- prepareBeanFactory(beanFactory) BeanFactory的预处理,这个接口是为 beanFactory 工厂添加一些内置组件,预处理过程。
- 执行beanFactory的后置处理器,像PlaceholderConfigurerSupport