Spring-bean的生命周期

本文详细阐述了SpringFramework6.0.9中Bean的生命周期,包括实例化策略(构造函数、工厂方法、FactoryBean),依赖注入方式(构造器、setter、field和方法注入),以及Aware接口和BeanPostProcessor在初始化和销毁阶段的作用。此外,还介绍了如何通过@PreDestroy、DisposableBean和destroy-method来定制Bean的销毁过程。
摘要由CSDN通过智能技术生成

版本 Spring Framework 6.0.9​

生命周期

Spring Bean的生命周期是指一个由Spring IoC容器管理的Java对象从创建到销毁所经历的一系列阶段。这个过程涉及了Bean的实例化、依赖注入、初始化、使用以及销毁等多个阶段。

  • 实例化
    • (1)调用InstantiationAwareBeanPostProcessor后置处理器,提前返回bean实例(如果有)
    • (2)createBeanInstance方法实例化bean
  • MergedBeanDefinitionPostProcessor后置处理器,对合并 Bean 定义进行后处理。(如果有)
  • 依赖注入(populateBean)
  • 初始化(initializeBean)
    • (1)处理Aware接口(BeanNameAware、BeanClassLoaderAware、BeanFactoryAware),
    • (2)Bean后置处理器的初始化前置处理。
    • (3)初始化方法回调
    • (4)bean后置处理器的初始化后置处理。
  • 使用
    • Bean已完成实例化、依赖注入和初始化,可以被应用程序中的其他组件通过Spring容器安全地使用。
  • 销毁
    • 调用DestructionAwareBeanPostProcessor 后置处理器,销毁前置处理。(如果有且与当前bean关联)
    • 执行DisposableBean接口的destroy方法(如果bean实现了该接口)
    • AutoCloseable接口的close方法或destroy-method方法(同时存在只调用destroy-method)

1. Bean的实例化

提供了多种实例化Bean的方式,其根本是调用适当的构造函数(默认无参构造函数或带有参数的构造函数,由依赖注入机制提供参数)来创建Bean的实例。

1.1 构造函数

Spring可以通过调用目标类的构造函数来创建Bean实例。根据构造函数参数的不同,有以下两种情况:

无参构造函数

如果Bean类有一个无参构造函数(默认构造函数),Spring容器会直接调用它来实例化Bean.。在这里插入图片描述

在配置文件中添加UserService的定义。
在这里插入图片描述

调用了UserService的无参构造函数
在这里插入图片描述
在这里插入图片描述

有参构造函数

如果有多个构造函数,Spring可以通过标签(在XML配置中)或@Autowired注解(在Java配置或类级别上)自动匹配合适的构造函数,并注入所需的依赖。

创建OrderService类,添加无参构造和有参构造
在这里插入图片描述

在配置文件中添加OrderService的定义。
在这里插入图片描述

从打印信息看出,调用了OrderService的有参构造函数
在这里插入图片描述

1.2 工厂方法

工厂方法模式允许通过工厂类创建目标Bean。Spring支持两种类型的工厂方法:

静态工厂

工厂类提供一个静态方法来创建Bean。在Spring配置中,使用factory-method属性指定该静态方法,并通过class属性指定工厂类。
在这里插入图片描述

创建工厂类,含有一个实例化OrderService的静态方法.
在这里插入图片描述

定义bean的xml配置.
在这里插入图片描述

先实例化了UserService,作为入参调用工厂类createInstance方法,实例化OrderService。
在这里插入图片描述

动态工厂

通过常规方式实例化一个工厂Bean,然后调用其非静态方法来创建目标Bean。配置时,除了指定factory-bean和factory-method属性外,还需定义工厂Bean本身。

添加OrderService工厂类的无参构造函数,打印一下信息
在这里插入图片描述

添加orderServiceFactory的xml配置,删除orderService的bean定义class配置,加上factory-bean配置指向OrderService工厂类的bean名称。
在这里插入图片描述

先实例化了UserService,然后实例化OrderServiceFactory,再讲UserService作为入参调用工厂类createInstance方法,实例化OrderService。
在这里插入图片描述

1.3 FactoryBean

通过让一个类实现 Spring 的 org.springframework.beans.factory.FactoryBean 接口,是Spring框架中一种特殊的Bean类型。当Spring容器请求这个FactoryBean时,它不会直接返回该FactoryBean实例本身,而是调用其getObject()方法来获取实际想要创建的Bean实例。

创建实现了FactoryBean接口的OrderServiceFactoryBean。
在这里插入图片描述

