Spring IoC 容器加载流程简述

博文目录


IoC容器加载流程

IoC容器加载流程可以分成两个步骤

  • 将配置的各种 Bean 解析成为 BeanDefinition
  • 遍历 BeanDefinition, 生产单例, 并缓存起来

注解形式的IoC容器加载流程

// 常见的写法, 其实AnnotationConfigApplicationContext还有一个传入basePackages的构造函数
// 如果传入的是包路径, 则通过BeanDefinitionScanner扫描, 找到候选组件将其封装成为BeanDefinition, 注册到容器
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
Object bean = context.getBean("demo");
System.out.println(bean);

准备工作

初始化 AnnotationConfigApplicationContext 的时候, 会预先注册几个底层基础架构工具类, 他们以后置处理器的形式被注册, 在容器初始化流程中发光发热. 然后再注册配置类, 然后才是刷新容器

这些工具类中有两个非常重要

  • ConfigurationClassPostProcessor: 配置类解析器, 负责解析配置类, 主要是解析配置类上的 @PropertySource, @ComponentScan, @Import, @ImportSelector 注解以及配置类中由 @Bean 注解标注的方法. 解析 @ComponentScan 的时候会扫描其指定的 basePackages 路径, 将标注有 @Component (@Repository, @Service, @Controller, @RestController 等含有 @Component 元注解, 也会被扫描到), @ManagedBean, @Named 注解的类也解析到
  • AutowiredAnnotationBeanPostProcessor: 注解注入解析器, 负责解析 @Autowired

将配置的各种 Bean 解析成为 BeanDefinition

调用 refresh 的 invokeBeanFactoryPostProcessors 方法, 将自动或手动注册的各种 BeanFactoryPostProcessors (包括 BeanDefinitionRegistryPostProcessor) 按一定的顺序规则逐个调用其 postProcessBeanDefinitionRegistry 和 postProcessBeanFactory 方法

这里其实主要就是工具类 ConfigurationClassPostProcessor 在发光发热, 它解析到目前为止容器中所有 BeanDefinition 中的配置类, 将相关的组件候选全都注册成为 BeanDefinition

遍历 BeanDefinition, 生产单例, 并缓存起来

调用 refresh 的 finishBeanFactoryInitialization 方法, 遍历 beanNames, 拿到对应 beanName 的 BeanDefinition, 符合生产条件(非抽象&是单例&非懒加载)的都调用 getBean(beanName) 来生产 Bean, 并缓存到一级缓存(单例池)中

Bean 生产步骤

Bean 的创建可以分为三个步骤

  • 实例化: 就是通过工厂(@Bean)或反射(无参反射, 有参构造函数反射)等完成 Bean 从无到有的第一步. ObjectBean 是不是在这里生效?
  • 填充属性: Bean 如果有 @Autowired / @Value 注解标注的属性, 则需要做自动填充, 主要由 AutowiredAnnotationBeanPostProcessor 来完成
  • 初始化: 调用各种 Aware 的相关属性注入方法, BeanPostProcessor 的 postProcessBeforeInitialization 方法 (包括 @PostConstruct 指定的初始化方法), InitializingBean 的 afterPropertiesSet 方法, 自定义的 init-method 方法, BeanPostProcessor 的 postProcessAfterInitialization 方法

生产完成之后, 将该 Bean 缓存到一级缓存(单例池)中

Bean 的生命周期接口调用

BeanFactory 的实现应该尽可能支持标准 Bean 生命周期接口. 全套初始化方法及其标准顺序如下

  • BeanNameAware 的 setBeanName
  • BeanClassLoaderAware 的 setBeanClassLoader
  • BeanFactoryAware 的 setBeanFactory
  • EnvironmentAware 的 setEnvironment
  • EmbeddedValueResolverAware 的 setEmbeddedValueResolver
  • ResourceLoaderAware 的 setResourceLoader (仅在 Application Context 中适用)
  • ApplicationEventPublisherAware 的 setApplicationEventPublisher (仅在 Application Context 中适用)
  • MessageSourceAware 的 setMessageSource (仅在 Application Context 中适用)
  • ApplicationContextAware 的 setApplicationContext (仅在 Application Context 中适用)
  • ServletContextAware 的 setServletContext (仅在 Web Application Context 中适用) (ServletContext 可能是指在 Servlet 容器中运行的每一个应用)
  • BeanPostProcessors 的 postProcessBeforeInitialization, 其中包括 @PostConstruct 的处理与标注方法的调用
  • InitializingBean 的 afterPropertiesSet
  • 自定义的 init-method 方法
  • BeanPostProcessors 的 postProcessAfterInitialization

BeanNameAware, BeanClassLoaderAware, BeanFactoryAware 是在 Bean 初始化方法 initializeBean 里面调用的

EnvironmentAware, EmbeddedValueResolverAware, ResourceLoaderAware, ApplicationEventPublisherAware, MessageSourceAware, ApplicationContextAware 是在 ApplicationContextAwareProcessor 这个 BeanPostProcessor 里面的 postProcessBeforeInitiolization 方法调用的

// 在 BeanPostProcessors 的 postProcessBeforeInitialization 中, InitDestroyAnnotationBeanPostProcessor会处理 @PostConstruct 注解, 会调用被该注解标注的方法, CommonAnnotationBeanPostProcessor 是 reader 注册的创世纪处理器之一
class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBeanPostProcessor

到这一步, bean已经生产好了, 它们将一直驻留在 ApplicatonContext 中, 直到该 ApplicatonContext 被销毁

在关闭 BeanFactory 时, 以下生命周期方法适用

  • DestructionAwareBeanPostProcessors 的 postProcessBeforeDestruction, 其中包括 @PreDestroy 的处理与标注方法的调用
  • DisposableBean 的 destroy
  • 自定义的 destroy-method 方法

Spring扩展接口和调用时机

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值