Spring的后处理器之BeanFactoryPostProcessor

news2024/9/21 18:37:07

Spring的后处理器

Spring的后处理器是Spring对外开放的重要扩展点,允许我们介入到Bean的整个实例化流程中来,以达到动态注册BeanDefinition,动态修改BeanDefinition,以及动态修改Bean的作用。Spring主要有两种后处理器:

  • BeanFactoryPostProcessor:Bean工厂后处理器,在BeanDefinitionMap填充完毕,Bean实例化之前执行;
  • BeanPostProcessor:Bean后处理器,一般在Bean实例化之后,填充到单例池singletonObjects之前执行。

Bean工厂后处理器-BeanFactoryPostProcessor

BeanFactoryPostProcessor是一个接口规范,实现了该接口的类只要交由Spring容器管理的话,那么Spring就会回调该接口的方法,用于对BeanDefinition注册和修改的功能。

BeanFactoryPostProcessor定义如下:

public interface BeanFactoryPostProcessor {
	void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory);
}

使用方法:

package com.luxifa.processor;
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
	System.out.println("beanDefinitionMap填充完毕后回调该方法")
	}
}

xml中:

<bean class="com.luxifa.processor.MyBeanFactoryPostProcessor"></bean>

案例:修改某个BeanDifinition

package com.luxifa.processor;
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
	System.out.println("beanDefinitionMap填充完毕后回调该方法")
	//修改某个BeanDifinition
	BeanDefinition beanDefintion = beanFactory.getBeanDefinition("userService");
	beanDefintion.setBeanClassName("com.luxifa.dao.impl.UserDaoImpl");
	}
}

<bean id="userDao" name="aaa,bbb" class="com.luxifa.dao.impl.UserDaoImpl"></bean>

<bean class="userService" class="com.luxifa.service.impl.UserServeiceImpl"></bean>

public class ApplicationContextTest {
	public static void main(String[] args) throws Exception{
	
	ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
	Object userService = applicationContext.getBean("userServeice");
	System.out.println(userService);
	}
}

打印信息:

beanDefinitionMap填充完毕后回调该方法
com.luxifa.dao.impl.UserDaoImpl@544fe44a

Spring的Bean工厂后处理器注册BeanDefinition

public interface PersonDao {
}

public class PersonDaoImpl implements PersonDao {
}
package com.luxifa.processor;
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
	System.out.println("beanDefinitionMap填充完毕后回调该方法")
	//注册BeanDifinition
	BeanDefinition beanDefintion = new RootBeanDefinition();
	beanDefintion.setBeanClassName("com.luxifa.dao.impl.PersonDaoImpl");
	DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) beanFactory;
	defaultListableBeanFactory.registerBeanDefinition(beanName:"personDao",beanDefinition);
	}
}

xml中:

<bean class="com.luxifa.processor.MyBeanFactoryPostProcessor"></bean>
public class ApplicationContextTest {
	public static void main(String[] args) throws Exception{
	
	ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
	PersonDao userService = applicationContext.getBean(PersonDao.class);
	System.out.println(userService);
	}
}

控制台打印:

beanDefinitionMap填充完毕后回调该方法
com.luxifa.dao.impl.PersonDaoImpl@4e1d422d

Bean工厂后处理器 - BeanFactoryPostProcessor

Spring提供了一个BeanFactoryPostProcessor的子接口BeanDefinitionRegisterPostProcessor专门用来注册BeanDefinition操作

public class MyBeanFactoryPostProcessor2 implements BeanDefinitionRegistryPostProcessor {
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeanException {}

	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeanException {
	BeanDefinitionRegistry beanDefinitionRegistry = new RootBeanDefinition();
	beanDefinitionRegistry.setBeanClassName(com.luxifa.dao.userDaoImpl2);
	beanDefinitionRegistry.registerBeanDefinition("userDao2",beanDefinition);
	}
}

xml中:

<bean class="com.luxifa.processor.MyBeanDefinitionRegistryPostProcessor"></bean>

postProcessBeanDefinitionRegistry是BeanDefinitionRegistryPostProcessor父接口中的方法,也需要实现。

执行顺序 先执行postProcessBeanDefinitionRegistry 方法,后执行 postProcessBeanFactory方法。


Spring的bean工厂后处理器-完善实例化基本流程图

在这里插入图片描述

Spring的Bean工厂后处理器-自定义@Component

案例:使用Spring的BeanFactoryPostProcessor扩展点完成自定义注解扫描

  • 自定义@MyConponent注解,使用在类上
  • 完成指定包的类扫描
  • 自定义BeanFactoryPostProcessor完成注解@MyComponent的解析,解析后最终被Spring管理。
package com.luxifa.beans;

@MyComponent("otherBean")
public class OtherBean {
}
package com.luxifa.anno;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyComponent {

	String value;
	
}
package com.luxifa.processor;

