Spring 容器启动全流程

spring 容器启动全流程.png

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(还没有真正创建),包括:

  • AnnotationAwareOrderComparator
  • ContextAnnotationAutowireCandidateResolver
  • ConfigurationClassPostProcessor
  • AutowiredAnnotationBeanPostProcessor
  • CommonAnnotationBeanPostProcessor
  • PersistenceAnnotationBeanPostProcessor
  • EventListenerMethodProcessor
  • DefaultEventListenerFactory

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
2
3
4
5
6
7
// 这个方法主要做了以下几件事
// 1.记录容器的启动时间,并将容器状态更改为激活
// 2.调用initPropertySources()方法,主要用于web环境下初始化封装相关的web资源,
// 比如将servletContext封装成为ServletContextPropertySource
// 3.校验环境中必要的属性是否存在
// 4.提供了一个扩展点可以提前放入一些事件,当applicationEventMulticaster
// 这个bean被注册到容器中后就直接发布事件

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 工厂设置一些属性。

依次执行:

  1. 设置 ClassLoader

    1
    beanFactory.setBeanClassLoader(getClassLoader());

    设置 classLoader,一般就是 appClassLoader。

  2. 设置 EL 表达式解析器

    1
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));

    设置 EL 表达式解析器。

  3. 添加属性编辑器注册表

    1
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

    容器中添加一个属性编辑器注册表。

  4. 注册 ApplicationContextAwareProcessor(重要)

    1
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

    注册一个 bean 后置处理器。ApplicationContextAwareEnvironmentAware 等 6 个 Aware 方法就是 ApplicationContextAwareProcessor#postProcessBeforeInitialization 回调赋值的。

  5. 忽略 Aware 接口的依赖检查

    1
    2
    beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
    // ......

    忽略上面 6 个 Aware 的依赖检查,不进行依赖检查也就不会进行自动注入。所以 bean 里面注入这几个 Aware 是无效的。

  6. 注册可解析的依赖

    1
    2
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    // ...

    设置几个自动装配。这样 Bean 里面进行注入 eg:ApplicationContext 时就可以获取到。

  7. 添加 ApplicationListenerDetector

    1
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

    添加一个后置处理器,用于处理 ApplicationListener

4.4 postProcessBeanFactory(beanFactory)

1
2
3
4
// Allows post-processing of the bean factory in context subclasses.
// 是一个空方法,留给子类实现,主要是一些web相关的ApplicationContext会重写这个方法,
// 传入的是当前容器,操作空间也是非常大的。由于是个空方法,这里不再赘述。
// 允许容器的子类去注册PostProcessor,钩子方法.

4.5 invokeBeanFactoryPostProcessors(beanFactory) — 注解模式下 BeanDefinition 注册的核心

1
2
3
4
5
6
// Invoke factory processors registered as beans in the context.
// 激活容器中注册为bean的BeanFactoryPostProcessor
// 对于注解容器,org.springframework.context.annotation.ConfigurationClassPostProcessor
// 实例化并调用所有已注册的 BeanFactoryPostProcessor bean,如果给定顺序,则按照顺序去执行
// 所有的后置处理器必须在其他的单例bean实例化之前被调用。
// **注解模式下,主要是这里进行BeanDefinition的注册**
1
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

4.5.1 获取并创建 BeanDefinitionRegistryPostProcessor

1
2
3
4
5
6
7
8
9
10
11
// ......
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName,
BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
// ......

这段代码就是创建了 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
2
3
4
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
// 创建该类,用于配置类分析
1
parser.parse(candidates);

通过 @ComponentScan@ComponentScans 一类的注解,完成扫描。此时项目中非配置类创建的 BeanDefinition 都已经注入。

4.5.6 加载 @Bean 和 @Import

1
this.reader.loadBeanDefinitions(configClasses);

加载 @Bean 注解解析信息,@Import 注解解析信息等等。

4.5.7 注册 ImportRegistry

1
2
3
if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}

注册 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
2
3
4
5
6
7
8
9
10
abstractBeanFactory#getBean
→ abstractBeanFactory#doGetBean
→ DefaultSingletonBeanRegistry#getSingleton(beanName, true) // 尝试从三级缓存中依次获取bean对象
→ getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
} catch (BeansException ex) {}
})
→ AbstractAutowireCapableBeanFactory#createBean(beanName, mbd, args)
→ Object beanInstance = doCreateBean(beanName, mbdToUse, args)

doCreateBean 内部流程

  1. 实例化

    1
    createBeanInstance(beanName, mbd, args);
  2. 加入三级缓存(重要)

    1
    addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

    有需要时加入三级缓存。在完成 Bean 的实例化后,属性注入之前 Spring 将 Bean 包装成一个工厂添加进了三级缓存中。

  3. 属性赋值

    1
    populateBean(beanName, mbd, instanceWrapper);
  4. 初始化

    1
    exposedObject = initializeBean(beanName, exposedObject, mbd);
  5. 加入一级缓存

    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()

完成刷新,发布容器刷新完成事件。