7.0 Spring启动过程源码解析
前言
一般来说,spring启动,就是构造ApplicationContext对象以及调用refresh()方法的过程
spring的启动主要做了这么几件事情:
- 构造一个
BeanFactory
对象 - 解析配置类,得到BeanDefinition,并注册到BeanFactory中
- 解析
@ComponentScan
,此时就会完成扫描 - 解析
@Import
- 解析
@Bean
- ...
- 解析
- 因为
ApplicationContext
还支持国际化,所以还需要初始化MessageSource
对象 - 因为
ApplicationContext
还支持事件机制,所以还需要初始化ApplicationEventMulticaster
对象 - 把用户定义的
ApplicationListener
对象添加到ApplicationContext
中,等Spring启动完了就要发布事件了 - 创建非懒加载的单例Bean对象,并存在BeanFactory的单例池中。
- 调用
Lifecycle Bean
的start()方法 - 发布
ContextRefreshedEvent
事件
由于Spring启动过程中要创建非懒加载的单例Bean对象,那么就需要用到BeanPostProcessor
,所 以Spring在启动过程中就需要做两件事:
- 生成默认的
BeanPostProcessor
对象,并添加到BeanFactory中AutowiredAnnotationBeanPostProcessor
:处理@Autowired、@ValueCommonAnnotationBeanPostProcessor
:处理@Resource、@PostConstruct、 @PreDestroyApplicationContextAwareProcessor
:处理ApplicationContextAware
等回调
- 找到外部用户所定义的
BeanPostProcessor
对象(类型为BeanPostProcessor
的Bean对象), 并添加到BeanFactory中
1. BeanFactoryPostProcessor
Bean的后置处理器,是用来对Bean进行加工的,类似的, BeanFactoryPostProcessor
理解为BeanFactory的后置处理器,用来用对BeanFactory进行加工的。
Spring支持用户定义BeanFactoryPostProcessor
的实现类Bean,来对BeanFactory进行加工,比 如:
@Component
public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
throws BeansException {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition("userService");
beanDefinition.setAutowireCandidate(false);
}
}
以上代码,就利用了BeanFactoryPostProcessor
来拿到BeanFactory,然后获取BeanFactory内的某 个BeanDefinition对象并进行修改,注意这一步是发生在Spring启动时,创建单例Bean之前的,所 以此时对BeanDefinition就行修改是会生效的。
注意:在ApplicationContext内部有一个核心的DefaultListableBeanFactory
,它实现了 ConfigurableListableBeanFactory
和BeanDefinitionRegistry
接口,所以ApplicationContext和 DefaultListableBeanFactory
是可以注册BeanDefinition的,但是 ConfigurableListableBeanFactory
是不能注册BeanDefinition的,只能获取BeanDefinition,然后 做修改。 所以Spring还提供了一个BeanFactoryPostProcessor
的子接口: BeanDefinitionRegistryPostProcessor
2. BeanDefinitionRegistryPostProcessor
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor{
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
BeanDefinitionRegistryPostProcessor
继承了BeanFactoryPostProcessor
接口,并新 增了一个方法,注意方法的参数为BeanDefinitionRegistry
,所以如果我们提供一个类来实现 BeanDefinitionRegistryPostProcessor
,那么在postProcessBeanDefinitionRegistry()
方法中就可 以注册BeanDefinition了。
public static void main(String[] args) {
@Component
public class ZhouyuBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition()
.getBeanDefinition();
beanDefinition.setBeanClass(User.class);
registry.registerBeanDefinition("user", beanDefinition);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition("userService");
beanDefinition.setAutowireCandidate(false);
}
}
}
3. 如何理解refresh()?
取自源码注释翻译:
加载或刷新持久化的配置,可能是XML文件、属性文件或关系数据库中存储的。由于这是一个启动方法,如果失败,它应该销毁已经创建的单例,以避免暂用资源。换句话说,在调用该方法之后,应该实例化所有的单例, 或者根本不实例化单例 。
ApplicationContext关闭之后不代表JVM也关闭了,ApplicationContext是 属于JVM的,说白了ApplicationContext也是JVM中的一个对象。
在Spring的设计中,也提供可以刷新的ApplicationContext和不可以刷新的ApplicationContext。
// 可以刷新
AbstractRefreshableApplicationContext extends AbstractApplicationContext
// 不可以刷新
GenericApplicationContext extends AbstractApplicationContext
AnnotationConfigApplicationContext
继承的是GenericApplicationContext
,所以它是不能刷新 的。 AnnotationConfigWebApplicationContext
继承的是 AbstractRefreshableWebApplicationContext
,所以它是可以刷的。 上面说的不能刷新是指不能重复刷新,只能调用一次refresh方法,第二次时会报错。
4. refresh()底层原理流程
面以AnnotationConfigApplicationContext
为例子,来介绍refresh的底层原理。
-
在调用
AnnotationConfigApplicationContext
的构造方法之前,会调用父类GenericApplicationContext
的无参构造方法,会构造一个BeanFactory,为DefaultListableBeanFactory
。 -
构造
AnnotatedBeanDefinitionReader
(主要作用添加一些基础的PostProcessor,同时可以通过reader进行BeanDefinition的注册),同时对BeanFactory进行设置和添加 PostProcessor(后置处理器)- 设置
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
(主要作用可以用来扫描得到并注册 BeanDefinition),同时进行设置:- 设置
this.includeFilters = AnnotationTypeFilter(Component.class)
- 设置environment
- 设置resourceLoader
- 设置
-
利用reader注册 AppConfig 为BeanDefinition,类型为
AnnotatedGenericBeanDefinition
-
调用refresh方法
-
prepareRefresh()
:- 记录启动时间
- 可以允许子容器设置一些内容到Environment中
- 验证Environment中是否包括了必须要有的属性
-
obtainFreshBeanFactory
():进行BeanFactory的refresh,在这里会去调用子类的 refreshBeanFactory方法,具体子类是怎么刷新的得看子类,然后再调用子类的 getBeanFactory方法,重新得到一个BeanFactory -
prepareBeanFactory(beanFactory)
:-
设置beanFactory的类加载器
-
设置表达式解析器:
StandardBeanExpressionResolver
,用来解析Spring中的表达式 -
添加
PropertyEditorRegistrar
:ResourceEditorRegistrar,PropertyEditor类型转化器注册器,用来注册一些默认的PropertyEditor -
添加一个Bean的后置处理器:
ApplicationContextAwareProcessor
,是一个BeanPostProcessor
,用来执行EnvironmentAware
、ApplicationEventPublisherAware
等回调方法 -
添加
ignoredDependencyInterface
:可以向这个属性中添加一些接口,如果某个类实现 了这个接口,并且这个类中的某些set方法在接口中也存在,那么这个set方法在自动注入的时候是不会执行的,比如EnvironmentAware
这个接口,如果某个类实现了这个接口,那么就必须实现它的setEnvironment方法,而这是一个set方法,和Spring中的autowire是冲突 的,那么Spring在自动注入时是不会调用setEnvironment方法的,而是等到回调Aware接口时再来调用(注意,这个功能仅限于xml的autowire,@Autowired注解是忽略这个属性的)-
EnvironmentAware
-
EmbeddedValueResolverAware
-
ResourceLoaderAware
-
ApplicationEventPublisherAware
-
MessageSourceAware
-
ApplicationContextAware
-
另外其实在构造BeanFactory的时候就已经提前添加了另外三个:
BeanNameAware
BeanClassLoaderAware
BeanFactoryAware
-
-
添加
resolvableDependencies
:在byType进行依赖注入时,会先从这个属性中根据类型 找bean- BeanFactory.class:当前BeanFactory对象
- ResourceLoader.class:当前ApplicationContext对象
- ApplicationEventPublisher.class:当前ApplicationContext对象
- ApplicationContext.class:当前ApplicationContext对象
-
添加一个Bean的后置处理器:
ApplicationListenerDetector
,是一个 BeanPostProcessor,用来判断某个Bean是不是ApplicationListener,如果是则把这个 Bean添加到ApplicationContext中去,注意一个ApplicationListener只能是单例的 -
添加一个Bean的后置处理器:
LoadTimeWeaverAwareProcessor
,是一个 BeanPostProcessor,用来判断某个Bean是不是实现了LoadTimeWeaverAware
接口,如果实现了则把ApplicationContext中的loadTimeWeaver回调setLoadTimeWeaver方法设 置给该Bean。 -
添加一些单例bean到单例池:
- "environment":Environment对象
- "systemProperties":System.getProperties()返回的Map对象
- "systemEnvironment":System.getenv()返回的Map对象
-
-
postProcessBeanFactory(beanFactory)
: 提供给AbstractApplicationContext
的子类进行扩 展,具体的子类,可以继续向BeanFactory中再添加一些东西 -
invokeBeanFactoryPostProcessors(beanFactory):
执行BeanFactoryPostProcessor
- . 此时在BeanFactory中会存在一个BeanFactoryPostProcessor:
ConfigurationClassPostProcessor
,它也是一个BeanDefinitionRegistryPostProcessor
- 第一阶段
- 从BeanFactory中找到类型为
BeanDefinitionRegistryPostProcessor
的beanName,也就是ConfigurationClassPostProcessor
, 然后调用BeanFactory的getBean方法得到实例对象 - 执行
ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry()
方法: - 解析AppConfig类
- 扫描得到BeanDefinition并注册
- 解析@Import,@Bean等注解得到BeanDefinition并注册
- 在这里,我们只需要知道在这一步会去得到BeanDefinition,而这些BeanDefinition中 可能存在
BeanFactoryPostProcessor
和BeanDefinitionRegistryPostProcessor
,所以 执行完ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry()
方 法后,还需要继续执行其他BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry()
方法 - 执行其他
BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry()
方法 - 执行所有
BeanDefinitionRegistryPostProcessor#postProcessBeanFactory()
方法 - 第二阶段
- 从BeanFactory中找到类型为
BeanFactoryPostProcessor
的beanName,而这些BeanFactoryPostProcessor
包括了上面的BeanDefinitionRegistryPostProcessor
- 执行还没有执行过的
BeanFactoryPostProcessor#postProcessBeanFactory()
方法
- . 此时在BeanFactory中会存在一个BeanFactoryPostProcessor:
-
到此,所有的
BeanFactoryPostProcessor
的逻辑都执行完了,主要做的事情就是得到 BeanDefinition并注册到BeanFactory中 -
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
类型的beanName,然后添加 到ApplicationContext中的事件广播器applicationEventMulticaster
中去,到这一步因为 FactoryBean还没有调用getObject()方法生成Bean对象,所以这里要在根据类型找一下 ApplicationListener,记录一下对应的beanName -
finishBeanFactoryInitialization(beanFactory)
:完成BeanFactory的初始化,主要就是实例化非懒加载的单例Bean,单独讲。 -
finishRefresh()
:BeanFactory的初始化完后,就到了Spring启动的最后一步 -
设置ApplicationContext的lifecycleProcessor,默认情况下设置的是
DefaultLifecycleProcessor
-
调用
lifecycleProcessor#onRefresh()
方法,如果是DefaultLifecycleProcessor,那么会获取所 有类型为Lifecycle的Bean对象,然后调用它的start()方法,这就是ApplicationContext的生命周期扩展机制 -
发布ContextRefreshedEvent事件
5. 执行BeanFactoryPostProcessor
- 执行通过ApplicationContext添加进来的
BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry()
方法 - 执行BeanFactory中实现了PriorityOrdered接口的
BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry()
方法 - 执行BeanFactory中实现了Ordered接口的
BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry()
方法 - 执行BeanFactory中其他的
BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry()
方法 - 执行上面所有的
BeanDefinitionRegistryPostProcessor#postProcessBeanFactory()
方法 - 执行通过ApplicationContext添加进来的
BeanFactoryPostProcessor#postProcessBeanFactory()
方法 - 执行BeanFactory中实现了PriorityOrdered接口的
BeanFactoryPostProcessor#postProcessBeanFactory()
方法 - 执行BeanFactory中实现了Ordered接口的
BeanFactoryPostProcessor#postProcessBeanFactory()
方法 - 执行BeanFactory中其他的
BeanFactoryPostProcessor#postProcessBeanFactory()
方法
6. Lifecycle的使用
Lifecycle表示的是ApplicationContext的生命周期,可以定义一个SmartLifecycle
来监听 ApplicationContext的启动和关闭:
public static void main(String[] args) {
@Component
public class CustomLifecycle implements SmartLifecycle {
private boolean isRunning = false;
@Override
public void start() {
System.out.println("启动");
isRunning = true;
}
@Override
public void stop() {
// 要触发stop(),要调用context.close(),或者注册关闭钩子(context.registerShutdownHook();)
System.out.println("停止");
isRunning = false;
}
@Override
public boolean isRunning() {
return isRunning;
}
}
}