在前面的文章中,我们已经对 Bean 的生命周期核心源码进行了较为详细的分析,但还有两个关键点尚未展开:一个是循环依赖,另一个是 AOP。循环依赖与依赖注入、构造方法注入关系密切,同时也与 AOP 存在关联。从本章开始,我们将逐步分析容器启动的完整过程,而 AOP 和循环依赖的相关内容会放在后续章节进行深入学习。
Bean 的生命周期涉及的内容较为丰富,此前我们已经花费了不少精力进行梳理。不妨先来回顾一下一个 Bean 在创建过程中的核心调用链路:
createBean --> 加载类 --> 实例化前 --> doCreateBean
--> 推断构造方法、构造方法注入、@Bean 的处理 --> 实例化 --> BeanDefinition 后置处理
--> 循环依赖处理(尚未分析)
--> 属性填充(实例化后、依赖注入:自动注入、@Autowired、@Value、@Resource)
--> Aware 回调 --> 初始化 Bean(初始化前、初始化、初始化后) --> 销毁 Bean在此之前,我们曾多次提到 refresh 方法,但只涉及其中部分环节。事实上,refresh 方法中还有很多前置步骤,这些步骤主要是为 Bean 的生命周期执行做各项准备和辅助工作。本章我们将重点分析:在容器启动过程中,refresh 方法究竟完成了哪些具体工作。
本文内容:
ApplicationContext创建过程源码解析
ApplicationContext启动过程源码解析
BeanFactory创建过程底层源码解析
BeanFactory预处理过程底层源码解析
requiredProperties的作用和底层源码解析
ApplicationContext重复刷新过程源码解析
Spring容器生命周期LifecycleProcessor底层原理解析
SmartLifecycle的作用和底层原理解析
Spring容器初始化MessageSource底层源码解析
Spring容器初始化事件发布器底层源码解析
启动过程
还是以最简单的入门代码开始:
public class Main {
public static void main(String[] args) {
// 容器启动过程中会做哪些事情?
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
UserService userService = (UserService) applicationContext.getBean("userService", new OrderService());
userService.test();
}
}
思考:容器启动过程中会做哪些事情?
至少有扫描和创建非懒加载的单例 Bean这个我们是知道的。
扫描与收集:BeanDefinition、BeanPostProcessor、TypeConvertor、Spel表达式、环境、事件。。。
解析配置类(@Component、@Bean、@Import) --> BeanDefinitionMap --> BeanFactory对象
下面以AnnotationConfigApplicationContext为例子,来介绍容器启动过程中的详细步骤。
在调用AnnotationConfigApplicationContext的构造方法之前,会调用父类GenericApplicationContext的无参构造方法,会构造一个BeanFactory,为DefaultListableBeanFactory。同时,再观察父类
AbstractAutowireCapableBeanFactory中会去忽略一些依赖接口和初始化instantiationStrategy,其中CglibSubclassingInstantiationStrategy是SimpleInstantiationStrategy的子类,同时具备JDK反射和cglib创建对象的能力。构造AnnotatedBeanDefinitionReader,构造过程中会做如下事情:
创建一个
Environment对象创建一个
ConditionEvaluator用来处理@Condition注解设置dependencyComparator:AnnotationAwareOrderComparator,它是一个Comparator,是用来进行排序的,会获取某个对象上的Order注解或者通过实现Ordered接口所定义的值进行排序
设置autowireCandidateResolver:ContextAnnotationAutowireCandidateResolver,用来解析某个Bean能不能进行自动注入,比如某个Bean的autowireCandidate属性是否等于true
向BeanFactory中添加ConfigurationClassPostProcessor对应的BeanDefinition,它是一个BeanDefinitionRegistryPostProcessor,并且实现了PriorityOrdered接口
向BeanFactory中添加AutowiredAnnotationBeanPostProcessor对应的BeanDefinition,它是一个InstantiationAwareBeanPostProcessorAdapter,MergedBeanDefinitionPostProcessor
向BeanFactory中添加CommonAnnotationBeanPostProcessor对应的BeanDefinition,它是一个InstantiationAwareBeanPostProcessor,InitDestroyAnnotationBeanPostProcessor
向BeanFactory中添加EventListenerMethodProcessor对应的BeanDefinition,它是一个BeanFactoryPostProcessor,SmartInitializingSingleton
向BeanFactory中添加DefaultEventListenerFactory对应的BeanDefinition,它是一个EventListenerFactory
构造ClassPathBeanDefinitionScanner,是让ApplicationContext拥有扫描的功能,但@ComponentScan注解使用的并不是这个对象,而是另外new的一个ClassPathBeanDefinitionScanner对象,功能一样,类一样,对象不同而已。
利用reader注册MyConfig为BeanDefinition,类型为AnnotatedGenericBeanDefinition
接下来就是调用refresh方法
EventListenerMethodProcessor和EventListenerFactory我们将在Spring事件监听机制进行学习。
refresh方法中的详细步骤:
prepareRefresh():
记录启动时间
可以允许子容器设置一些内容到Environment中,比如Tomcat容器、Servlet的配置
验证Environment中是否包括了必须要有的属性
obtainFreshBeanFactory():进行BeanFactory的refresh,在这里会去调用子类的refreshBeanFactory方法,具体子类是怎么刷新的得看子类,然后再调用子类的getBeanFactory方法,得到一个BeanFactory(这里主要有两个不同的实现,一个容器refresh方法不能重复执行,一个是可以重复执行,这个机制与后面的SpringMVC等Web环境有关联)
prepareBeanFactory(beanFactory):
设置beanFactory的类加载器
设置表达式解析器:StandardBeanExpressionResolver,用来解析Spring中的表达式
添加PropertyEditorRegistrar:ResourceEditorRegistrar,PropertyEditor类型转化器注册器,用来注册一些默认的PropertyEditor,比如FileEditor,是使用将String转成File对象的
添加一个Bean的后置处理器:ApplicationContextAwareProcessor,是一个BeanPostProcessor,用来执行EnvironmentAware、ApplicationEventPublisherAware等回调方法
添加ignoredDependencyInterface:可以向这个属性中添加一些接口,如果某个类实现了这个接口,并且这个类中的某些set方法在接口中也存在,那么这个set方法在自动注入(byType/byName/constructor)的时候是不会执行的,比如EnvironmentAware这个接口,如果某个类实现了这个接口,那么就必须实现它的setEnvironment方法,而这是一个set方法,和Spring中的autowire是冲突的,那么Spring在自动注入时是不会调用setEnvironment方法的,而是等到回调Aware接口时再来调用(注意,这个功能仅限于Spring的自动注入autowireMode,@Autowired注解是忽略这个属性的)
EnvironmentAware
EmbeddedValueResolverAware
ResourceLoaderAware
ApplicationEventPublisherAware
MessageSourceAware
ApplicationContextAware
ApplicationStartupAware
另外其实在构造BeanFactory的时候就已经提前添加了忽略另外三个:
BeanNameAware
BeanFactoryAware
BeanClassLoaderAware
添加resolvableDependencies:在byType进行依赖注入时,会先从这个属性中根据类型找bean
BeanFactory.class:当前BeanFactory对象
ResourceLoader.class:当前ApplicationContext对象
ApplicationEventPublisher.class:当前ApplicationContext对象
ApplicationContext.class:当前ApplicationContext对象
添加一个Bean的后置处理器:ApplicationListenerDetector,是一个BeanPostProcessor,用来判断某个Bean是不是ApplicationListener,如果是则把这个Bean添加到ApplicationContext中去
添加一些单例bean到单例池:
environment:Environment对象
systemProperties:System.getProperties()返回的Map对象
systemEnvironment:System.getenv()返回的Map对象
applicationStartup:JFR相关的
postProcessBeanFactory(beanFactory) : 提供给AbstractApplicationContext的子类进行扩展,具体的子类,可以继续向BeanFactory中再添加一些东西,比如注册RequestScope、SessionScope
invokeBeanFactoryPostProcessors(beanFactory):后面单独分析,核心会解析配置类,从而解析@ComponentScan注解、@Bean注解、@Import注解,从而解析得到BeanDefinition并注册到Spring容器中
registerBeanPostProcessors(beanFactory):因为上面的步骤完成了扫描,这个过程中程序员可能自己定义了一些BeanPostProcessor,在这一步就会把BeanFactory中所有的BeanPostProcessor找出来并实例化得到一个对象,并添加到BeanFactory中去(属性beanPostProcessors),最后再重新添加一个ApplicationListenerDetector对象(之前其实就添加了过,这里是为了把ApplicationListenerDetector移动到最后)
initMessageSource():如果BeanFactory中存在一个叫做messageSource的BeanDefinition,那么就会把这个Bean对象创建出来并赋值给ApplicationContext的messageSource属性,让ApplicationContext拥有国际化的功能
initApplicationEventMulticaster():如果BeanFactory中存在一个叫做applicationEventMulticaster的BeanDefinition,那么就会把这个Bean对象创建出来并赋值给ApplicationContext的applicationEventMulticaster属性,让ApplicationContext拥有事件发布的功能
onRefresh():提供给AbstractApplicationContext的子类进行扩展
registerListeners():从BeanFactory中获取ApplicationListener对象并添加到applicationEventMulticaster中去(后面讲事件监听机制的时候详细分析)
finishBeanFactoryInitialization(beanFactory):完成BeanFactory的初始化,主要就是实例化非懒加载的单例Bean
如果BeanFactory中存在一个叫做bootstrapExecutor的BeanDefinition,那么就会把这个Bean对象(一个线程池)创建出来并设置给BeanFactory,从而可以通过线程池并发实例化非懒加载的单例Bean
如果BeanFactory中存在一个叫做conversionService的BeanDefinition,那么就会把这个Bean对象创建出来并设置给BeanFactory,用来进行类型转换
设置${}的占位符解析器
设置BeanFactoryInitializer(Spring6.2新增)
preInstantiateSingletons,真正开始实例化非懒加载的单例Bean
finishRefresh():BeanFactory的初始化完后,就到了Spring启动的最后一步了
设置ApplicationContext的lifecycleProcessor,默认情况下设置的是DefaultLifecycleProcessor
调用lifecycleProcessor的onRefresh()方法,如果是DefaultLifecycleProcessor,那么会获取所有类型为Lifecycle的Bean对象,然后调用它的start()方法,这就是ApplicationContext的生命周期扩展机制
发布ContextRefreshedEvent事件
SmartLifecycle
@Component
public class MyLifecycle implements SmartLifecycle {
private boolean isRunning = false;
// 发布启动事件前会调用start方法(源码中可以看到两者中间没有其他环节)
@Override
public void start() {
System.out.println("start...");
isRunning = true;
}
// 发布关闭事件完成才调用stop方法(具体看容器close方法源码)
@Override
public void stop() {
System.out.println("stop...");
}
@Override
public boolean isRunning() {
return isRunning; // 如果返回false,容器close,stop不会被调用
}
}
public class Main {
public static void main(String[] args) {
// 容器启动过程中会做哪些事情?
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(MyConfig.class);
// applicationContext.getEnvironment().setRequiredProperties("kkk");
AnnotatedGenericBeanDefinition beanDefinition = new AnnotatedGenericBeanDefinition(UserService.class);
beanDefinition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
applicationContext.registerBeanDefinition("userService", beanDefinition);
applicationContext.refresh();
UserService userService = (UserService) applicationContext.getBean("userService", new OrderService());
userService.test();
applicationContext.close();
}
}
总结
本章我们只是大概的把整个容器过程中的方法过了一遍,知道了容器启动过程中在干什么,但其中有些步骤没有展开,比如:解析配置类、事件监听等,后面的文章会展开学习。