请你谈谈:spring bean的生命周期 - 阶段3:属性赋值(设置属性)

2024/07/17 22:17 : 两天内完成,敬请期待!!!

Spring属性赋值阶段是Spring Bean生命周期中的一个重要阶段,它紧随Bean的实例化之后。在这个阶段,Spring容器会根据BeanDefinition中定义的属性配置,将属性值注入到Bean实例中。这个过程可以细分为三个小阶段,下面将逐一进行介绍:

一、Bean实例化后阶段(Bean属性赋值前处理)

在Bean实例化之后,但在正式进行属性赋值之前,Spring会提供一个机会给InstantiationAwareBeanPostProcessor接口的实现类,通过调用其postProcessAfterInstantiation方法来进行一些预处理工作。这个方法的调用逻辑是:

  • 遍历所有的BeanPostProcessor实现类。
  • 如果某个BeanPostProcessor实现了InstantiationAwareBeanPostProcessor接口,则调用其postProcessAfterInstantiation方法。
  • 如果该方法返回false,则表示不需要继续对该Bean进行后续的属性赋值和初始化操作;如果返回true,则继续。

这个阶段的主要目的是在属性赋值之前,允许对Bean实例进行一些定制化的处理,比如检查Bean的某些属性是否满足特定条件,或者修改Bean的某些状态等。

示例说明

以下是一个包含User类和CustomBeanPostProcessor实现的完整例子,其中CustomBeanPostProcessor重写了postProcessAfterInstantiation方法,并在Spring容器实例化User Bean时输出一条消息。为了简化,我们将使用Spring Boot的自动配置和@Component注解来注册Bean。

首先,是User类的定义:

public class User {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}public User() {}// 构造函数、getter和setter省略,但实际应用中应该包含@Overridepublic String toString() {return "User{name='" + name + "'}";}
}

注意:为了简化,User类只包含了一个name属性,并且省略了构造函数、getter和setter方法。在实际应用中,你应该包含这些方法来完整地管理类的状态。

