Spring 启动过程

本文详细解释了Spring启动过程,涉及AnnotationConfigApplicationContext的创建、BeanFactory的初始化、BeanPostProcessor的处理以及ConfigurationClassPostProcessor的作用,展示了从构造ApplicationContext到调用refresh方法的底层流程。
摘要由CSDN通过智能技术生成

博文目录


内容总结

Spring启动流程详解

通常,我们说的 Spring 启动,就是构造 ApplicationContext 对象以及调用 refresh() 方法的过程。

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Application.class);

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(Application.class);
context.refresh();

ApplicationContext 的定位是 Spring 的应用上下文, 负责管理和组织应用程序的各个部分. 从代码层面来说, ApplicationContext 是一个 BeanFactory, 从架构层面来说, ApplicationContext 是比 BeanFactory 更加高级的存在, 它统御 BeanFactory, EnvironmentCapable, MessageSource 等这些组件完成相应的功能, BeanFactory 只是它的一个零件而已. GenericApplicationContext 不继承 DefaultListableBeanFactory 而是将之作为一个属性, 从 BeanFactory 继承来的功能全部委托其持有的 DefaultListableBeanFactory 来执行

大致做了下面的一些事情

  • 构造了一个 DefaultListableBeanFactory 对象
  • 初始化一些基础架构组件
  • 解析配置类, 得到 BeanDefinition, 注册到 BeanFactory 中
    • 解析 @ComponentScan, 完成扫描
    • 解析 @Import
    • 解析 @Bean
  • 初始化 MessageSource 支持国际化
  • 初始化 ApplicationEventMulticaster 支持事件机制, 将用户定义的 ApplicationListener 添加到 ApplicationContext 中
  • 创建 非懒加载的单例 Bean, 并存在 BeanFactory 的单例池中
  • 调用 Liftcycle Bean 的 start 方法
  • 发布 ContextRefreshedEvent 事件

由于 Spring 启动过程中要创建非懒加载的单例 Bean 对象, 那么就需要用到 BeanPostProcessor, 所以 Spring 在启动过程中就需要做两件事

  • 生成默认的 BeanPostProcessor 对象, 并添加到 BeanFactory 中
    • AutowiredAnnotationBeanPostProcessor, 处理@Autowired, @Value
    • CommonAnnotationBeanPostProcessor, 处理@Resource, @PostConstruct, @PreDestroy
    • ApplicationContextAwareProcessor, 处理 ApplicationContextAware 等回调
  • 找到外部用户所定义的 BeanPostProcessor 对象 (类型为 BeanPostProcessor 的 Bean 对象), 并添加到 BeanFactory 中

new AnnotationConfigApplicationContext

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Application.class);

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
	this();
	register(componentClasses);
	refresh();
}

public AnnotationConfigApplicationContext() {
	// todo 会调用父类的无参构造方法, super(); 创建 BeanFactory (DefaultListableBeanFactory)
	StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");
	// new Reader, 用来支持 ApplicationContext 的 register 等功能
	this.reader = new AnnotatedBeanDefinitionReader(this);
	createAnnotatedBeanDefReader.end();
	// new Scanner, 用来支持 ApplicationContext 的 scan 功能
	this.scanner = new ClassPathBeanDefinitionScanner(this);
}

