Spring 容器启动全流程
Spring 容器启动全流程

1. 入口:创建容器
1 | new AnnotationConfigApplicationContext(Class<?>... componentClasses) |
构造方法内部依次执行三个步骤:
1 | this() → register(componentClasses) → refresh() |
2. this() — 初始化 Reader 和 Scanner
2.1 创建 AnnotatedBeanDefinitionReader
1 | this.reader = new AnnotatedBeanDefinitionReader(this); |
内部调用:
1 | this.conditionEvaluator = new ConditionEvaluator(registry, environment, null); |
1 | AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry); |
注册了 Spring 框架需要使用的类的 BeanDefinition(还没有真正创建),包括:
AnnotationAwareOrderComparatorContextAnnotationAutowireCandidateResolverConfigurationClassPostProcessorAutowiredAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessorPersistenceAnnotationBeanPostProcessorEventListenerMethodProcessorDefaultEventListenerFactory
2.2 创建 ClassPathBeanDefinitionScanner
1 | this.scanner = new ClassPathBeanDefinitionScanner(this); |
ClassPathBeanDefinitionScanner#doScan(String... basePackages)是 Spring 后续进行包路径扫描的方法。但没有使用此时的实例对象,而是重新创建。
3. register(componentClasses) — 注册配置类
1 | this.reader.register(componentClasses); |
将配置类注册到容器中。
4. refresh() — 核心启动流程
4.1 prepareRefresh()
1 | // 这个方法主要做了以下几件事 |
4.2 obtainFreshBeanFactory()
1 | ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); |
核心就是获取到一个
DefaultListableBeanFactory。在前面new AnnotationConfigApplicationContext(Class<?>... componentClasses)的this()中,Java 会执行父类GenericApplicationContext的无参构造this.beanFactory = new DefaultListableBeanFactory(),所以AnnotationConfigApplicationContext实例化后就有DefaultListableBeanFactory对象了。
4.3 prepareBeanFactory(beanFactory)
为 bean 工厂设置一些属性。
依次执行:
设置 ClassLoader
1
beanFactory.setBeanClassLoader(getClassLoader());
设置 classLoader,一般就是 appClassLoader。
设置 EL 表达式解析器
1
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
设置 EL 表达式解析器。
添加属性编辑器注册表
1
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
容器中添加一个属性编辑器注册表。
注册 ApplicationContextAwareProcessor(重要)
1
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
注册一个 bean 后置处理器。
ApplicationContextAware、EnvironmentAware等 6 个 Aware 方法就是ApplicationContextAwareProcessor#postProcessBeforeInitialization回调赋值的。忽略 Aware 接口的依赖检查
1
2beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
// ......忽略上面 6 个 Aware 的依赖检查,不进行依赖检查也就不会进行自动注入。所以 bean 里面注入这几个 Aware 是无效的。
注册可解析的依赖
1
2beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
// ...设置几个自动装配。这样 Bean 里面进行注入 eg:
ApplicationContext时就可以获取到。添加 ApplicationListenerDetector
1
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
添加一个后置处理器,用于处理
ApplicationListener。
4.4 postProcessBeanFactory(beanFactory)
1 | // Allows post-processing of the bean factory in context subclasses. |
4.5 invokeBeanFactoryPostProcessors(beanFactory) — 注解模式下 BeanDefinition 注册的核心
1 | // Invoke factory processors registered as beans in the context. |
1 | PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()); |
4.5.1 获取并创建 BeanDefinitionRegistryPostProcessor
1 | // ...... |
这段代码就是创建了
BeanDefinitionRegistryPostProcessor的类,就是AnnotatedBeanDefinitionReader初始化时注册的其中一个 BeanDefinition ->ConfigurationClassPostProcessor。
4.5.2 调用 postProcessBeanDefinitionRegistry 开始扫描
1 | invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); |
开始扫描并注册 BeanDefinition。
1 | ConfigurationClassPostProcessor#postProcessor.postProcessBeanDefinitionRegistry(registry); |
4.5.3 processConfigBeanDefinitions(registry)
1 | String[] candidateNames = registry.getBeanDefinitionNames(); |
此时候选对象就是前面 Spring 自身注册的几个 BeanDefinition 以及我们的配置类。
4.5.4 判断配置类
1 | ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory) |
判断是否配置类。就是我们自己定义的启动类 eg:
XxxApplication。
4.5.5 解析配置类
1 | ConfigurationClassParser parser = new ConfigurationClassParser( |
1 | parser.parse(candidates); |
通过
@ComponentScan,@ComponentScans一类的注解,完成扫描。此时项目中非配置类创建的 BeanDefinition 都已经注入。
4.5.6 加载 @Bean 和 @Import
1 | this.reader.loadBeanDefinitions(configClasses); |
加载
@Bean注解解析信息,@Import注解解析信息等等。
4.5.7 注册 ImportRegistry
1 | if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) { |
注册 ImportRegistry 到容器中。当通过
@Import注解导入一个全配置类 A(被@Configuration注解修饰的类),A 可以实现ImportAware接口,通过这个 Aware 可以感知到是哪个类导入的 A。
4.5.8 调用 BeanFactoryPostProcessor
1 | invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory); |
按照不同分类循环调用
postProcessor.postProcessBeanFactory(beanFactory);
4.6 registerBeanPostProcessors(beanFactory)
注册 BeanPostProcessors。
4.7 initMessageSource()
初始化容器中的 messageSource,如果程序员没有提供,默认会创建一个
org.springframework.context.support.DelegatingMessageSource。
4.8 initApplicationEventMulticaster()
初始化事件分发器,如果程序员没有提供,那么默认创建一个
org.springframework.context.event.ApplicationEventMulticaster。
4.9 onRefresh()
留给子类复写扩展使用。
4.10 registerListeners()
注册事件监听器,就是将容器中所有实现了
org.springframework.context.ApplicationListener接口的对象放入到监听器的集合中。
4.11 finishBeanFactoryInitialization(beanFactory) — 创建 Bean,IOC 的核心
1 | beanFactory.preInstantiateSingletons(); |
Bean 创建流程
1 | abstractBeanFactory#getBean |
doCreateBean 内部流程
实例化
1
createBeanInstance(beanName, mbd, args);
加入三级缓存(重要)
1
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
有需要时加入三级缓存。在完成 Bean 的实例化后,属性注入之前 Spring 将 Bean 包装成一个工厂添加进了三级缓存中。
属性赋值
1
populateBean(beanName, mbd, instanceWrapper);
初始化
1
exposedObject = initializeBean(beanName, exposedObject, mbd);
加入一级缓存
1
addSingleton(beanName, singletonObject);
添加到一级缓存
singletonObjects中。
三级缓存
| 缓存级别 | 字段名 | 说明 |
|---|---|---|
| 一级缓存 | singletonObjects |
存储的是所有创建好了的单例 Bean |
| 二级缓存 | earlySingletonObjects |
完成实例化,但是还未进行属性注入及初始化的对象 |
| 三级缓存 | singletonFactories |
提前暴露的一个单例工厂,二级缓存中存储的就是从这个工厂中获取到的对象 |
getEarlyBeanReference 与 AOP 代理
1 | getEarlyBeanReference(beanName, mbd, bean); |
这个就是二级缓存获取对象时调用的方法。
不存在 AOP 情况下,直接将前面实例化完成的对象返回。
存在 AOP 的情况下,它实际上就是调用了后置处理器的
getEarlyBeanReference方法去返回代理对象。而真正实现了这个方法的后置处理器只有一个,就是通过@EnableAspectJAutoProxy注解导入的AnnotationAwareAspectJAutoProxyCreator。所以二级缓存存在的目的就是为了 AOP 返回代理对象。
4.12 finishRefresh()
完成刷新,发布容器刷新完成事件。