接下来是CustomBeanPostProcessor的实现:

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;public class CustomBeanPostProcessor implements InstantiationAwareBeanPostProcessor {@Overridepublic boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {// 检查bean是否是User类的实例if (bean instanceof User) {// 输出一条消息,表示User Bean已被实例化System.out.println("User Bean实例化后处理,beanName: " + beanName);((User) bean).setName("zhaoshuai-lc - enhance");// 返回true表示继续后续的属性赋值和初始化return true;}// 对于非User类型的bean,默认返回truereturn true;}// 注意:这里省略了其他未重写的方法,因为它们对于本例来说不是必需的
}

最后,我们需要一个Spring Boot的主类来启动应用程序,并注册UserCustomBeanPostProcessor作为Bean:

import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class AppConfig {@Beanpublic User user() {return new User(); // 注意:在实际应用中,通常不需要手动new User,而是通过@Component或@Bean的自动装配来管理}@Beanpublic CustomBeanPostProcessor customBeanPostProcessor() {return new CustomBeanPostProcessor();}
}
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class Main {  public static void main(String[] args) {  ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);User user = context.getBean("user", User.class);System.out.println(user.getName());}
}
User Bean实例化后处理,beanName: user
zhaoshuai-lc - enhance

如下内容未整理,下班之后整理!!!!

二、Bean属性赋值

在完成了属性赋值前的预处理之后,Spring会正式进入属性赋值阶段。这个阶段的主要工作是:

  • 获取BeanDefinition中定义的属性配置(即PropertyValues)。
  • 遍历这些属性配置,通过反射调用Bean实例的setter方法,将属性值注入到Bean实例中。

如果Bean的依赖注入类型是byNamebyType,Spring还会在属性赋值之前进行自动装配,即根据Bean名称或类型自动查找并注入依赖的Bean。

三、InstantiationAwareBeanPostProcessor属性赋值后回调

在属性赋值完成之后,Spring还会再次提供一个机会给InstantiationAwareBeanPostProcessor接口的实现类,通过调用其postProcessPropertiespostProcessPropertyValues方法来进行一些后处理工作。这个阶段的目的是在属性赋值之后,允许对Bean实例的属性值进行进一步的定制化处理,比如修改属性值、添加额外的属性等。

总结

Spring属性赋值阶段包括三个小阶段:Bean实例化后阶段(Bean属性赋值前处理)、Bean属性赋值、InstantiationAwareBeanPostProcessor属性赋值后回调。这三个阶段共同构成了Spring Bean属性赋值的完整流程,确保了Bean实例能够按照BeanDefinition中的定义被正确地初始化和配置。

需要注意的是,以上描述是基于Spring框架的一般行为,具体实现可能会因Spring版本的不同而有所差异。因此,在实际开发中,建议参考具体版本的Spring文档或源码来获取最准确的信息。

针对Spring属性赋值阶段的三个小阶段,我将分别给出举例说明。请注意,由于具体的代码实现可能因Spring版本和具体项目的不同而有所差异,以下示例将基于一般性的理解和描述进行构建。

一、Bean实例化后阶段(Bean属性赋值前处理)

示例说明

假设我们有一个User类,并且我们注册了一个InstantiationAwareBeanPostProcessor的实现类CustomBeanPostProcessor,在该实现类中,我们重写了postProcessAfterInstantiation方法。

@Component
public class CustomBeanPostProcessor implements InstantiationAwareBeanPostProcessor {@Overridepublic boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {if (bean instanceof User) {// 在这里可以进行一些前置处理,比如检查bean的某些属性System.out.println("对User bean进行实例化后处理,beanName: " + beanName);// 返回true表示继续后续的属性赋值和初始化return true;}// 对于非User类型的bean,默认返回truereturn true;}
}@Component
public class User {// 类的属性和方法
}

在这个例子中,当Spring容器实例化User类的Bean时,会调用CustomBeanPostProcessorpostProcessAfterInstantiation方法。我们可以在这个方法中进行一些前置处理,比如检查Bean的某些属性是否满足条件,或者修改Bean的某些状态。由于我们返回了true,所以Spring会继续对User Bean进行属性赋值和初始化。

二、Bean属性赋值

示例说明

通常,Bean的属性赋值是通过Spring的依赖注入机制自动完成的,我们不需要手动编写代码来执行这个过程。但是,我们可以通过Spring的配置文件或注解来指定Bean的属性值。

@Component
public class User {@Value("${user.name}")private String name;@Autowiredprivate Address address;// 类的其他部分
}@Component
public class Address {// 类的属性和方法
}// application.properties
user.name=John Doe

在这个例子中,User类的name属性通过@Value注解从配置文件中注入了值,而address属性则通过@Autowired注解自动注入了Address类型的Bean。当Spring容器创建User Bean时,它会根据这些注解和配置信息,自动为User Bean的属性赋值。

三、InstantiationAwareBeanPostProcessor属性赋值后回调

示例说明

InstantiationAwareBeanPostProcessor接口中,除了postProcessAfterInstantiation方法外,还有postProcessPropertiespostProcessPropertyValues方法(注意:在Spring的某些版本中,postProcessPropertyValues方法可能被标记为过时或移除,具体取决于Spring的版本)。然而,由于postProcessProperties方法通常用于更高级的场景,并且不是所有Spring版本都支持该方法,因此这里我们以一个假设的postProcessPropertyValues方法为例进行说明。

请注意,由于postProcessPropertyValues方法可能在新版本的Spring中不再使用,这里仅提供一个概念性的示例。

// 假设的示例,实际中可能需要根据Spring版本进行调整
@Component
public class CustomBeanPostProcessor implements InstantiationAwareBeanPostProcessor {@Overridepublic PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {if (bean instanceof User) {// 在这里可以对PropertyValues进行修改或扩展// 注意:这里只是示例,实际中可能需要根据需要进行复杂的处理MutablePropertyValues mutablePvs = new MutablePropertyValues(pvs);// 假设我们想要为User Bean添加一个额外的属性mutablePvs.addPropertyValue("extraProperty", "extraValue");return mutablePvs;}// 对于非User类型的bean,默认返回原始的PropertyValuesreturn pvs;}
}

然而,需要注意的是,由于postProcessPropertyValues方法可能已被Spring的新版本废弃或替换,因此在实际应用中,我们应该参考Spring的官方文档和API指南,以了解当前版本所支持的正确方法和实践。

在实际应用中,更常见的是使用postProcessProperties方法的替代方案,如通过@PostConstruct注解标记的方法或实现InitializingBean接口中的afterPropertiesSet方法,来在属性赋值后进行一些额外的处理。但是,这些方法并不直接属于InstantiationAwareBeanPostProcessor接口的一部分。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/872939.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用 git 和 GitHub 互动

本文根据《GitHub入门与实践》整理 创建账户 要想使用GitHub那就必须先有GitHub账号,账号自行注册,不作介绍。 本地生成 SSH Key SSH 提供了一种安全的方式来通过不安全的网络进行通信。当你使用SSH key连接到GitHub时,你的身份是通过密钥对(一个公钥和一个私钥)来验…

PJA1介导的焦亡抑制是鼻咽癌产生耐药性的驱动因素

引用信息 文 章:PJA1-mediated suppression of pyroptosis as a driver of docetaxel resistance in nasopharyngeal carcinoma. 期 刊:Nature Communications(影响因子:14.7) 发表时间:2024年6月2…

unity 把Vuforia的Image做成预制件prefab后,通过ab加载或者其他动态加载后,扫描图片不会出现模型

//通过ab加载资源(自己封装的ab加载的脚本)GameObject go LoadHandle.Instance.LoadPrefab.LoadPrefabAssets("ImagePrefab");GameObject game GameObject.Instantiate(go);//加载预制件后,加载图片的数据库// 初始化 Vuforia I…

Lua 数组

Lua 数组 Lua 是一种轻量级的编程语言,广泛用于游戏开发、脚本编写和其他应用程序。在 Lua 中,数组是一种非常基础和重要的数据结构。本文将详细介绍 Lua 数组的概念、用法和操作方法。 数组的概念 在 Lua 中,数组实际上是一个列表&#x…

链接追踪系列-10.mall-swarm微服务运行并整合elk-上一篇的番外

因为上一篇没对微服务代码很详细地说明,所以在此借花献佛,使用开源的微服务代码去说明如何去做链路追踪。 项目是开源项目,fork到github以及gitee中,然后拉取到本地 后端代码: https://gitee.com/jelex/mall-swarm.gi…

密码学原理精解【7】

文章目录 流密码密码体制概述唯吉尼亚密码一、历史与背景二、加密算法三、特点与应用四、破译方法五、原理概述加密过程解密过程注意事项 流密码理论解释一、定义与原理二、特点与优势三、工作原理四、应用实例五、安全性与限制 RC4算法一、算法概述二、算法原理三、算法特点四…

11.FreeRTOS_事件组

事件组概述 事件组的作用: 可以等待某一个事件发生可以等待若干个事件发生可以等待若干个事件中的某一个事件发生 同步点是事件组的另一个使用方式,它可以让多个任务进行阻塞等待,当全部事件完成后,再一起解除任务的阻塞。常常…

【字幕】字幕特效入门

前言 最近两周调研了一下字幕特效的底层程序逻辑,因为工作内容的原因,就分享几个自己找的链接具体细节就不分享了,CSDN也是我的个人笔记,只记录一些简单的内容用于后续自己方便查询,顺便帮助一下正在苦苦查阅资料入门…

【JavaScript脚本宇宙】解锁 JavaScript 二维码/条形码库的指南

JavaScript框架中的二维码与条形码生成库大比拼:选择适合你项目的最佳利器 前言 随着二维码和条形码在商业和日常生活中的广泛应用,为了方便开发人员在各种前端框架和库中集成生成二维码和条形码的功能,出现了多款专门用于在不同JavaScript…

51单片机学习(4)

一、串口通信 1.串口通信介绍 写完串口函数时进行模块化编程,模块化编程之后要对其进行注释,以便之后使用模块化函数,对模块化.c文件中的每一个函数进行注释。 注意:一个函数不能既在主函数又在中断函数中 模式1最常用&#xf…

Elasticsearch与其他系统的集成(如Logstash、Kibana、Beats等):构建强大的数据处理与分析平台

在当今的数据驱动时代,Elasticsearch以其强大的搜索和分析能力,成为了众多企业和项目中的核心组件。然而,Elasticsearch的强大并不止于其本身,其与其他系统的紧密集成,如Logstash、Kibana、Beats等,共同构建…

【学习笔记】无人机(UAV)在3GPP系统中的增强支持(十)-服务体验保证的用例

引言 本文是3GPP TR 22.829 V17.1.0技术报告,专注于无人机(UAV)在3GPP系统中的增强支持。文章提出了多个无人机应用场景,分析了相应的能力要求,并建议了新的服务级别要求和关键性能指标(KPIs)。…

Java前后端分离开发的步骤以及注意事项

在现代Web应用程序开发中,前后端分离是一种常见的架构模式。这种模式将前端(用户界面)和后端(业务逻辑和数据处理)分开独立开发和部署,从而提高开发效率、代码的可维护性和团队协作能力。本文将介绍Java前后…

Go语言中的并发

简单介绍go中的并发编程. 涉及内容主要为goroutine, goroutine间的通信(主要是channel), 并发控制(等待、退出). 想查看更多与Go相关的内容, 可以查看我的Go编程栏目 Goroutine 语法 在一个函数调用前加上go即可, go func(). 语法很简单, 可以说是并发写起来最简单的程序语言…

rust编译安卓各个平台so库

安卓studio 安装SDK 和 NDK 所有操作是mac m1 上操作的 NDK 可以在 Android studio 设置里面,搜索sdk ,然后看下SDK 位置例如我下面的位置: /Users/admin/Library/Android/sdk/ndkAndroid NDK(Native Development Kit)生成一个独立的工具链…

Java中锁的全面详解(深刻理解各种锁)

一.Monitor 1. Java对象头 以32位虚拟机位例 对于普通对象,其对象头的存储结构为 总长为64位,也就是8个字节, 存在两个部分 Kclass Word: 其实也就是表示我们这个对象属于什么类型,也就是哪个类的对象.而对于Mark Word.查看一下它的结构存储 64位虚拟机中 而对于数组对象,我…

Java面试题(企业真题)

01.泛型的理解 泛型是Java 5引入的一种特性,它允许程序员在定义类、接口或方法时指定一个或多个类型参数,从而可以在运行时处理各种不同的数据类型,同时保持类型安全。泛型提供了编译时类型检查,消除了强制类型转换的需要,减少了运行时ClassCastException异常的可能性。02…

设计模式使用场景实现示例及优缺点(行为型模式——状态模式)

在一个遥远的国度中,有一个被称为“变幻之城”的神奇城堡。这座城堡有一种特殊的魔法,能够随着王国的需求改变自己的形态和功能。这种神奇的变化是由一个古老的机制控制的,那就是传说中的“状态宝石”。 在变幻之城中,有四颗宝石&…

神经网络中的激活函数举例,它们各自的特点,以及哪个激活函数效果更好,为什么

sigmoid: \(\sigma(x)1/(1e^{-x})\); 优:将数值压缩到 0 1,导数为 \(\sigma(x)(1-\sigma(x))\) 好算。劣:输出均值非0(0.5),梯度消失(Gradient vanishing)每次…

Java中的迭代器(Iterator)

Java中的迭代器(Iterator) 1、 迭代器的基本方法2、 迭代器的使用示例3、注意事项4、克隆与序列化5、结论 💖The Begin💖点点关注,收藏不迷路💖 在Java中,迭代器(Iterator&#xff0…