AnnotationConfigApplicationContext

  • 调用父类 GenericApplicationContext 的构造方法, 生成 DefaultListableBeanFactory 并赋值给 this.beanFactory
  • 构造 AnnotatedBeanDefinitionReader, 添加一些基础的 PostProcessor, 为 ApplicationContext 提供 register BeanDefinition 的功能
    • 设置 BeanFactory 的 dependencyComparator 为 AnnotationAwareOrderComparator, 它是一个Comparator, 是用来进行排序的, 会获取某个对象上的 Order 注解或者通过实现 Ordered 接口所定义的值进行排序
    • 设置 BeanFactory 的 autowireCandidateResolver 为 ContextAnnotationAutowireCandidateResolver, 多级继承, 每级提供不同的功能, 如 @Lazy 字段生成代理, @Qualifier 解析, 判断某个 Bean 是否可用于依赖注入 (isAutowireCandidate)
    • 添加 BeanDefinition ConfigurationClassPostProcessor, 是一个 BeanFactoryPostProcessor, 用于解析配置类, 涉及到扫描
    • 添加 BeanDefinition AutowiredAnnotationBeanPostProcessor, 用于处理与 @Autowired, @Value 注解相关的内容, 包括推断构造方法, 依赖注入点查找, 执行注入 等
    • 添加 BeanDefinition CommonAnnotationBeanPostProcessor, 用于处理与 @Resource, @PostConstruct, @PreDestroy 注解相关的内容, 包括依赖注入点查找, 执行依赖注入 等
    • 添加 BeanDefinition EventListenerMethodProcessor, 具体见下方 refresh 中的 registerListeners 阶段, 一个 Bean 中如果有一个方法加了 @EventListener 注解, 将由 EventListenerMethodProcessor 解析处理, 它是一个 BeanFactoryPostProcessor, EventListenerMethodProcessor 实现了 SmartInitializingBean 接口, 当所有非懒加载单例 Bean 创建完后, 会调用实现该接口的 Bean 的 afterSingletonsInstantiated 方法, 方法内, 拿到所有 BeanNames, 遍历调用 processBean 方法, 找到其加了 EventListener 注解的方法, 现在还不能去调用, 默认使用 DefaultEventListenerFactory 将该方法构造成 ApplicationListenerMethodAdapter (实现了 ApplicationListener), 添加到 ApplicationContext 的 listener 中
    • 添加 BeanDefinition DefaultEventListenerFactory, 同上
  • 构造 ClassPathBeanDefinitionScanner, 可以用来扫描得到并注册 BeanDefinition
    • 设置 this.includeFilters = AnnotationTypeFilter(Component.class)
    • 设置 environment
    • 设置 resourceLoader
  • 利用 reader 注册 Application.class 为 BeanDefinition, 类型为 AnnotatedGenericBeanDefinition

AbstractApplicationContext.refresh

/**
 * Load or refresh the persistent representation of the configuration, which
 * might be from Java-based configuration, an XML file, a properties file, a
 * relational database schema, or some other format.
 * <p>As this is a startup method, it should destroy already created singletons
 * if it fails, to avoid dangling resources. In other words, after invocation
 * of this method, either all or no singletons at all should be instantiated.
 * @throws BeansException if the bean factory could not be initialized
 * @throws IllegalStateException if already initialized and multiple refresh
 * attempts are not supported
 */
void refresh() throws BeansException, IllegalStateException;

这是 ConfigurableApplicationContext 接口上 refresh 方法的注释, 意思是: 加载或刷新持久化的配置, 可能是XML文件, 属性文件, 关系数据库中存储的. 由于这是一个启动方法, 如果失败, 它应该销毁已经创建的单例, 以避免占用资源. 换句话说, 在调用该方法之后, 应该实例化所有的单例, 或者根本不实例化单例

Spring 提供了多种 ApplicationContext, 可刷新的和不可刷新的, 不能刷新是指不能重复刷新, 只能调用一次 refresh 方法, 第二次时会报错

  • AbstractRefreshableApplicationContext, AbstractRefreshableWebApplicationContext, AnnotationConfigWebApplicationContext
  • GenericApplicationContext, AnnotationConfigApplicationContext

底层流程

ConfigurableApplicationContext#refresh, 以 AnnotationConfigApplicationContext 为例

prepareRefresh

  • 给子类提供了额外添加 kv 到 Environment 的方式, 检查必要 kv 是否存在, 额外赋了几个值

obtainFreshBeanFactory

  • 给子类提供刷新 BeanFactory 的抽象, 由子类决定是否支持, 支持的话, 销毁旧 Bean, 关闭旧 BeanFactory, 重新创建新的 BeanFactory, 返回 BeanFactory
  • SpringMVC / SpringBoot 等可能需要刷新容器, 比如热部署等

