Spring扩展点系列-BeanFactoryAware

server/2024/9/22 10:38:03/

文章目录

    • 简介
    • 源码分析
    • 示例代码
      • 示例一:验证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一个方法。

java">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方法

java">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 提供关于其运行环境或其他相关信息。

java">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接口,这样可以比对看出两者的执行顺序

java">@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

java">@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 是否存在或者其状态,下面是代码展示

java">@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.ppmy.cn/server/118280.html

相关文章

【Python笔记】PyCharm大模型项目环境配置

一、PyCharm创建新项目 二、更新pip版本 ...>python.exe -m pip install --upgrade pip 三、生成所需requirements配置文件 ...>pip freeze > requirements.txt 四、安装所需组件requirements.txt ...>pip install -r requirements.txt

如何进行DAP-seq的数据挖掘,筛选验证位点

从样本准备到寄送公司&#xff0c;每一天都在“祈祷”有个心仪的分析结果&#xff0c;终于在这天随着邮件提示音的响起&#xff0c;收到了分析结果...... 分析前工作 爱基在进行数据分析之前&#xff0c;会有两次质控报告反馈给老师们。第一个&#xff0c;基因组DNA的提取质控…

【JAVA】数据脱敏技术(对称加密算法、非对称加密算法、哈希算法、消息认证码(MAC)算法、密钥交换算法)使用方法

文章目录 数据脱敏的定义和目的数据脱敏的技术分类对称加密算法非对称加密算法哈希算法消息认证码&#xff08;MAC&#xff09;算法密钥交换算法 数据脱敏的技术方案实现字符替换哈希算法&#xff08;例如:SHA-3 算法&#xff09;消息认证码&#xff08;MAC&#xff09;算法(CM…

uniapp 发布苹果IOS详细流程,包括苹果开发者公司账号申请、IOS证书、.p12证书文件等

记录一下uniapp发布苹果IOS的流程。 一、苹果开发者公司账号申请 1、邓白氏编码申请&#xff08;先申请公司邓白氏编码&#xff0c;这一步需要1-2周&#xff0c;没有这个编码苹果开发者没法申请&#xff0c;已有编码的跳过此步骤&#xff09;&#xff1a; 1&#xff09;联系苹…

‌内网穿透技术‌总结

内网穿透是一种网络技术&#xff0c;通过它可以使外部网络用户访问内部网络中的设备和服务。一般情况下&#xff0c;内网是无法直接访问的&#xff0c;因为它位于一个封闭的局域网中&#xff0c;无法从外部访问。而通过内网穿透&#xff0c;可以将内部网络中的设备和服务暴露在…

算法两道题

算法一 Write a function: int solution(vector<int>&A); that, given an array A of length N, returns as an integer the minimum number of moves needed to transform a zero-filled array into A. Examples: 1. Given A [2, 1, 3], the function should …

redis:全局ID生成器实现

问题&#xff1a;订单id不能设置为自增长的原因 id的规律性太明显&#xff0c; 受订单的数据量限制:若数据量过大&#xff0c;需要多张表存储&#xff0c;若自增会导致id重复 全局ID生成器&#xff1a;在分布式系统中用来生成全局唯一ID的工具 ID的组成&#xff1a; 符号位…

微信小程序中的实时通讯:TCP/UDP 协议实现详解

文章目录 前言一、实时通讯的基础知识二、微信小程序中 TCP/UDP 的支持2.1 TCP 实现2.2 UDP 实现 三、实现即时通讯的基本架构四、实际开发中的注意事项4.1 网络环境问题4.2 数据格式与协议设计4.3 消息重发机制 五、实时通讯中的性能优化5.1 减少不必要的通信5.2 数据压缩5.3 …