bean加载过程
加载过程
- load BeanDefinition
- merge BeanDefinition(GenericBeanDefinition -》RootBeanDefinition)
- 不存在parent,直接创建RootBeanDefinition
- 存在parent,复制新的RootBeanDefinition,并且覆盖parent相关配置
- postProcessBeanFactory(覆盖org.springframework.context.support.AbstractApplicationContext#postProcessBeanFactory)
-
- 调用上下文本身的beanFactory后置处理方法
- invokeBeanFactoryPostProcessors(实现BeanFactoryPostProcessor扩展)
-
- 调用beanFactoryPostProcessors。
- 例如:在配置文件中使用占位符的方式来配置bean属性,解析由PropertyPlaceholderConfigurer实现。
- BeanDefinitionRegistryPostProcessor接口继承自BeanFactoryPostProcessor接口。
-
- 例如:mybatis的mapper接口无需写实现类,就是由MapperScannerConfigurer实现BeanDefinitionRegistryPostProcessor,扫描@Mapper注解修饰的接口,注册factoryBean为MapperFactoryBean的AnnotatedBeanDefinition,最终会创建MapperProxy对象。
- 调用beanFactoryPostProcessors。
- registerBeanPostProcessors(实现BeanPostProcessor扩展)
-
- 注册bean的后置处理器
- 国际化
- 初始化事件多播器
- 注册监听器
- 创建bean
- 执行InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation
- 实例化bean
- 将匿名BeanFactory添加至三级缓存
- 属性填充
- 循环依赖时,执行依赖对象在三级缓存中的BeanFactory,得到代理对象,但是被代理对象还未完成属性填充和初始化,将代理对象放入二级缓存
- 执行org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation
- 初始化bean
- 执行beanPostProcessor的beforeInitialization
- InitDestroyAnnotationBeanPostProcessor处理@PostConstruct
- 执行initializingBean#afterPropertiesSet()
- 例如:AOP事务管理用到的类,TransactionProxyFactoryBean 就是利用afterPropertiesSet方法事先把事务管理器 TransactionManager的代理类对象给生成好了,后面调用FactoryBean对象的getObject方法的时候,就直接把这个代理对象返回出去了。
- 执行init-method
- 执行beanPostProcessor的afterInitialization
- AnnotationAwareAspectJAutoProxyCreator继承AbstractAutoProxyCreator,处理Aspect注解,生成代理对象
- 此时被代理对象完成了初始化,是个完整对象,于是将代理对象放入一级缓存。
循环依赖
只能解决通过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)。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构