Spring扩展点系列-BeanFactoryAware

文章目录

    • 简介
    • 源码分析
    • 示例代码
      • 示例一:验证BeanFactoryAware执行顺序
      • 示例二:动态获取其他bean
      • 示例三:动态bean的状态

简介

spring容器中Bean的生命周期内所有可扩展的点的调用顺序
扩展接口 实现接口
ApplicationContextlnitializer initialize
AbstractApplicationContext refreshe
BeanDefinitionRegistryPostProcessor postProcessBeanDefinitionRegistry
BeanDefinitionRegistryPostProcessor postProcessBeanFactory
BeanFactoryPostProcessor postProcessBeanFactory
instantiationAwareBeanPostProcessor postProcessBeforelnstantiation
SmartlnstantiationAwareBeanPostProcessor determineCandidateConstructors
MergedBeanDefinitionPostProcessor postProcessMergedBeanDefinition
InstantiationAwareBeanPostProcessor postProcessAfterlnstantiation
SmartInstantiationAwareBeanPostProcessor getEarlyBeanReference
BeanNameAware setBeanName
BeanFactoryAware postProcessPropertyValues
ApplicationContextAwareProcessor invokeAwarelnterfaces
InstantiationAwareBeanPostProcessor postProcessBeforelnstantiation
@PostConstruct
InitializingBean afterPropertiesSet
FactoryBean getobject
SmartlnitializingSingleton afterSingletonslnstantiated
CommandLineRunner run
DisposableBeandestroy

BeanFactoryAware用于注入BeanFactory对象。我们可以访问创建该对象的BeanFactory 。借助 setBeanFactory()方法,我们将IoC 容器中的BeanFactory引用分配给beanFactory 属性,之后,我们可以创建函数直接使用它。
BeanNameAware的常用场景一般是用于日志记录。

源码分析

BeanFactoryAware是Aware的超级子接口
在这里插入图片描述

从源码中可以看到BeanFactoryAware只提供了一个set方法,该接口中只定义了setBeanFactory一个方法。

public interface BeanFactoryAware extends Aware {void setBeanFactory(BeanFactory beanFactory) throws BeansException;}

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean实现了Spring的Aware接口族的Beans(如BeanNameAware, BeanFactoryAware等)。如果提供的bean实现了任何这些接口,该方法会回调相应的Aware方法

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {if (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {invokeAwareMethods(beanName, bean);return null;}, getAccessControlContext());}else {invokeAwareMethods(beanName, bean);}Object wrappedBean = bean;if (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);}try {invokeInitMethods(beanName, wrappedBean, mbd);}catch (Throwable ex) {throw new BeanCreationException((mbd != null ? mbd.getResourceDescription() : null),beanName, "Invocation of init method failed", ex);}if (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}return wrappedBean;
}

当一个 bean 实现了如 BeanNameAware、BeanClassLoaderAware 或 BeanFactoryAware 等接口时,此方法确保正确的回调方法被调用,从而为 bean 提供关于其运行环境或其他相关信息。

private void invokeAwareMethods(String beanName, Object bean) {if (bean instanceof Aware) {if (bean instanceof BeanNameAware) {((BeanNameAware) bean).setBeanName(beanName);}if (bean instanceof BeanClassLoaderAware) {ClassLoader bcl = getBeanClassLoader();if (bcl != null) {((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);}}if (bean instanceof BeanFactoryAware) {((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);}}
}

示例代码

示例一:验证BeanFactoryAware执行顺序

这里创建一个类去实现BeanFactoryAware,顺带也实现 BanNameAware接口,这样可以比对看出两者的执行顺序

@Slf4j
@Component
public class ExtendBeanFactoryAware implements BeanNameAware, BeanFactoryAware {@Overridepublic void setBeanName(String name) {log.info("ExtendBeanNameAware-2--beanName:{}",name);}@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {log.info("ExtendBeanFactoryAware-3--beanName:{}",beanFactory);}
}

注:如果把@Component缓存@Configuration,setBeanFactory会执行两次。setBeanFactory-》setBeanName=》setBeanFactory
运行示例
在这里插入图片描述

示例二:动态获取其他bean

下面这个示例主要展示一个常用的场景,一个 Bean 可以在运行时动态获取其他 Bean

@Slf4j
@Component
public class ExtendBeanFactoryAware implements BeanNameAware, BeanFactoryAware {private BeanFactory beanFactory;@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {this.beanFactory = beanFactory;log.info("ExtendBeanFactoryAware-3--beanName:{}",beanFactory);}public void getOtherBean() {OtherBean otherBean = beanFactory.getBean(OtherBean.class);System.out.println("获取 otherBean 实例: " + otherBean);}
}@Component
public class OtherBean {@Overridepublic String toString() {return "这是 OtherBean 实例";}
}@Configuration
public class AppConfig {@Beanpublic OtherBean getOtherBean () {return new OtherBean();}@Beanpublic ExtendBeanFactoryAware getExtendBeanFactoryAware () {return new ExtendBeanFactoryAware();}
}//controller运行调用获取bean
@GetMapping("/getOtherBean")
public void getOtherBean() throws Exception{ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);ExtendBeanFactoryAware beanFactoryAware = context.getBean(ExtendBeanFactoryAware.class);beanFactoryAware.getOtherBean();
}

运行示例
在这里插入图片描述

示例三:动态bean的状态

在运行时,可以通过 BeanFactoryAware检查某个 Bean 是否存在或者其状态,下面是代码展示

@Slf4j
@Component
public class ExtendBeanFactoryAware implements BeanNameAware, BeanFactoryAware {private BeanFactory beanFactory;@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {this.beanFactory = beanFactory;log.info("ExtendBeanFactoryAware-3--beanName:{}",beanFactory);}public void checkBeanState() {boolean exists = beanFactory.containsBean("getOtherBean");log.info("otherBean 是否存在: {}" , exists);}
}@Component
public class OtherBean {
}@Configuration
public class AppConfig {//如果不指定Bean名,则默认是bean的名字为方法名@Beanpublic OtherBean getOtherBean () {return new OtherBean();}@Beanpublic ExtendBeanFactoryAware getExtendBeanFactoryAware () {return new ExtendBeanFactoryAware();}
}//controller运行调用获取bean
@GetMapping("/checkBeanState")
public void checkBeanState() throws Exception{ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);ExtendBeanFactoryAware beanFactoryAware = context.getBean(ExtendBeanFactoryAware.class);beanFactoryAware.checkBeanState();
}