prepareBeanFactory

  • 设置 BeanFactory 的类加载器
  • 设置 BeanFactory 的表达式解析器, StandardBeanExpressionResolver, 用来解析 SpringEL
  • 添加类型转化注册器, ResourceEditorRegistrar, 自带注册一些默认的 String 转其他对象的转换器
  • 添加 BeanPostProcessor ApplicationContextAwareProcessor, 用来执行 ApplicationContext 相关 Aware 的 Setter 回调方法
  • 添加 ignoredDependencyInterfaces, 忽略指定接口对应 Setter 方法在依赖注入阶段的执行, 因为在依赖注入阶段后还有 Aware 执行阶段也要执行, 否则会执行两次, 没有必要. 比如通过 @Bean(byType/byName) 配置的 Bean, 在依赖注入时会判断实现的接口是否在这个列表中, 在的话就不执行对应 Setter 方法. 而如果给对应 Setter 方法加上 @Autowired 注解则没有此效果, 依赖注入阶段会因 @Autowired 的原因注入一次, 后面的 Aware 阶段又会执行一次
    • AbstractAutowireCapableBeanFactory - autowireByType/autowireByName- unsatisfiedNonSimpleProperties - isExcludedFromDependencyCheck - isSetterDefinedInInterface 里面就会用到 ignoredDependencyInterfaces 这个列表
    • EnvironmentAware, EmbeddedValueResolverAware, ResourceLoaderAware, ApplicationEventPublisherAware, MessageSourceAware, ApplicationContextAware, ApplicationStartupAware
    • BeanNameAware, BeanFactoryAware, BeanClassLoaderAware, 这三个在构造 DefaultListableBeanFactory 的时候添加
  • 添加 resolvableDependencis, 指定某些类型对应的 Bean, 比如要通过 @Autowired 注入一个 ApplicationContext, 我们没有配置这样的 Bean, 但仍然能注入成功, 就是因为这个原因. 在 ByType 依赖注入时, 会先从这个属性中根据类型找 Bean
    • BeanFactory: BeanFactory
    • ResourceLoader: ApplicationContext
    • ApplicationEventPublisher: ApplicationContext
    • ApplicationContext: ApplicationContext
  • 添加 BeanPostProcessor ApplicationListenerDetector, 用于在 Bean 初始化后检测 Bean 是否为 ApplicationListener, 是的话添加到 ApplicationContext 的 listener 中
  • 添加 BeanPostProcessor LoadTimeWeaverAwareProcessor, 负责处理实现 LoadTimeWeaverAware 接口的 Bean 的 Setter 方法的调用
  • 添加一些 Bean 到单例池
    • environment: ApplicationContext 的 Environment
    • systemProperties: 操作系统环境变量, ApplicationContext 的 Environment 中的 SystemProperties
    • systemEnvironment: JVM 环境变量, ApplicationContext 的 Environment 中的 SystemEnvironment
    • applicationStartup: 监控对象

postProcessBeanFactory

  • 模板方法, 子类实现, 补充一些上面通用流程之外的内容, 大多都是和 Web 有关
    • 比如 GenericWebApplicationContext 会补充一些 Web Servlet 相关的内容, 如 BeanPostProcessor, ignoreDependencyInterface, ResolvableDependency, 单例 Bean, request/session/application 作用域等

invokeBeanFactoryPostProcessors

  • 执行所有的 BeanFactoryPostProcessor, 包括其子接口 BeanDefinitionRegistryPostProcessor 定义的方法, 共两个方法
    • BeanDefinitionRegistryPostProcessor, 拥有注册 BeanDefinition 的能力
    • BeanFactoryPostProcessor, 不能注册 BeanDefinition, 但能获取并修改
  • 之前在实例化 AnnotationConfigApplicationContext 时创建 AnnotatedBeanDefinitionReader 里添加的 ConfigurationClassPostProcessor 的 RootBeanDefinition, 就是一个 BeanDefinitionRegistryPostProcessor, 就会在这一步被 getBean 实例化并执行, 会执行 scanner.scan, 将扫描到的 BeanDefinition 注册到 BeanFactory 中

registerBeanPostProcessors

  • 将所有的 BeanPostProcessor, 包括 Spring 自带的和用户定义的, 全部实例化并排序, 并添加到 BeanFactory 的 beanPostProcessors 中, 供创建 Bean 的流程里使用

initMessageSource

  • 初始化国际化组件, ApplicationContext 的国际化实现是通过 MessageSource 提供的, MessageSource 通常是我们自己定义的

initApplicationEventMulticaster

  • 初始化事件广播器, 事件广播器是 ApplicationContext 的事件广播实现, 通常是我们自己定义的
    • ApplicationContext.publishEvent(“111”) 底层就是通过 ApplicationEventMulticaster.multicastEvent 实现的
    • 发布的事件分 ApplicationEvent 和 PayloadApplicationEvent, 自定义的消息在监听到后需要转换为 PayloadApplicationEvent 才能看到具体内容

onRefresh

  • 模板方法, 子类实现, 给子类提供的一个 Refresh 回调

