news 2026/1/14 9:39:57

day04-Spring之Bean的生命周期

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
day04-Spring之Bean的生命周期

前言:
Spring主要功能创建对象(俗称IOC),
Bean的生命周期流程图

1、生成BeanDefinition

spring启动会进行扫描执行如下方法
org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#scanCandidateComponents
Spring的扫描流程图

  • 根据ResourcePatternResolver 获取指定路径下所有的.class文件【最终生成 Resource 对象】
  • 遍历 Resource 集合
  • 利用MetadataReaderFactory 解析 Resource 获取metadateReader
  • 对metadataReader 进行 excludeFilters和 includeFilters ,
  • 若excludeFilters 匹配直接返回false,
  • 若 includeFiletes 匹配还要判断,是否有@Conditional ,如果有则需要判断@Conditional 注解筛选是否筛选过,不能筛选 直接false
  • 筛选通过后,还要判断
  • 是否独立、【不是接口或抽象】、如果是抽象,类上面是否添加@Lookup注解 【三个条件缺一不可】
  • 最终将 ScannedGenericBeanDefinition 生成BeanDefinition 对象返回

其中 @Conditional 的注解的作用
@Conditional 是 Spring 4.0 引入的核心注解,用于条件化地创建 Bean。它允许根据特定条件决定是否注册 Bean 到 Spring 容器中。

除了自定义条件,Spring 还提供了一些内置的条件注解,这些注解都是 @Conditional 的扩展,使用起来更加方便:

  • @ConditionalOnBean:当容器中存在指定 Bean 时。
  • @ConditionalOnMissingBean:当容器中不存在指定 Bean 时。
  • @ConditionalOnClass:当类路径中存在指定类时。
  • @ConditionalOnMissingClass:当类路径中不存在指定类时。
  • @ConditionalOnProperty:当指定的属性有指定的值时。
  • @ConditionalOnResource:当类路径中存在指定资源时。
  • @ConditionalOnWebApplication:当是 Web 应用时。
  • @ConditionalOnNotWebApplication:当不是 Web 应用时。
  • @ConditionalOnExpression:当 SpEL 表达式为 true 时。

@Conditional 注解 demo案例:
StuService Bean的创建 要依赖于 StuServiceCondition

