随笔 - 171  文章 - 0  评论 - 0  阅读 - 62466

bean加载过程

加载过程

  1. load BeanDefinition
  2. merge BeanDefinition(GenericBeanDefinition -》RootBeanDefinition)
    1. 不存在parent,直接创建RootBeanDefinition
    2. 存在parent,复制新的RootBeanDefinition,并且覆盖parent相关配置
  3. postProcessBeanFactory(覆盖org.springframework.context.support.AbstractApplicationContext#postProcessBeanFactory)
    •   调用上下文本身的beanFactory后置处理方法
  1. invokeBeanFactoryPostProcessors(实现BeanFactoryPostProcessor扩展)
    •   调用beanFactoryPostProcessors。
      •   例如:在配置文件中使用占位符的方式来配置bean属性,解析由PropertyPlaceholderConfigurer实现。
    •   BeanDefinitionRegistryPostProcessor接口继承自BeanFactoryPostProcessor接口。
      •   例如:mybatis的mapper接口无需写实现类,就是由MapperScannerConfigurer实现BeanDefinitionRegistryPostProcessor,扫描@Mapper注解修饰的接口,注册factoryBean为MapperFactoryBean的AnnotatedBeanDefinition,最终会创建MapperProxy对象。
  1. registerBeanPostProcessors(实现BeanPostProcessor扩展)
    •   注册bean的后置处理器
  1. 国际化
  2. 初始化事件多播器
  3. 注册监听器
  4. 创建bean
    1. 执行InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation
    2. 实例化bean
    3. 将匿名BeanFactory添加至三级缓存
    4. 属性填充
      1. 循环依赖时,执行依赖对象在三级缓存中的BeanFactory,得到代理对象,但是被代理对象还未完成属性填充和初始化,将代理对象放入二级缓存
    5. 执行org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation
    6. 初始化bean
    7. 执行beanPostProcessor的beforeInitialization
      1. InitDestroyAnnotationBeanPostProcessor处理@PostConstruct
    8. 执行initializingBean#afterPropertiesSet()
      1. 例如:AOP事务管理用到的类,TransactionProxyFactoryBean 就是利用afterPropertiesSet方法事先把事务管理器 TransactionManager的代理类对象给生成好了,后面调用FactoryBean对象的getObject方法的时候,就直接把这个代理对象返回出去了。
    9. 执行init-method
    10. 执行beanPostProcessor的afterInitialization
      1. AnnotationAwareAspectJAutoProxyCreator继承AbstractAutoProxyCreator,处理Aspect注解,生成代理对象
    11. 此时被代理对象完成了初始化,是个完整对象,于是将代理对象放入一级缓存。

循环依赖

只能解决通过setter方法进行依赖注入且是在单例模式下产生的循环依赖问题。

通过三级缓存来解决循环依赖。

流程

核心代码

一级缓存:Map<String, Object> singletonObjects

第一级缓存的作用?

  • 用于存储单例模式下创建的Bean实例(已经创建完毕)。

  • 该缓存是对外使用的,指的就是使用Spring框架的程序员。

存储什么数据?

  • K:bean的名称。

  • V:bean的实例对象(有代理对象则指的是代理对象,已经创建完毕)。

第二级缓存:Map<String, Object> earlySingletonObjects

第二级缓存的作用?

  • 用于存储单例模式下创建的Bean实例(该Bean被提前暴露的引用,该Bean还在创建中)。

  • 该缓存是对内使用的,指的就是Spring框架内部逻辑使用该缓存。

  • 为了解决第一个A引用最终如何替换为代理对象的问题(如果有代理对象)。

存储什么数据?

  • K:bean的名称。

  • V:bean的实例对象(有代理对象则指的是代理对象,该Bean还在创建中)。

第三级缓存:Map<String, ObjectFactory<?>> singletonFactories

第三级缓存的作用?

  • 通过ObjectFactory对象来存储单例模式下提前暴露的Bean实例的引用(正在创建中)。

  • 该缓存是对内使用的,指的就是Spring框架内部逻辑使用该缓存。

  • 此缓存是解决循环依赖最大的功臣。

存储什么数据?

  • K:bean的名称。

  • V:ObjectFactory,该对象持有提前暴露的bean的引用。

 bean销毁时机

org.springframework.context.ConfigurableApplicationContext#close上下文关闭时,会进行bean的销毁org.springframework.context.support.AbstractApplicationContext#destroyBeans
Bean的生命周期中,在完成了Bean的创建之后,会注册Bean销毁的逻辑 。在注册Bean销毁逻辑时,首先需要通过!mbd.isPrototype()保证该Bean不是原型Bean,因为Spring容器并不会缓存原型Bean,就没有销毁一说。
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
     …… 
    registerDisposableBeanIfNecessary(beanName, bean, mbd); 
     …… 
}
如果bean指定了destroyMethod,或者实现DisposableBean接口,重写destroy方法或者注解@PreDestroy,销毁前做一些逻辑。
配置优先级:@preDestroy > DisposableBean > destoryMethod(xml注解或者@Bean)。
posted on   zhengbiyu  阅读(37)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示