public class ComponentBeanFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor {
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeanException {}

	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeanException {
	//通过扫描工具去扫描指定包及其子包下的所有类,收集使用@Mycomponent的注解的类
	Map<String, Class> myComponentAnnotationMap = BaseClassScanUtils.scanMyComponentAnnotation(basePackage:"com.luxifa");
	//遍历Map,组装BeanDefinition进行注册
	myComponentAnnotationMap.forEach((beanName,clazz)->{
		//获得beanClassName
		String beanClassName = clazz.getName(); //com.luxifa.beans.OtherBean
		//创建BeanDefinition
		BeanDefinition beanDefinition = new RootBeanDefinition();
		beanDefinition.setBeanClassName(beanClassName);
		//注册
		beanDefinitionRegistry.registerBeanDefinition(beanName,beanDefinition);
		});
	}
}

xml中:

<bean class="com.luxifa.processor.MyComponentBeanFactoryPostProcessor"></bean>
public class ApplicationContextTest {
	
	public static void main(String[] args) throws Exception {
		
		ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
		OtherBean otherBean = applicationContext.getBean(OtherBean.class);
		System.out.println(otherBean);
		
	}
}

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

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

相关文章

【车载开发系列】StatusOfDTC的解析

【车载开发系列】StatusOfDTC的解析 StatusOfDTC的解析【车载开发系列】StatusOfDTC的解析StatusOfDTC概念StatusOfDTC列表StatusOfDTC状态掩码Bit 0: TestFailedBit 1: testFailedThisOperationCycleBit 2: pendingDTCBit 3: confirmedDTCBit 4: testNotCompletedSinceLastCle…

【操作系统】3、内存管理

文章目录三、内存管理3.1 内存基础3.1.1 内存管理概念3.1.2 程序装入与链接3.1.3 内存保护3.2 内存空间的分配与回收3.2.1 连续分配管理方式3.2.1.1 单一连续分配3.2.1.2 固定分区分配3.2.1.3 动态分区分配3.2.2 动态分区分配算法3.2.2.1 首次适应算法3.2.2.2 最佳适用算法3.2.…

【数据库原理与SQL Server应用】Part05——表和表数据操作

【数据库原理与SQL Server应用】Part05——表和表数据操作一、表概念1.1 表结构1.2 表类型1.3 数据类型二、创建表2.1 管理工具界面方式创建表2.2 命令行方式创建表三、修改表3.1 管理工具界面方式修改表3.2 命令行方式修改表四、删除表五、表数据操作5.1 管理工具界面方式操作…

怎么快速选择出色的香港服务器

相信一些大规模企业或站长都不满足于普通的香港VPS&#xff0c;虽然它也拥有很不错的性能与速度&#xff0c;但远远比不上香港服务器。但是&#xff0c;对于初次使用香港服务器的用户来说&#xff0c;选择起来肯定是要经过一番考虑的&#xff0c;那么&#xff0c;有没有什么简单…

电子词典项目

16. 电子词典项目需求 项目要求&#xff1a; 登录注册功能&#xff0c;不能重复登录&#xff0c;重复注册单词查询功能历史记录功能&#xff0c;存储单词&#xff0c;意思&#xff0c;以及查询时间基于TCP&#xff0c;支持多客户端连接采用数据库保存用户信息与历史记录将dic…

VS2022离线安装教程

官方教程下载和安装步骤 https://docs.microsoft.com/zh-cn/visualstudio/install/create-an-offline-installation-of-visual-studio?viewvs-2022 使用命令行创建本地布局 下载所需的 Visual Studio 版本的引导程序&#xff0c;并将其复制到要用作本地布局源位置的目录中。…

训练自己的GPT2模型(中文),踩坑与经验

GPT2与Bert、T5之类的模型很不一样&#xff01;&#xff01;&#xff01; 如果你对Bert、T5、BART的训练已经很熟悉&#xff0c;想要训练中文GPT模型&#xff0c;务必了解以下区别&#xff01;&#xff01;&#xff01; 官方文档里虽然已经有教程&#xff0c;但是都是英文&…

手撸低代码平台搭建(四)组件拖动自由布局的实现

前言 大家好,在前两篇文章中,我们走进了前端低代码的世界,并揭秘了低代码的核心——页面设计器的实现。在揭秘页面设计器时,我们重点分享了顺序排列布局的组件拖动方式,那篇文章的评论中,有小伙伴问到自由布局的实现,那么我们在这篇文章中来分享一下自由布局拖动的实现…

Echarts柱形头部圆弧处理

第008个点击查看专栏目录对于柱状图来说&#xff0c;我们想要的效果是圆柱的上面进行圆弧的处理&#xff0c;产生顺滑的感觉&#xff0c;怎么处理呢&#xff0c;只要设置好样式即可&#xff0c;参考源代码圆角半径&#xff0c;单位px&#xff0c;支持传入数组分别指定 4 个圆角…