运行示例
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

git 更换远程地址的方法

需要将正在开发的代码远程地址改成新的地址&#xff0c;通过查询发现有三个方法可以实现&#xff0c;特此记录。具体方法如下&#xff1a; &#xff08;1&#xff09;通过命令直接修改远程仓库地址 git remote 查看所有远程仓库git remote xxx 查看指定远程仓库地址git remote…

MySQL代码顺序(整合)

这个图片也就是说明执行顺序 FROM > WHERE > GOURP BY > HAVING > SELECT > ORDER BY > LIMIT; 编写按照这个顺序写即可。

SX_VMware联网_23

利用Nat模式联网&#xff0c;NAT模式&#xff08;Network Address Translation&#xff09;&#xff1a; 在NAT模式下&#xff0c;虚拟机通过主机的网络接口访问外部网络。 虚拟机之间可以相互通信&#xff0c;也可以访问主机网络以及互联网。 虚拟机使用私有IP地址&#xff0c…

工业互联网网络集成与实训系统解决方案

随着工业4.0时代的到来和信息技术的高速发展&#xff0c;工业互联网已成为推动产业升级的重要力量。本方案旨在通过构建高度仿真的实训环境&#xff0c;帮助学生全面掌握工业互联网技术&#xff0c;为未来的职业生涯奠定坚实基础。 一、设计理念 在设计理念上&#xff0c;本方…

【GIS开发小课堂】写一个高德地图巡航功能的小DEMO

介绍 此项目使用vite为基础架构&#xff0c;内部实现均以typescript开发&#xff0c;可替换为自己的业务逻辑&#xff0c;并迁移到react&#xff0c;vue&#xff0c;umi等其他框架。 通过调用高德地图的API和threejs的开发&#xff0c;实现了一个小鸭子&#xff08;可替换为自己…

TiDB 扩容过程中 PD 生成调度的原理及常见问题丨TiDB 扩缩容指南(一)

导读 作为一个分布式数据库&#xff0c;扩缩容是 TiDB 集群最常见的运维操作之一。本系列文章&#xff0c;我们将基于 v7.5.0 具体介绍扩缩容操作的具体原理、相关配置及常见问题的排查。 通常&#xff0c;我们根据当前资源状态来决定是否需要调整 TiKV 节点的规模&#xff0…

Version ‘18.19.0‘ not found - try `nvm ls-remote` to browse available versions.

nvm安装指定版本不好使了 使用 nvm install 18.19.0 一直报错 Version 18.19.0 not found - try nvm ls-remote to browse available versions.然而使用 nvm ls-remote 只看到 iojs-v1.0.0iojs-v1.0.1iojs-v1.0.2iojs-v1.0.3iojs-v1.0.4iojs-v1.1.0iojs-v1.2.0iojs-v1.3.0iojs…

Wildberries测评自养号支付下单技术

Wildberries&#xff08;俄语&#xff1a;ООО Ягодки&#xff09;是俄罗斯最大的在线零售商&#xff0c;由Tatyana Bakalchuk于 2004 年创立。除俄罗斯外&#xff0c;他们还在其他 15 个国家提供服务&#xff1a;亚美尼亚、白俄罗斯、法国、德国、以色列、意大利、哈萨…

PHP省时省力海报在线制作系统小程序源码