在配置文件中添加OrderServiceFactoryBean的定义
在这里插入图片描述

打印下bean名称为orderService的对象。
在

从打印信息看出,先实例化了OrderServiceFactoryBean,然后实例化UserService,再调用OrderServiceFactoryBean的getObject方法,实例化OrderService。最后通过getBean获取名称为OrderServcie的bean类型是OrderService,而不是OrderServiceFactoryBean。
在这里插入图片描述

动态工厂和FactoryBean区别

FactoryBean和动态工厂都在Spring中用于动态创建Bean,它们是两种不同的机制。动态工厂更接近于传统的工厂模式,而FactoryBean是Spring特有的接口,提供了更深度的集成和更丰富的功能。

  • 动态工厂:
    • 使用方式:在Spring配置文件中通过元素的factory-bean和factory-method属性指定工厂类和方法。
    • 创建逻辑:直接在工厂方法内编写创建Bean的代码,方法可以接收参数,返回目标Bean实例。
    • 作用范围:主要用于简单、一次性创建Bean的场景,或者需要根据运行时条件动态选择创建不同Bean的情况。
  • FactoryBean接口:
    • 使用方式:定义一个类实现FactoryBean接口,并实现getObject()、getObjectType()和isSingleton()等方法。
    • 创建逻辑:在getObject()方法中编写创建Bean的代码,可以返回原始类型、代理对象或其他复杂对象。
    • 作用范围:适用于需要更精细控制Bean创建过程、支持延迟初始化、提供代理或装饰等功能的场景,尤其适合于框架或库的集成,以及需要创建复杂对象结构的情况。

1.4 注解驱动

相较于xml的配置方式,注解驱动减少了单独的XML配置文件数量和大小、通过如@Autowired、@Resource、@Inject等简化了依赖注入,通过如@ComponentScan、@Configuration、@Service、@Repository、@Controller等减少重复配置,减轻了配置负担。配合Spring Boot等框架时,进一步减少了手动配置的工作量。注解驱动本质上上和上面提及实例化的方式大致一样,bean的定义从xml配置改成注解的配置方式。

通过注解实例化Bean主要有以下几种方式:

@Component及派生注

  • @Component是最基础的组件扫描注解,用于标记在Spring应用中任何需要被Spring管理的类。
  • 派生注解包括:
    • @Service:用于标记业务层(Service层)的类。
    • @Repository:用于标记数据访问层(DAO/Repository层)的类,通常与异常转换和事务处理有关。
    • @Controller:用于标记控制器层(MVC中的Controller层)的类,通常与Web请求处理相关

@Configuration类中的@Bean方法

  • @Configuration注解标记的类表示这是一个配置类,其中的方法使用@Bean注解来声明Bean。当Spring容器加载此类时,会调用这些方法来创建Bean实例。
  • @Bean方法的返回值将作为Bean的实例,方法名默认作为Bean的名称。可以在方法体内编写初始化逻辑,包括依赖注入和其他配置操作。

@Autowired构造函数

  • 可以在类的构造函数上使用@Autowired注解,指示Spring通过构造函数自动注入依赖。当Spring创建此类的Bean实例时,会自动寻找匹配的依赖Bean并注入到构造函数中。

2. 依赖注入

Spring提供了多种依赖注入(Dependency Injection, DI)的方式,使得Bean之间的依赖关系能够在运行时由Spring容器自动管理。

2.1 构造器注入

在Bean类的构造函数中声明需要注入的依赖作为参数,Spring容器在创建Bean实例时,会找到对应的依赖Bean并传递给构造函数。
在这里插入图片描述

2.2 方法注入

setter方法

在Bean类中定义setter方法,使用@Autowired注解,Spring容器通过调用这些方法将依赖注入到Bean中。
在这里插入图片描述

普通方法

除了构造函数和setter方法外,Spring还支持对普通方法进行依赖注入。使用@Autowired注解标记方法,Spring会在Bean创建后调用该方法并将所需的依赖作为参数传入。
在这里插入图片描述

普通方法注入和setter方法注入区别

普通方法注入和setter方法注入都是Spring框架中依赖注入方式,但它们在注入目的、时机有所不同:

  • 普通方法
    • 目的:主要用于在Bean实例化后执行特定的初始化逻辑,这些逻辑可能依赖于注入的外部资源或服务。
    • 时机:发生在Bean的生命周期中构造函数注入和setter方法注入之后,通常在@PostConstruct注解的方法之前。
  • setter方法
    • 为了设置Bean的属性值,使Bean能够持有对其它依赖Bean的引用。
    • 通常发生在Bean的构造函数注入之后,但在Bean生命周期的早期阶段。