VMware 多站点容灾之SRM部署实践

一、背景 在VMware 多云场景中&#xff0c;我们最初会通过vmware的副本机制手动克隆或主从模式完成一些节点的灾备&#xff0c;虽然在初期不会出现什么问题&#xff0c;但一旦出现灾备恢复的复杂度和数据丢失风险还是一大考验&#xff0c;基于此&#xff0c;我们可借助VMware v…

Qt 获取网络信息

在Qt Network模块中使用QHostAddress存放IP地址&#xff0c;QHostInfo类来获取主机名和IP。 进行TCP/UDP编程时&#xff0c;需要将连接的主机名解析为IP地址&#xff0c;这个操作用DNS协议执行。 在互联网中现在有两种IP类型&#xff1a;IVP4和IVP6。 IP地址是给每一个连接在互…

Linux操作系统之基础IO

目录 系统IO调用接口 open write read 理解文件描述符fd 理解Linux操作系统的设计哲学&#xff0c;多态的思想是如何应用在Linux文件系统的 输出&#xff0c;追加&#xff0c;输入重定向的本质 子进程共享父进程的文件 IO的两个缓冲区 Linux特有的EXT文件系统 磁盘系…

代码训练营第二十天|530.二叉搜索树的最小绝对差 ● 501.二叉搜索树中的众数 ● 236. 二叉树的最近公共祖先

530 .二叉搜索树的最小绝对差 看完题后的思路 因为是二叉搜索树&#xff0c;所以直接按照二叉搜索树中序遍历&#xff0c;得到递增序列。遍历过程中一个指针指向遍历过的前一个元素 prenull&#xff1b; void f&#xff08;root&#xff09;if rootnull return递归 f&#x…

git语义化定制版本规范

目录说明说明 语义化版本控制规范,语义化的版本控制规范要求版本号由三部分构成&#xff1a;x.y.z MAJOR&#xff08;X&#xff09;&#xff1a;这个是主版本号&#xff0c;一般是涉及到不兼容的 API 更改时&#xff0c;这个会变化。MINOR&#xff08;Y&#xff09;&#xff…

剑指Offer pow() 函数实现(快速幂)!!!

剑指 Offer 16. 数值的整数次方 实现 pow(x, n) &#xff0c;即计算 x 的 n 次幂函数&#xff08;即&#xff0c;xn&#xff09;。不得使用库函数&#xff0c;同时不需要考虑大数问题。 示例 1&#xff1a; 输入&#xff1a;x 2.00000, n 10 输出&#xff1a;1024.00000 示…

早已有所耳闻的堆排序,你知道如何用C语言实现吗? 【堆排序|C语言版】

目录 0.写在前面 1.什么是堆&#xff1f; 2. 堆排序 2.1 建堆 2.1.1 AdjustUp&#xff08;向上调整算法&#xff09; 2.1.2 AdjustDown&#xff08;向下调整算法&#xff09; 2.2 两种建堆算法的时间复杂度 2.2.1 AdjustUp建堆的时间复杂度 2.2.2 AdjustDown建堆的时间…

神经网络(模型)量化介绍 - PTQ 和 QAT

神经网络&#xff08;模型&#xff09;量化介绍 - PTQ 和 QAT1. 需求目的2. 量化简介3. 三种量化模式3.1 Dynamic Quantization - 动态量化3.2 Post-Training Static Quantization - 训练后静态量化3.3 Quantization Aware Training - 量化感知训练4. PTQ 和 QAT 简介5. 设备和…

Flutter 小技巧之 3.7 性能优化background isolate

Flutter 3.7 的 background isolate 绝对是一大惊喜&#xff0c;尽管它在 release note 里被一笔带过 &#xff0c;但是某种程度上它可以说是 3.7 里最实用的存在&#xff1a;因为使用简单&#xff0c;提升又直观。 Background isolate YYDS 前言 我们知道 Dart 里可以通过新建…

CODESYS开发教程9-文件读写(CAA File库)

今天继续我们的小白教程&#xff0c;老鸟就不要在这浪费时间了&#x1f60a;。 前面一期我们介绍了CODESYS的定时器及触发相关的功能块。这一期主要介绍CODESYS的CAA.File库中的目录和文件读写功能块&#xff0c;主要包括文件路径、名称、大小的获取以及文件的创建、打开、读、…

软测(概念) · 软件测试的基本概念 · 什么是需求 · 测试用例的概念 · 软件错误(bug)的概念

一、什么是软件测试软件测试和开发的区别测试和调试的区别一个优秀的软件测试人员具备的素质二、什么是需求从测试人员角度看待需求三、测试用例的概念四、软件错误&#xff08;bug&#xff09;的概念一、什么是软件测试 最常见的解释是&#xff1a;软件测试就是找 BUG&#x…