省时省力海报在线制作系统&#xff1a;设计小白也能秒变大师 &#x1f3a8; 开篇&#xff1a;告别繁琐&#xff0c;拥抱高效设计 你还在为设计一张海报而熬夜加班吗&#xff1f;还在为找不到合适的素材而焦头烂额吗&#xff1f;别担心&#xff0c;“省时省力海报在线制作系统”…

使用开源框架HandyControl

准备 NuGet 搜索安装 HandyControl。 在App.xaml中添加以下代码&#xff1a; <Application.Resources><ResourceDictionary><ResourceDictionary.MergedDictionaries><ResourceDictionary Source"pack://application:,,,/HandyControl;component/…

大雪纷飞的视频素材去哪里找啊?雪景素材库分享

当冬季的银装素裹覆盖大地&#xff0c;无数抖音创作者便开始寻找那些可以捕捉到大雪纷飞的壮观画面。无论是为了制作节日主题的视频、记录下雪天的活动&#xff0c;还是单纯展示雪的清新美&#xff0c;优质的大雪视频素材都显得尤为重要。如果你正为寻找这类素材而苦恼&#xf…

建造者模式:灵活构建复杂对象的利器

在软件开发中&#xff0c;创建一个复杂对象通常需要多个步骤和参数&#xff0c;直接在客户端代码中进行这些操作不仅繁琐&#xff0c;而且难以维护。建造者模式&#xff08;Builder Pattern&#xff09;提供了一种优雅的解决方案&#xff0c;使得对象的创建过程更加清晰、灵活和…

磁盘写操作压力测试工具的设计与实现

磁盘写操作压力测试工具的设计与实现 1. 设计概述2. 关键技术点3. 伪代码设计4. C代码实现5. 运行与测试6. 结论在进行磁盘性能评估时,写操作压力测试是不可或缺的一部分。本篇文章将介绍如何使用C语言结合系统调用,设计并实现一个针对磁盘写操作的压力测试工具。这个工具将模…

LINUX网络编程:http

目录 1.认识http请求的字段 2.HTTP请求类 3.认识HTTP应答字段 4.HTTP应答类 5.源代码 协议就是一种约定&#xff0c;http也并不例外&#xff0c;使用http也无非就是&#xff0c;定义一个http请求的结构体&#xff0c;将结构体序列化为字符串&#xff0c;发送给服务器&…

2024年06月中国电子学会青少年软件编程(图形化)等级考试试卷(一级)答案 + 解析

青少年软件编程&#xff08;图形化&#xff09;等级考试试卷&#xff08;一级&#xff09; 分数&#xff1a;100 题数&#xff1a;37 一、单选题 音乐Video Game1的时长将近8秒&#xff0c;点击一次角色&#xff0c;下列哪个程序不能完整地播放音乐两次&#xff1f;&#xff0…

【Hot100】LeetCode—169. 多数元素

目录 1- 思路题目识别技巧 2- 实现⭐136. 只出现一次的数字——题解思路 3- ACM 实现 原题链接&#xff1a;169. 多数元素 1- 思路 题目识别 识别1 &#xff1a;统计数组中出现数量多余 [n/2] 的元素 技巧 值相同&#xff0c;则对 count 1&#xff0c;如果不相同则对值进行…

【C#】VS插件

翻译 目前推荐较多的 可以单词发言&#xff0c;目前还在开发阶段 TranslateIntoChinese - Visual Studio Marketplace 下载量最高的(推荐) Visual-Studio-Translator - Visual Studio Marketplace 支持翻译的版本较多&#xff0c;在 Visual Studio 代码编辑器中通过 Googl…

vue使用TreeSelect设置带所有父级节点的回显

Element Plus的el-tree-select组件 思路&#xff1a; 选中节点时&#xff0c;给选中的节点赋值 pathLabel&#xff0c;pathLabel 为函数生成的节点名字拼接&#xff0c;数据源中不包含。 在el-tree-select组件中设置 props“{ label: ‘pathLabel’ }” 控制选中时input框中回…

【信创】推荐一款好用的免费在线流程图思维导图工具 _ 统信 _ 麒麟 _ 方德

原文链接&#xff1a;【信创】推荐一款好用的免费在线流程图思维导图工具 | 统信 | 麒麟 | 方德 Hello&#xff0c;大家好啊&#xff01;今天给大家推荐一款非常好用的免费在线流程图和思维导图工具——ProcessOn。无论是项目管理、数据分析、头脑风暴还是日常办公&#xff0c;…

RFID读写器:零部件加工中的高效识别与管理利器

RFID读写器&#xff1a;零部件加工中的高效识别与管理利器 在传统零部件加工行业&#xff0c;面临着提高生产效率、保证生产计划执行、系统化管控产品质量以及有效管理库存等多方面的挑战&#xff0c;而 RFID 读写器在应对这些挑战的过程中扮演着至关重要的角色。 传统识别方式…