概述
Spring容器初始化过程,会伴随着Bean的初始化,下文将以AnnotationConfigApplicationContext类为例,从源码开始讲解Spring容器的初始化和Bean的初始化过程。
专业术语
简称 | 名称 | |
---|---|---|
ACAC | AnnotationConfigApplicationContext | 基于注解配置类的spring容器上下文 |
pp | PostProcessor | 后置处理器。以BeanFactoryPostProcessor为例,在BF初始化完成,实例化其他bean之前会调用所有对BF的后置处理器。 |
源码
从ACAC构造看spring容器加载过程
// demo启动类的main方法中 new一个AnnotationConfigApplicationContext
public static void main(String[] args) {
// 传入一个配置类
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(DefConfig.class);
DemoBan bean = annotationConfigApplicationContext.getBean(DemoBan.class);
bean.sayHello();
}
// 自定义的配置类 将决定spring扫描哪些包下面的bean
@ComponentScan("com.demo.springweb")
public static class DefConfig {
@Bean
MyPostProcessor myPostProcessor(){
return new MyPostProcessor();
}
}
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
this();
register(annotatedClasses);
refresh();
}
可以看到AnnotationConfigApplicationContext(以上简称ACAC)类中构造方法主要包含注册和刷新两个方法。
- 注册: 读取应用程序提供的bean配置信息,并在容器中生成一张bean配置注册表;
- 刷新:
注册
配置类装配成BeanDefinition
调用org.springframework.context.annotation.AnnotatedBeanDefinitionReader#registerBean(java.lang.Class<?>, java.lang.String, java.lang.Class<? extends java.lang.annotation.Annotation>…) 方法,将配置类装配成BeanDefinition后存放到 beanDefinitionMap
刷新
- prepareRefresh(); 准备上下文 ,初始化ACAC的父类AbstractApplicationContext中的一些属性
- obtainFreshBeanFactory(); 获取并刷新BeanFactory
- prepareBeanFactory(bf);
初始化BeanFactory
- 设置ignoreDepencyInterfaces, 忽略给定接口的自动装配功能
- 添加系统的PostProcessors
- 注册systemProperties,systemEnvrionment在内的系统bean到beanFactory
systemProperies里存放java运行环境,jdk版本、编码等
systemEnvrionment存放maven_home, mainclass等
postProcessBeanFactory()
ACAC类中为空实现,允许其他AbstractApplicationContext的子类对BeanFactory做后置处理
invokeBeanFactoryPostProcessors()
调用所有的BeanFactoryPostProcessors,包括spring容器内置的和bean扫描到用户自定义的。
- 调用系统pp
ACAC中系统的pp主要是:ConfigrationClassPostProcessor,其核心方法processConfigBeanDefinitions主要是做:
- 拿到应用程序定义(如代码一中的DefConfig)的config配置类对应的BeanDefinition
- 调用ConfigurationClassParser类的parse方法,对应用程序定义配置类解析
- parse方法中调用ComponentScanAnnotationParser.parse方法,对程序定义配置类中的定义的包路径扫描
- 调用ClassPathBeanDefinitionScanner.scan方法扫描对应包路径下所有的Bean对应的BeanDefinition,并注册到beanDefinitionMap。 (这里并不会直接实例化)
- 调用应用程序定义的pp
- 调用ClassPathBeanDefinitionScanner.scan方法扫描对应包路径下所有的Bean对应的BeanDefinition,并注册到beanDefinitionMap。 (这里并不会直接实例化)
- parse方法中调用ComponentScanAnnotationParser.parse方法,对程序定义配置类中的定义的包路径扫描
- 从BeanFactory获取所有应用定义的pp(代码块一中的MyPostProcessor),没有实例化则先实例化
- 调用pp的postProcessBeanDefinitionRegistry方法
- registerBeanPostProcessors() 注册bpp,仅注册不会调用
BeanPostProcessor接口的核心方法是postProcessBeforeInitialization,postProcessAfterInitialization分别将在bean实例化前和实例化后被调用。
- 找到并实例化所有的BeanPostProcessors
- 添加到DefalutListableBeanFactory的BeanPostProcessors中去,供bean实例化前后调用
Spring容器内置的BeanPostProcessor有:
- ApplicationContextAwareProcessor
- CommonAnnotationBeanPostProcessor
- AutowriedAnnotationBeanPostProcessor
- RequireAnnotaionBeanPostProcessor
- ApplicationListenerDetecotr
- initMessageSource()
- initApplicationEventMulticaster()
- onRefresh();
空实现
- registerListeners()
注册应用监听器
- finishBeanFactoryInitialization(beanFactory);
这一步主要是实例化所有单列bean.
- beanFactory.setTempClassLoader(null);// Stop using the temporary ClassLoader for type matching.
- beanFactory.freezeConfiguration()
冻结全部bean定义,给被注册的bean定义发信号告诉它们今后不再被修改和进一步后续处理。它允许factory去积极缓存bean定义元数据。
- beanFactory.preInstantiateSingletons()
实例化所有单例
- 根据在beanDefinitionNames注册的beanName,找到所有的beanDefinition
- 实例化所有单例bean到singletonObjects. 调用DefaultListableBeanFactory中的doGetBean方法, 有则返回,没有则反射实例化注册到singletonObjects的map中并返回
实例化bean前后还有其他复杂操作,下文再讲
c. 对实现了SmartInitializingSingleton接口的bean,调用其afterSingletonsInstantiated()方法。
- finishRefresh()
其他