registerListeners

  • 将扫描到的 ApplicationListener (比如自己定义的事件监听器) 添加到 ApplicationEventMulticaster 中, 便于事件发布时能通知到对应监听器. 因为这时 FactoryBean 还没有调用 getObject 方法生成 Bean 对象, 所以这里要再根据类型找一下 ApplicationListener, 记录一下对应的 beanName
  • 注册监听器有多种方式, 如 Bean 实现 ApplicationListener 接口, 或 方法添加 ApplicationEvent 参数, 添加 @EventListener 注解
  • 一个 Bean 如果实现了 ApplicationListener 接口, 在初始化后阶段, 将由 ApplicationListenerDetector 这个 BeanPostProcessor 识别并加入到 ApplicationContext 的 listener 中. 即使这个 Bean 是懒加载的也没有关系(虽然实例化全部非懒加载 Bean 的流程在这一步后面), 因为在往事件多播器中注册的时候, 会对监听器执行 getBean, 懒加载的也会被创建出来.
    • ApplicationListenerDetector, 在前面 refresh 的 prepareBeanFactory 阶段添加到 beanPostProcessors 中
  • 一个 Bean 中如果有一个方法加了 @EventListener 注解, 将由 EventListenerMethodProcessor 解析处理, 它是一个 BeanFactoryPostProcessor, EventListenerMethodProcessor 实现了 SmartInitializingBean 接口, 当所有非懒加载单例 Bean 创建完后, 会调用实现该接口的 Bean 的 afterSingletonsInstantiated 方法, 方法内, 拿到所有 BeanNames, 遍历调用 processBean 方法, 找到其加了 EventListener 注解的方法, 现在还不能去调用. 默认使用 DefaultEventListenerFactory 将该方法构造成 ApplicationListenerMethodAdapter (实现了 ApplicationListener), 添加到 ApplicationContext 的 listener 中
    • EventListenerMethodProcessor, 在 new ApplicationConfigApplicationContext 初始化 Reader 的时候, 就会添加成为 BeanDefinition
    • DefaultEventListenerFactory, 在 new ApplicationConfigApplicationContext 初始化 Reader 的时候, 就会添加成为 BeanDefinition

finishBeanFactoryInitialization

  • 实例化所有非懒加载的单例 Bean

finishRefresh, 完成刷新

  • 初始化一个 LifecycleProcessor, 不存在就用 DefaultLifecycleProcessor
    • Spring 容器也有生命周期的概念, 比如一个 Bean 实现了 SmartLifecycle, 就可以覆盖 start / stop 等方法来监听容器的状态
    • finishRefresh 中调用 start, ApplicationContext.close() 时调用 stop, isRunning 返回 false 才会调用 start, 返回 true 才会调用 stop
  • 调用 lifecycleProcessor 的 onRefresh 方法, 如果是 DefaultLifecycleProcessor, 那么会获取所有类型为 Lifecycle 的 Bean 对象, 然后调用它的 start 方法, 这就是 ApplicationContext 的生命周期扩展机制
  • 发布刷新完成事件 ContextRefreshedEvent

refresh - invokeBeanFactoryPostProcessors

invokeBeanFactoryPostProcessors 阶段, 会调用所有 BeanFactoryPostProcessor 的方法, 这个阶段在创建非懒加载单例 Bean 的 finishBeanFactoryInitialization 阶段之前, 所以此阶段对 BeanDefinition 的修改是有效的

BeanFactoryPostProcessor

BeanPostProcessor 用于操作 Bean, 即方法入参都是一个 Bean

BeanFactoryPostProcessor 与之类似, 可用来操作 BeanFactory, 也可用来操作 BeanDefinition, 只提供了一个方法 postProcessBeanFactory, 方法入参是一个 ConfigurableListableBeanFactory, 这个工厂不支持注册 BeanDefinition, 但是能获取 BeanDefinition, 然后修改其内容

BeanDefinitionRegistryPostProcessor 是 BeanFactoryPostProcessor 的子接口, 额外提供了一个方法 postProcessBeanDefinitionRegistry, 入参是一个 BeanDefinitionRegistry, 这个方法支持注册 BeanDefinition

我们说的扫描 BeanDefinition, 其实就是基于 BeanDefinitionRegistryPostProcessor 接口实现的, 具体的类叫 ConfigurationClassPostProcessor

postProcessBeanDefinitionRegistry 会早于 postProcessBeanFactory 执行

我们可以通过 ApplicationContext 手动添加一些 BeanFactoryPostProcessor 实例对象