@Component @Conditional(StuServiceCondition.class)public class StuService{publicvoidtest(){System.out.println("stu test ...");}}
import org.springframework.context.annotation.Condition;import org.springframework.context.annotation.ConditionContext;import org.springframework.core.type.AnnotatedTypeMetadata;public class StuServiceCondition implements Condition{@Override public booleanmatches(ConditionContext context,AnnotatedTypeMetadata metadata){// 检查某个属性是否存在returncontext.getEnvironment().containsProperty("stu.service.enabled");}}

这时获取bean 为stuService 找不到异常。
Exception in thread “main” org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named ‘stuService’ available…

MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
创建MetadataReader 注意点:
org.springframework.core.type.classreading.CachingMetadataReaderFactory#getMetadataReader
CachingMetadataReaderFactory解析某个.class文件得到 MetadataReader对象,利用的是ASM技术,并没有加载这个类到JVM。最终得到的ScannedGenericBeanDefinition对象,beanClass属性存储当前的类的名称,而不是class对象。

2、合并BeanDefinition

在通过BeanDefinition之后,就可以根据BeanDefinition创建Bean对象。在spring中支持父子BeanDefinition,和Java中继承相似
比如:
spring.xml

<bean id="parent"class="com.dx.service.Parent"scope="prototype"/><bean id="child"class="com.dx.service.Child"/>

测试:

AnnotationConfigApplicationContext applicationContext=newAnnotationConfigApplicationContext(AppConfig.class);XmlBeanDefinitionReader xmlBeanDefinitionReader=newXmlBeanDefinitionReader(applicationContext);xmlBeanDefinitionReader.loadBeanDefinitions("spring.xml");System.out.println(applicationContext.getBean("child"));System.out.println(applicationContext.getBean("child"));System.out.println(applicationContext.getBean("child"));

测试结果:
com.dx.service.Child@ef9296d
com.dx.service.Child@ef9296d
com.dx.service.Child@ef9296d
如果将xml修改为:

<bean id="parent"class="com.dx.service.Parent"scope="prototype"/><bean id="child"class="com.dx.service.Child"parent="parent"/>

测试的结果是
com.dx.service.Child@ef9296d
com.dx.service.Child@36c88a32
com.dx.service.Child@7880cdf3
child可以继承parent的 scope,

  • 子如果有scope 则使用自己的
  • 子没有scope,继承父类scope,父类若没有scope有parent的属性,同样的继承逻辑
    源码的大概如下:
  • 根据beanName判断是否合并过,合并过直接退出
  • 判断当前的bean是否有父类,
  • 如果没有设置 当前bean为RootBeanDefinition
  • 如果有循环获取 bean的父bean
  • 覆盖父定义属性(子覆盖父)
protected RootBeanDefinitiongetMergedBeanDefinition(String beanName,BeanDefinition bd,@Nullable BeanDefinition containingBd)throws BeanDefinitionStoreException{synchronized(this.mergedBeanDefinitions){// 1. 检查是否已经合并过RootBeanDefinition mbd=this.mergedBeanDefinitions.get(beanName);if(mbd==null){// 2. 如果没有父定义,直接转换为RootBeanDefinitionif(bd.getParentName()==null){mbd=newRootBeanDefinition(bd);}else{// 3. 递归合并父定义BeanDefinition pbd;try{String parentBeanName=transformedBeanName(bd.getParentName());pbd=getMergedBeanDefinition(parentBeanName);}// ...// 4. 深度拷贝父定义mbd=newRootBeanDefinition(pbd);// 5. 覆盖父定义属性(子覆盖父)mbd.overrideFrom(bd);}// 6. 缓存合并结果this.mergedBeanDefinitions.put(beanName,mbd);}returnmbd;}}

3、加载类

BeanDefinition合并之后,就可以创建Bean的对象执行的方法是
org.springframework.beans.factory.support.AbstractBeanFactory#resolveBeanClass
创建bean就必须实例化对象,实例化要先加载类所对应class

Class<?>resolvedClass=resolveBeanClass(mbd,beanName);

方法的主要实现是:

// 如果是beanClass就直接返回if(mbd.hasBeanClass()){returnmbd.getBeanClass();}// 如果beanClass没有被加载,会根据doResolveBeanClassif(System.getSecurityManager()!=null){returnAccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>)()->doResolveBeanClass(mbd,typesToMatch),getAccessControlContext());}else{returndoResolveBeanClass(mbd,typesToMatch);}

如果beanClass 属性的类型是Class 直接返回,不是则根据类名加载(doResolveBeanClass(mbd, typesToMatch))
会利用BeanFactory所设置的类加载器加载类,如果没有设置,则默认使用ClassUtils.getDefaultClassLoader()类加载
ClassUtils.getDefaultClassLoader()类加载方法:

  • 优先获取当前线程的类加载器
  • 当前线程类加载为空,返回ClassUtils.class.getClassLoader()
  • 如果ClassUtils.class.getClassLoader() 也为空,则ClassLoader.getSystemClassLoader()

4、实例化前

BeanDefinition 对应的类加载成功后,实例化对象前 Spring提供一个扩展点允许某个对象、某些对象实例化前做些额外的工作
org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation

import com.zhouyu.service.StuService;import org.springframework.beans.BeansException;import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;import org.springframework.stereotype.Component;@Component public class DxBeanPostProcessor implements InstantiationAwareBeanPostProcessor{@Override public ObjectpostProcessBeforeInstantiation(Class<?>beanClass,String beanName)throws BeansException{if("stuService".equals(beanName)){System.out.println("加载 stuService 初始化之前");// Spring将直接使用这个对象returnnewStuService();}// 返回null则走正常流程returnnull;}}

InstantiationAwareBeanPostProcessor 的
postProcessBeforeInstantiation 除了常见的创建代理对象外,还有以下重要作用:
1,完全绕过spring的生命周期

@Override public ObjectpostProcessBeforeInstantiation(Class<?>beanClass,String beanName){// 如果返回非null对象,Spring将:// 1. 跳过默认构造函数调用// 2. 跳过后置处理器链的后续处理// 3. 跳过属性注入if(beanName.equals("specialBean")){returnnewSpecialBean();// Spring将直接使用这个对象}returnnull;// 返回null则走正常流程}

2、根据条件Bean创建

@Override public ObjectpostProcessBeforeInstantiation(Class<?>beanClass,String beanName){// 根据条件决定是否创建Beanif(shouldSkipCreation(beanClass,beanName)){returnnewNoOpBean();// 返回一个占位对象}// 根据环境变量/配置决定实现类if(beanClass.isAssignableFrom(Service.class)){returnisProduction()?newProductionService():newMockService();}returnnull;}

3、对象池/缓存管理

@Override public ObjectpostProcessBeforeInstantiation(Class<?>beanClass,String beanName){if(beanClass.isAnnotationPresent(Poolable.class)){// 从对象池获取实例,而不是新建Object pooledInstance=objectPool.acquire(beanClass);if(pooledInstance!=null){returnpooledInstance;// 返回池中对象}}returnnull;}

4、性能优化场景

@Override public ObjectpostProcessBeforeInstantiation(Class<?>beanClass,String beanName){// 对于频繁创建的原型Bean,使用对象复用策略if(isHighFrequencyPrototype(beanClass)){returnprototypeReuseStrategy.createOrReuse(beanClass);}// 对于已知的无状态Bean,直接返回共享实例if(isStateless(beanClass)){returngetSharedInstance(beanClass);}returnnull;}

postProcessBeforeInstantiation 使用注意点
1、跳过正常的生命周期 :返回null 会跳过

  • postProcessAfterInstantiation
  • 属性注入 (populateBean)
  • 初始化回调 (afterPropertiesSet, init-method)
  • postProcessBeforeInitialization
  • postProcessAfterInitialization
    2、需要手动处理依赖
@Override public ObjectpostProcessBeforeInstantiation(Class<?>beanClass,String beanName){MyBean bean=newMyBean();// 需要手动注入依赖bean.setDependency(manualLookup());// 手动调用初始化bean.init();returnbean;}

3、与 AOP 的协调:如果在此创建代理,需要确保与其他 AOP 配置协调一致

5、实例化

会根据 BeanDefinition 创建一个对象。

5.1 Supplier创建对象
判断Beandefinition 中是否设置Supplier,如果设置了 则调用Supplier的get() 设置 Supplier

AnnotationConfigApplicationContext applicationContext=newAnnotationConfigApplicationContext(AppConfig.class);GenericBeanDefinition beanDefinition=newGenericBeanDefinition();beanDefinition.setBeanClass(Person.class);// 设置 supplierbeanDefinition.setInstanceSupplier(new Supplier<Object>(){@Override public Objectget(){// 这里可以编写创建逻辑Person person=newPerson();person.setAge(18);person.setName("张三");returnperson;}});// 注册beanapplicationContext.registerBeanDefinition("person",beanDefinition);System.out.println(applicationContext.getBean("person"));======执行结果=====Person{age=18,name='张三'}

Supplier 基础概念和作用
1,Supplier 是什么
是 Java 8 引入的函数式接口,表示一个结果的提供者:

@FunctionalInterface public interface Supplier<T>{/** * Gets a result. * * @return a result */Tget();}

1.2 在Spring中作用:
1.延迟实例化:将 Bean 的创建逻辑封装起来,按需调用
2.灵活性:允许运行时动态决定如何创建 Bean
3.与 BeanDefinition 解耦:将创建逻辑从 BeanDefinition 中分离

2、工厂方法创建对象
如果没有设置Supplier,检查是否BeanDefinition中是否设置 factory-method
sprin.xml

<bean id="stuService"class="com.zhouyu.service.StuService"factory-method="createStuServiceFactory"/>
public class StuService{publicstaticStuServicecreateStuServiceFactory(){System.out.println("this StuService createFactory");returnnewStuService();}publicvoidtest(){System.out.println("stu test ...");}}
AnnotationConfigApplicationContext applicationContext=newAnnotationConfigApplicationContext(AppConfig.class);newXmlBeanDefinitionReader(applicationContext).loadBeanDefinitions("spring.xml");System.out.println(applicationContext.getBean("stuService"));

3、推断方法 @Lookup注解

import org.springframework.stereotype.Component;@Component public class StuService{publicvoidtest(){System.out.println("stu test ...");}}
创建一个Spring容器 AnnotationConfigApplicationContext applicationContext=newAnnotationConfigApplicationContext(AppConfig.class);StuService stuService=(StuService)applicationContext.getBean("stuService");stuService.test();

执行结果
stu test …

测试@Conditional注解

import org.springframework.context.annotation.Conditional;import org.springframework.stereotype.Component;@Component @Conditional(StuServiceCondition.class)public class StuService{publicvoidtest(){System.out.println("stu test ...");}}
import org.springframework.context.annotation.Condition;import org.springframework.context.annotation.ConditionContext;import org.springframework.core.type.AnnotatedTypeMetadata;public class StuServiceCondition implements Condition{@Override public booleanmatches(ConditionContext context,AnnotatedTypeMetadata metadata){// 检查某个属性是否存在returncontext.getEnvironment().containsProperty("stu.service.enabled");}}

执行结果报:
Exception in thread “main” org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named ‘stuService’ available…

6、BeanDefinition的后置处理器

比如Spring中使用

@Component public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor,MergedBeanDefinitionPostProcessor,PriorityOrdered,BeanFactoryAware{@Override publicvoidpostProcessMergedBeanDefinition(RootBeanDefinition beanDefinition,Class<?>beanType,String beanName){System.out.println(" AutowiredAnnotationBeanPostProcessor postProcessMergedBeanDefinition method ");}}

7、实例化后

postProcessAfterInstantiation 作用

  • 在Bean的实例化后、属性注入前执行
  • 可以返回false阻止Spring对该Bean进行属性注入
  • 适合用于自定义初始化逻辑或条件判断
    典型应用场景:
  • 动态控制属性注入
  • 实现延迟注入
  • 属性值验证和转换
  • 特殊Bean的预处理
    属性填充案例:
@Component public class DxInstanceAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor{@Override public booleanpostProcessAfterInstantiation(Object bean,String beanName)throws BeansException{if("stuService".equals(beanName)){PerSon perSon=newPerSon();perSon.setAge(12);perSon.setName("张三");System.out.println(perSon);}returntrue;}}

8、自动注入

9、处理属性

InstantiationAwareBeanPostProcessor.postProcessProperties() 是Spring框架中一个非常重要的扩展点,它在Bean的生命周期中扮演着关键角色。
主要作用包括:
1.处理注解驱动的依赖注入:例如,@Autowired、@Value、@Inject、@Resource等注解的解析和注入。
2.属性值的后处理:可以对属性值进行转换、验证、加密/解密等操作。
3.动态添加属性:根据某些条件动态添加属性。
4.跳过某些属性的注入:通过返回null或修改PropertyValues来控制哪些属性需要注入。
比如Spring内置实现
AutowiredAnnotationBeanPostProcessor

// 主要职责:处理 @Autowired、@Value、@Inject 注解public class AutowiredAnnotationBeanPostProcessor{@Override public PropertyValuespostProcessProperties(PropertyValues pvs,Object bean,String beanName){// 1. 获取或构建注入元数据InjectionMetadata metadata=findAutowiringMetadata(beanName,bean.getClass(),pvs);try{// 2. 执行实际的注入操作metadata.inject(bean,beanName,pvs);}catch(Throwable ex){throw newBeanCreationException(beanName,"Injection failed",ex);}// 3. 返回可能被修改的 PropertyValuesreturnpvs;}privatevoidinject(Object bean,@Nullable String beanName,@Nullable PropertyValues pvs){// 字段注入for(AutowiredFieldElement field:this.autowiredFields){field.inject(bean,beanName,pvs);}// 方法注入for(AutowiredMethodElement method:this.autowiredMethods){method.inject(bean,beanName,pvs);}}}

注解解析
处理各种依赖注入注解属性处理
修改、添加、删除属性值值转换
类型转换、占位符解析、SpEL计算
条件控制:根据条件决定是否注入某些属性
验证检查:属性值验证和约束检查

10、执行Aware

1.获取Bean在容器中的名称:通过实现BeanNameAware接口,Bean可以知道自己在容器中配置的名称。
2.获取BeanFactory:通过实现BeanFactoryAware接口,Bean可以获取到BeanFactory,从而可以手动获取其他Bean,或者进行一些高级操作。
3.获取ApplicationContext:通过实现ApplicationContextAware接口,Bean可以获取到ApplicationContext,从而可以访问容器上下文,例如获取其他Bean、发布事件、访问环境变量等。
4.获取环境配置:通过实现EnvironmentAware接口,Bean可以获取到Environment对象,从而可以访问配置属性、profiles等。
5.资源加载:通过实现ResourceLoaderAware接口,Bean可以获取到ResourceLoader,从而可以加载类路径或文件系统中的资源。
6.国际化:通过实现MessageSourceAware接口,Bean可以获取到MessageSource,从而可以进行国际化消息的解析。
7.应用事件发布:通过实现ApplicationEventPublisherAware接口,Bean可以获取到ApplicationEventPublisher,从而可以发布应用事件。
8.嵌入式值解析:通过实现EmbeddedValueResolverAware接口,Bean可以获取到StringValueResolver,从而可以解析嵌入式值(例如SpEL表达式)。

使用 Aware 的场景清单

import org.springframework.beans.factory.BeanClassLoaderAware;import org.springframework.beans.factory.BeanNameAware;import org.springframework.stereotype.Component;@Component public class BeanIdentityService implements BeanNameAware,BeanClassLoaderAware{private String beanName;private ClassLoader classLoader;@Override publicvoidsetBeanClassLoader(ClassLoader classLoader){this.classLoader=classLoader;System.out.println("current classLoader :"+classLoader);}@Override publicvoidsetBeanName(String name){// 场景:日志记录、监控、动态配置this.beanName=beanName;System.out.println("current bean name :"+beanName);}}

11、初始化前

BeanPostProcessor.postProcessBeforeInitialization()

import org.springframework.beans.BeansException;import org.springframework.beans.factory.config.BeanPostProcessor;import org.springframework.stereotype.Component;@Component public class DxPostProcessor implements BeanPostProcessor{@Override public ObjectpostProcessBeforeInitialization(Object bean,String beanName)throws BeansException{if("stuService".equals(beanName)){System.out.println("初始化之前");}returnbean;}}

12、初始化

// 1. @PostConstruct 注解方法@PostConstruct publicvoidinitMethod1(){// JSR-250 标准,最先执行}// 2. InitializingBean 接口的 afterPropertiesSet 方法@Override publicvoidafterPropertiesSet()throws Exception{// Spring 接口方式,第二执行}// 3. XML/@Bean 配置的 init-method// XML: <bean id="demo" class="com.xx.xx.Demo" init-method="customInit"/>// @Bean: @Bean(initMethod = "customInit")publicvoidcustomInit(){// 自定义方法,最后执行}

13、初始化后

这个是bean创建的生命周期最后一步。

import org.springframework.beans.BeansException;import org.springframework.beans.factory.config.BeanPostProcessor;import org.springframework.stereotype.Component;@Component public class DxPostProcessor implements BeanPostProcessor{@Override public ObjectpostProcessAfterInitialization(Object bean,String beanName)throws BeansException{if("stuService".equals(beanName)){System.out.println("初始化之后");}returnbean;}}
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2025/12/17 3:35:03

LobeChat市场需求变化预测

LobeChat&#xff1a;如何重塑下一代开源AI交互界面&#xff1f; 在生成式AI席卷全球的今天&#xff0c;人们早已不再惊讶于一个模型能写出诗歌或解答数学题。真正的挑战在于——如何让这些强大的能力真正被“人”所用&#xff1f; OpenAI 的 ChatGPT 带来了惊艳的对话体验&…

作者头像 李华
网站建设 2025/12/17 3:34:23

LobeChat回滚预案自动生成

LobeChat回滚预案自动生成 在AI应用快速迭代的今天&#xff0c;一次看似微小的配置更新&#xff0c;可能引发连锁反应&#xff1a;用户对话中断、插件失效、响应延迟飙升。某企业运维团队曾因升级LobeChat后未及时备份数据库&#xff0c;导致上千条客户会话记录丢失&#xff0c…

作者头像 李华
网站建设 2025/12/23 12:58:43

1、量子计算与供应链管理:优化新时代

量子计算与供应链管理:优化新时代 1. 量子计算与供应链优化基础 量子计算在供应链优化中展现出巨大潜力。传统优化方法在处理大规模供应链结构时,难以高效分析所有变量。而量子计算的基本原理,如叠加、纠缠和量子门等,为供应链活动提供了新的解决方案。以下是量子计算在供…

作者头像 李华
网站建设 2025/12/27 12:13:51

3、量子计算助力供应链优化:原理、算法与应用

量子计算助力供应链优化:原理、算法与应用 1. 量子计算简介 量子计算已取得显著进展,能够推动包括供应链在内的多个行业的变革。它以物理学的数学原理为基础,与传统计算机截然不同。量子计算的起源可追溯到一些杰出科学家的突破性想法,如理查德费曼(Richard Feynman)在…

作者头像 李华
网站建设 2025/12/17 3:33:58

20、量子供应链中的伦理与安全:保障运营完整性的关键

量子供应链中的伦理与安全:保障运营完整性的关键 1. 量子伦理概述 在科技驱动的时代,量子计算融入供应链管理成为关键领域,它能显著提升供应链效率与优化程度。量子算法可解决传统供应链难以攻克的优化问题,应用广泛,涵盖库存管理、路线优化、需求预测和风险降低等方面。…

作者头像 李华