2.3 字段注入

@Autowire

直接在Bean类的字段上使用注解(如@Autowired、@Resource等)声明依赖,Spring容器会自动将依赖注入到该字段。
在这里插入图片描述

@Value

用于注入基本类型、String或其他可序列化的值,可以从属性文件、环境变量等来源获取。
在这里插入图片描述

2.4 @Bean

@Bean注解用于在@Configuration类中定义一个Spring管理的Bean。它标记的方法将返回一个Bean实例,Spring容器会调用这个方法来创建Bean,并处理方法内部的依赖注入。

在这里插入图片描述

3. Bean的初始化

在这里插入图片描述

3.1 处理Aware接口

Aware接口是一系列以*Aware命名的接口,它们为Spring管理的Bean提供了获取Spring容器内部服务或相关信息的能力。当一个Bean实现了Aware接口,Spring容器在初始化该Bean的过程中会自动调用接口中定义的方法,注入相应的服务或信息

当bean实现了BeanNameAware、BeanClassLoaderAware、BeanFactoryAware接口,Spring在bean初始化方法AbstractAutowireCapableBeanFactory#initializeBean中,会自动调用接口中定义的方法,注入相应的服务或信息。

  • BeanNameAware:允许当前bean获取其bean定义中的名称
  • BeanClassLoaderAware:允许Bean获取到其所在ClassLoader(类加载器)的引用。
  • BeanFactoryAware:允许Bean获取到当前BeanFactory(Bean工厂)的引用。
    在这里插入图片描述

3.2 BeanPostProcessor的前置初始化

在初始化回调方法(如@PostConstruct,也是在一个BeanPostProcessor调用,只是优先级较低)执行之前,调用所有注册的BeanPostProcessor接口的实现类,通过其定义的postProcessBeforeInitialization完成初始化的前置操作。
在这里插入图片描述

ApplicationContextAwareProcessor

ApplicationContextAwareProcessor后置处理器也是处理Aware接口,该实例在refresh的prepareBeanFactory阶段注册到Bean工厂中,处理的Aware接口包含

  • EnvironmentAware:允许Bean获取到当前Spring环境中Environment对象的引用。
  • EmbeddedValueResolverAware:允许Bean获取到StringValueResolver对象的引用。StringValueResolver接口提供了解析嵌入在字符串中的占位符(如${…})的能力。
  • ResourceLoaderAware:允许Bean获取到当前ResourceLoader(资源加载器)的引用。
  • ApplicationEventPublisherAware:允许Bean获取到当前ApplicationContext中ApplicationEventPublisher(事件发布器)的引用。
  • MessageSourceAware:允许Bean获取到当前ApplicationContext中MessageSource(消息源)的引用
  • ApplicationStartupAware:允许Bean获取到当前ApplicationContext(应用上下文)的ApplicationStartup的(应用启动记录器)引用。
  • ApplicationContextAware:允许Bean获取到当前ApplicationContext(应用上下文)的引用。
    在这里插入图片描述

@PostConstruct

在 Spring Bean 类中的某个方法上添加 @PostConstruct 注解,在初始化回调方法之前调用。相较于实现InitializingBean接口或在xml配置文件中指定init-method,有更好的兼容性和更低的耦合度。通常建议优先使用 @PostConstruct 来处理 Bean 的初始化逻辑。

@PostConstruct由CommonAnnotationBeanPostProcessor后置处理器实现,
在调用CommonAnnotationBeanPostProcessor无参构造函数时,将jakarta.annotation.PostConstruct、javax.annotation.PostConstruct添加给其父类InitDestroyAnnotationBeanPostProcessor的initAnnotationTypes属性,用于
标注 @PostConstruct 的方法,在初始化前置处理时识别并调用它。
在这里插入图片描述
在这里插入图片描述

3.3 初始化方法

用于处理 Bean 的初始化逻辑。
在这里插入图片描述

InitializingBean

InitializingBean 是 Spring 框架中定义的一个接口,用于处理 Bean 的初始化逻辑。当一个类实现了 InitializingBean 接口时,Spring 容器在完成对其实例的依赖注入之后,会调用该接口定义的唯一方法 afterPropertiesSet()。
在这里插入图片描述

init-method

init-method 是 Spring 框架提供的另一种用于定义 Bean 初始化逻辑的机制,它允许在 Spring 配置文件(XML 或 Java 配置类)中指定一个方法名称,Spring 容器会在 Bean 实例化并完成依赖注入后调用该方法。