大致流程

  • 先执行全部 BeanDefinitionRegistryPostProcessorpostProcessBeanDefinitionRegistry 方法
    • 执行 ApplicationContext 中手动添加的 BeanFactoryPostProcessor 中的 BeanDefinitionRegistryPostProcessor 的该方法
    • 从容器中获取实现了 PriorityOrdered 接口的 BeanDefinitionRegistryPostProcessor, 排序并执行该方法
      • 执行过后, 会被加到一个 list 中, 供后面遍历调用另一个方法
      • 在这里就能找到 ConfigurationClassPostProcessor, 完成自定义 BeanDefinition 的扫描与注册, , 我们自定义的各种 Bean 就会在后续被找到了. ConfigurationClassPostProcessor 是在前面创建 AnnotationConfigApplicationContext 的 reader 里面被包装成 RootBeanDefinition 被注册到容器中
    • 从容器中获取实现了 Ordered 接口的 BeanDefinitionRegistryPostProcessor, 排序并执行该方法
    • 从容器中获取未实现 PriorityOrdered 和 Ordered 接口的 BeanDefinitionRegistryPostProcessor, 执行该方法
      • 因为 BeanDefinitionRegistryPostProcessor 有支持注册 BeanDefinition 的能力, 所以该方法有可能会注册新的 BeanDefinitionRegistryPostProcessor. 所以这里有额外的循环, 保证能执行到新生成的实例的该方法
  • 再执行全部 BeanFactoryPostProcessor (含 BeanDefinitionRegistryPostProcessor)postProcessBeanFactory 方法
    • 执行 ApplicationContext 中手动添加的 BeanFactoryPostProcessor 的该方法
    • 调用之前从容器中找到的实现了 PriorityOrdered 接口的 BeanDefinitionRegistryPostProcessor 的该方法
    • 调用之前从容器中找到的实现了 Ordered 接口的 BeanDefinitionRegistryPostProcessor 的该方法
    • 调用之前从容器中找到的未实现 PriorityOrdered 和 Ordered 接口 BeanDefinitionRegistryPostProcessor 的该方法
    • 从容器中获取到 BeanFactoryPostProcessor, 按 PriorityOrdered, Ordered, 未排序 分组
    • 拿到实现了 PriorityOrdered 接口的 BeanFactoryPostProcessor, 排序并执行该方法
    • 拿到实现了 Ordered 接口的 BeanFactoryPostProcessor, 排序并执行该方法
    • 拿到未实现 PriorityOrdered 和 Ordered 接口的 BeanFactoryPostProcessor, 排序并执行该方法

refresh - registerBeanPostProcessors

将 Spring 自带的和用户自定义的 BeanPostProcessor 实例化, 排序, 然后注册到 BeanFactory 的 beanPostProcessors 属性中, 供后续实例化 Bean 的时候使用

MergedBeanDefinitionPostProcessor 是 BeanPostProcessor 的子接口, 拥有合并 BeanDefinition 的能力, 实现了该接口的对象被认为是 Spring 内部的基础架构组件, 排序的时候会被额外处理, 放到队列的最末尾

大致流程

  • 从容器中获取所有 BeanPostProcessor, 自定义的也已经在上一步被扫描注册进入容器中了
  • 将实现了 PriorityOrdered 和 Ordered 的和未实现排序的区分开
  • 先把 PriorityOrdered 的实例化并排序并添加到 BeanFactory 的 beanPostProcessors 属性中
  • 再把 Ordered 的实例化并排序并添加到 BeanFactory 的 beanPostProcessors 属性中
  • 再把 未实现排序的添加到 BeanFactory 的 beanPostProcessors 属性中
  • 其中有一个小逻辑, 只要同时还实现了 MergedBeanDefinitionPostProcessor 接口的, 会额外存到另一个 list 中. 在最后给这个 list 排序, 并重新添加到 BeanFactory 的 beanPostProcessors 属性中
    • 重新添加会不会添加两次? 不会, 添加方法内部会先 remove 然后再 add, 添加两次的会先把前面的删掉, 重新添加到后面
    • CommonAnnotationBeanPostProcessor 和 AutowiredAnnotationBeanPostProcessor 同时实现了 PriorityOrdered 和 MergedBeanDefinitionPostProcessor. 在前面被添加, 在后面被重新添加, 相当于排到了后面, 且二者之间按照 PriorityOrdered 排序, Common 在 Autowired 前面
  • 然后在最后又重新添加了一次 ApplicationListenerDetector, 确保它在最末尾, 它也实现了 MergedBeanDefinitionPostProcessor

ConfigurationClassPostProcessor

解析配置类, 在下一篇文章里单说

ConfigurationClassPostProcessor 实现了 BeanDefinitionRegistryPostProcessor, 即同时拥有 postProcessBeanDefinitionRegistry 和 postProcessBeanFactory 两个方法, 会在 refresh 的 invokeBeanFactoryPostProcessor 阶段被调用, 且先调用 postProcessBeanDefinitionRegistry 再调用 postProcessBeanFactory

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值