例子1
在这里插入图片描述

例子2
在这里插入图片描述

@PostConstruct、InitializingBean、init-method区别

  • 实现方式:
    • @PostConstruct:通过元注解直接标记在方法上。
    • InitializingBean:实现接口并实现 afterPropertiesSet() 方法。
    • init-method:在配置文件中显式指定方法名称。

三者都用于定义 Bean 初始化逻辑,但@PostConstruct相较于另外两种方式,更符合面向切面编程(AOP)的理念,使代码更加简洁和模块化,降低耦合度 。一般只有在无法使用注解或者有特殊需求的情况下,才考虑实现另外两种。

3.4 BeanPostProcessor的后置初始化

在初始化回调方法执行后,调用所有注册的BeanPostProcessor接口的实现类,通过其定义的postProcessAfterInitialization完成初始化的后置操作。
在这里插入图片描述

ApplicationListenerDetector

如果当前bean实现了ApplicationListener接口,并且是单例对象,Spring容器会将其注册作为事件监听器到bean工厂中,用于监听ApplicationEvent事件。
在这里插入图片描述

4. Bean的销毁

销毁阶段是指当一个 Bean 不再需要或者 Spring 容器关闭时,Spring 容器对 Bean 执行清理操作的阶段。如果bean配置了销毁流程,Spring容器会将该bean托管给DisposableBeanAdapter类,执行bean的销毁工作。

  • DisposableBeanAdapter适配器实现了DisposableBean接口,bean工厂在销毁阶段调用其destroy方法销毁bean。
  • DisposableBeanAdapter适配器会调用DestructionAwareBeanPostProcessor后置处理器的requiresDestruction方法,如果该后置处理器与当前bean销毁有关联,则将其缓存起来。
    在这里插入图片描述
    在这里插入图片描述

4.1 DestructionAwareBeanPostProcessor销毁前置处理

DestructionAwareBeanPostProcessor 是 Spring 框架中的一种特殊的 Bean 后处理器接口,继承自 BeanPostProcessor。它主要用来定制化 Bean 的销毁过程,允许在 Spring 容器销毁 Bean 之前或之后执行特定的操作。DestructionAwareBeanPostProcessor 提供了两个方法:

  • postProcessBeforeDestruction:销毁前置处理,在给定的 Bean 实例销毁之前将其应用于该实例,例如调用自定义销毁回调。
  • requiresDestruction:确定给定的 Bean 实例是否需要由此后处理器销毁。

在这里插入图片描述

@PreDestroy

@PreDestroy 是 Java 平台企业版(Java EE)规范中定义的一个注解,用于标记一个方法,该方法将在 Bean 被销毁前由容器自动调用。在 Spring 框架中,也支持 @PreDestroy 注解,并将其整合到 Spring Bean 的生命周期管理中。
@PreDestroy和@PostConStruct原理类似,CommonAnnotationBeanPostProcessor无参构造函数将jakarta.annotation.PreDestroy、javax.annotation.PreDestroy添加给其父类InitDestroyAnnotationBeanPostProcessor的destroyAnnotationTypes属性,用于
标注 @PreDestroy 的方法,并在DisposableBeanAdapter适配器执行destroy方法的销毁前置处理时,识别并调用它。
在这里插入图片描述

例子
在这里插入图片描述

4.2 DisposableBean

DisposableBean 是 Spring 框架中用于定义对象销毁行为的接口。当一个实现了 DisposableBean 的 Bean 被 Spring 容器管理并在其生命周期结束时,Spring 会调用其 destroy() 方法来进行资源清理等销毁操作。这是 Spring 提供的一种与 @PreDestroy 注解相类似的、用于定义 Bean 销毁逻辑的方式。
在这里插入图片描述

例子
在这里插入图片描述

4.3 destroy-method

destroy-method 是 Spring 框架中 标签的一个属性,用于指定当该 Bean 被 Spring 容器销毁时应调用的方法名。
在这里插入图片描述

例子1
在这里插入图片描述
例子2
在这里插入图片描述

4.4 AutoClose

,AutoCloseable 是 Java SE 7 提供的一个标准接口,用于支持资源的自动关闭。在 Spring 应用中,并不保证一定调用close方法(如果指定了destroy-method则不调用),AutoCloseable 主要用于业务代码层面的资源管理,而不是 Spring 容器管理的 Bean 的销毁逻辑。
在这里插入图片描述

  • 28
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值