Spring经典扩展接口应用:BeanPostProcessor

news2024/11/22 12:04:30

备注:新进行基本思路总结,四五月总结完

一、BeanPostProcessor基本知识总结

BeanPostProcessor是Bean级处理器,用于在bean实例化后、初始化后自定义修改bean实例,如属性校验、针对自定义bean做统一处理等。

BeanPostProcessor接口中定义了两个方法:

  • postProcessBeforeInitialization 方法,在任何bean初始化回调「如InitializingBean接口的afterPropertiesSet方法、自定义的初始化方法」之前,使BeanPostProcessor应用于给定的bean实例,其返回值可以是bean本身或其包装类。

  • postProcessAfterInitialization 方法,在bean回调初始化方法后调用。

实现过程:注册-执行postProcessBeforeInitialization-执行postProcessAfterInitialization

如果我们想在Spring容器中完成bean实例化、配置以及其他初始化方法前后要添加一些自己逻辑处理。我们需要定义一个或多个BeanPostProcessor接口实现类,然后注册到Spring IoC容器中。

Spring中Bean的实例化过程图示:

 注意:

1、接口中的两个方法都要将传入的bean返回,而不能返回null,如果返回的是null那么我们通过getBean方法将得不到目标。

2、BeanFactory和ApplicationContext对待bean后置处理器稍有不同。ApplicationContext会自动检测在配置文件中实现了BeanPostProcessor接口的所有bean,并把它们注册为后置处理器,然后在容器创建bean的适当时候调用它,因此部署一个后置处理器同部署其他的bean并没有什么区别。而使用BeanFactory实现的时候,bean 后置处理器必须通过代码显式地去注册,在IoC容器继承体系中的ConfigurableBeanFactory接口中定义了注册方法

/**  
 * Add a new BeanPostProcessor that will get applied to beans created  
 * by this factory. To be invoked during factory configuration.  
 * <p>Note: Post-processors submitted here will be applied in the order of  
 * registration; any ordering semantics expressed through implementing the  
 * {@link org.springframework.core.Ordered} interface will be ignored. Note  
 * that autodetected post-processors (e.g. as beans in an ApplicationContext)  
 * will always be applied after programmatically registered ones.  
 * @param beanPostProcessor the post-processor to register  
 */    
void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);

另外,不要将BeanPostProcessor标记为延迟初始化。因为如果这样做,Spring容器将不会注册它们,自定义逻辑也就无法得到应用。假如你在<beans />元素的定义中使用了'default-lazy-init'属性,请确信你的各个BeanPostProcessor标记为'lazy-init="false"'。

二、BeanPostProcessor实际应用分析

BeanPostProcessor 接口在 Spring 框架中的实际应用场景有很多,以下是一些举例:

  1. 属性注入:可以通过实现 BeanPostProcessor 接口,在 Bean 实例化后、初始化之前,对 Bean 的属性进行自定义注入。例如,可以在 BeanPostProcessor 的 postProcessBeforeInitialization 方法中,对 Bean 的属性进行修改或赋值,从而实现属性注入的定制化需求。
  2. AOP 预处理:可以通过实现 BeanPostProcessor 接口,在 Bean 实例化后、初始化之前,对 Bean 进行 AOP 相关的预处理。例如,可以在 BeanPostProcessor 的 postProcessBeforeInitialization 方法中,为 Bean 动态生成代理对象,实现 AOP 面向切面的功能。
  3. 定制初始化逻辑:可以通过实现 BeanPostProcessor 接口,在 Bean 初始化阶段,对 Bean 进行自定义的初始化逻辑。例如,可以在 BeanPostProcessor 的 postProcessAfterInitialization 方法中,执行一些初始化操作,例如数据初始化、资源加载等。
  4. 数据校验:可以通过实现 BeanPostProcessor 接口,在 Bean 初始化后,对 Bean 中的数据进行校验。例如,可以在 BeanPostProcessor 的 postProcessAfterInitialization 方法中,对 Bean 中的数据进行验证,确保数据的合法性和完整性。
  5. 资源回收:可以通过实现 BeanPostProcessor 接口,在 Bean 销毁前,对 Bean 中的资源进行回收操作。例如,可以在 BeanPostProcessor 的 postProcessBeforeDestruction 方法中,执行资源的释放、关闭等操作,确保资源的合理释放。

需要注意的是,实现 BeanPostProcessor 接口时,需要谨慎处理 Bean 的生命周期,避免引入不必要的副作用和潜在的问题。在使用 BeanPostProcessor 接口时,应该根据具体需求,仔细考虑是否真正需要对 Bean 进行自定义处理,以及处理的时机和方式。

三、实际应用展示

(一)属性注入

可以通过实现 BeanPostProcessor 接口,在 Bean 实例化后、初始化之前,对 Bean 的属性进行自定义注入。例如,可以在 BeanPostProcessor 的 postProcessBeforeInitialization 方法中,对 Bean 的属性进行修改或赋值,从而实现属性注入的定制化需求。

定义MyBeanPostProcessor 实现了 BeanPostProcessor 接口,并重写了其中的两个方法postProcessBeforeInitialization 和 postProcessAfterInitialization。

在 postProcessBeforeInitialization 方法中,对 MyBean 类型的 Bean 进行了属性的自定义注入,实现了属性注入的定制化需求(这里只是简单的示例,实际应用中的处理逻辑可能更加复杂,根据具体需求进行自定义处理。)

package org.zyf.javabasic.springextend.beanpostprocessorext;

import lombok.Data;

/**
 * @author yanfengzhang
 * @description
 * @date 2023/4/16  23:54
 */
@Data
public class MyBean {
    private String myProperty;

    public void doSomething(){
        System.out.println("MyBean.doSomething()执行,myProperty="+myProperty);
    }
}

实际应用中,MyBean 可以是业务对象,例如一个业务逻辑的实现类,一个数据访问对象等等,具体根据你的业务需求而定。MyBean 只是一个占位符,可以根据你的实际业务需求和业务对象的命名规范来定义和命名自己的 Bean 类型。在实际应用中,你需要替换 MyBean 为你实际使用的业务对象的类名,以便在 MyBeanPostProcessor 中进行相应的处理。

配置示例

要使用这个自定义的 BeanPostProcessor,需要将其注册到 Spring 容器中,有以下两种方式:

通过配置文件方式

<!-- 配置文件中的注册方式 -->
<bean class="org.zyf.javabasic.springextend.beanpostprocessorext.MyBeanPostProcessor" />

通过 Java 配置类的方式

package org.zyf.javabasic.springextend.beanpostprocessorext;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author yanfengzhang
 * @description
 * @date 2023/4/16  23:58
 */
@Configuration
public class MyAppConfig {
    @Bean
    public MyBeanPostProcessor myBeanPostProcessor() {
        return new MyBeanPostProcessor();
    }
}

代码展示

package org.zyf.javabasic.springextend.beanpostprocessorext;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

/**
 * @author yanfengzhang
 * @description
 * @date 2023/4/16  23:53
 */
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        // 在 Bean 初始化前的处理逻辑
        if (bean instanceof MyBean) {
            MyBean myBean = (MyBean) bean;
            // 对 MyBean 的属性进行自定义注入
            myBean.setMyProperty("自定义属性");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        // 在 Bean 初始化后的处理逻辑
        return bean;
    }
}

这样,Spring 容器在实例化 Bean 并初始化之前,会调用 MyBeanPostProcessor 中的 postProcessBeforeInitialization 方法,从而实现属性注入的自定义处理。需要注意的是,MyBeanPostProcessor 需要在 Spring 容器中作为一个 Bean 进行注册,才能被 Spring 容器识别并执行其中的逻辑。

(二)

参考链接:

1.Spring实战系列(三)-BeanPostProcessor的妙用_轻鸿飘羽的博客-CSDN博客

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

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

相关文章

实战:向人工智能看齐用Docker部署一个ChatGPT

文章目录前言鉴赏chatgpt环境要求开始搭建云安装docker从docker仓库拉取chatgpt-web镜像创建容器并运行chatgpt-web创建容器启动chatgpt-web访问自己的chatgpt总结前言 目前GPT-4都官宣步入多模态大型语言模型领域了&#xff0c;大佬竟然还没有体验GPT么。作为一个资深搬砖人士…

容器编排部署

一、概述 容器编排部署的作用&#xff1a; 实现复杂容器应用架构之间的互联&#xff0c;减少大量容器部署的成本 Docker"三剑客"编排部署 工具︰ docker machine 用于创建和管理docker host docker compose 通过一个文件定义复杂的容器应用之间的关系 容器与容…

【FMCW系统性能参数之测量精度公式推导】

本文编辑&#xff1a;调皮哥的小助理 连续多篇文章都在说FMCW雷达系统性能参数这个事儿&#xff0c;如&#xff1a; &#xff08;1&#xff09;从奈奎斯特采样定理推导FMCW雷达系统性能参数 &#xff08;2&#xff09;从FMCW毫米波雷达系统的性能参数理解4D成像毫米波雷达的设…

深度学习语义分割篇——FCN原理详解篇

&#x1f34a;作者简介&#xff1a;秃头小苏&#xff0c;致力于用最通俗的语言描述问题 &#x1f34a;往期回顾&#xff1a;目标检测系列——开山之作RCNN原理详解    目标检测系列——Fast R-CNN原理详解    目标检测系列——Faster R-CNN原理详解 &#x1f34a;近期目标&…

Unity --- 3d数学 --- 坐标系统

1.世界坐标系是固定不动的 2.每一个游戏物体在世界坐标系中都有对应的坐标和方向 1.轴心点的位置不是固定的&#xff0c;是可以人为设定的 1.Screen Space --- 屏幕坐标 2.我们看到的屏幕其实就是相机所在的平面的位置 --- 而屏幕坐标系的Z其实就是游戏中的物体到相机平面的…

GDOUCTF

WEB hate eat snake 这是一个JS的题目&#xff0c;但是这个题目好像有点奇怪&#xff0c;不是很理解&#xff0c;当时我找到了我寝室JS的大哥&#xff0c;跟大哥说了一下我的思路&#xff0c;就是他根据这个time然后/1000转化为秒&#xff0c;就当作是我们玩游戏的一个分数&a…

速卖通韩国下载量再次登顶,7500万投资换来回报

韩国市场&#xff0c;还是一片蓝海。 速卖通终于等到了回报。 近日&#xff0c;数据平台 Data ai 显示&#xff0c;3 月 9 日以来&#xff0c;速卖通再次成为韩国购物 App 下载量第一名&#xff0c;超过当地电商平台 Coupang。 这或许和速卖通近日在韩国的布局有关。 前些天…

使用File System Access API 让浏览器可以操作文件

使用File System Access API 让浏览器可以操作文件 在早期我们开始学习前端三件套时&#xff0c;经常会听到这样的说法&#xff1a;浏览器是一个沙盒&#xff0c;它不允许我们操作本地文件&#xff0c;但是现在这个说法已经不再适用了&#xff0c;因为我们可以使用 File Syste…

2023接口自动化测试,完整入门篇

1. 什么是接口测试 顾名思义&#xff0c;接口测试是对系统或组件之间的接口进行测试&#xff0c;主要是校验数据的交换&#xff0c;传递和控制管理过程&#xff0c;以及相互逻辑依赖关系。其中接口协议分为HTTP,WebService,Dubbo,Thrift,Socket等类型&#xff0c;测试类型又主…

BBR算法

BBR算法 简述 bbr算法为google在2016年提出&#xff0c;用于改善tcp的性能&#xff0c;提升稳定性&#xff0c;降低延迟&#xff0c;更好地应对网络损伤。在整个算法调节周期中&#xff0c;bbr算法都在尽力维持最大bw和最小rtt。 对比传统的tcp算法 传统算法不能区分是拥塞导…

【RabbitMQ】Java操作RabbitMQ之入门Demo

目录 一、项目创建 二、生产者 三、消费者 一、项目创建 我们先在idea里创建两个Maven项目一个项目作为生产者&#xff0c;另一个作为消费者。创建完成后&#xff0c;在各自的pom.xml文件里引入Java使用RabbitMQ的依赖 <dependency><groupId>com.rabbitmq</g…

Android 单位和尺寸 以及ViewPager的使用

一 px 和 pt 1 px pixels 像素点 2 pt point 一个标准的长度单位&#xff0c;1pt 1/72英寸&#xff0c;用于印刷业&#xff0c;非常简单易用。 二 dp 和 sp 1 dp 就是 dip device independent pixels(设备独立像素) 不同设备有不同的显示效果。这个和设备硬件有关系&…

【数学推导找规律】全排列的价值【蓝桥杯13届】

欢迎观看我的博客&#xff0c;如有问题交流&#xff0c;欢迎评论区留言&#xff0c;一定尽快回复&#xff01;&#xff08;大家可以去看我的专栏&#xff0c;是所有文章的目录&#xff09;   文章字体风格&#xff1a; 红色文字表示&#xff1a;重难点★✔ 蓝色文字表示&#…

ChatGPT资讯—2023.4.14

一、 最新资讯 1. 国内大模型&#xff1a; 4月8日&#xff0c;华为云人工智能领域首席科学家田奇首次介绍了华为“盘古大模型”的进展及其应用。 紧接着4月10日&#xff0c;一天内三个大模型争相“官宣”&#xff0c;包括搜狗创始人王小川宣布即将投入创业的大模型产品名为“…

机器学习 day04(梯度下降算法,学习率,偏导数)

梯度下降 我们可以用一种更系统的方法&#xff0c;来找到一组w&#xff0c;b&#xff0c;使成本函数的值最小。这个方法叫梯度下降算法&#xff0c;它可用于最小化任何函数&#xff0c;不仅仅包括线性回归的成本函数&#xff0c;也包括两个以上参数的其他成本函数在线性回归中…

2023最新面试题-Java-4

Date相关 1. java8的Date相关API&#xff1a; 常用 api 1、 获取当前日期 LocalDate.now() 2、创建日期 LocalDate date LocalDate.of(2020, 9, 21) 3、获取年份 date.getYear()//通过 TemporalField 接口的实现枚举类 ChronoField.YEAR 获取年份 date.get(ChronoFie…

车载通信——J1939 DM1

诊断故障代码&#xff08;DTC&#xff09;由4 个独立域构成&#xff1a; a. 可疑参数的编号(SPN) 19位 b. 故障模式标志(FMI) 5位 c. 发生次数(OC) 7位 d. 可疑参数编号的转化方式(CM) 1 位 Byte1 – Lamp Status Bits1 – 2 Protection Lamp 保护灯状态 …

基于 NIOSII 软核的流水灯实验

文章目录一、硬件部分设计1、进行 Qsys 系统设计二、逻辑连接三、软件设计四、总结一、硬件部分设计 1、进行 Qsys 系统设计 新建kernel.qsys文件&#xff1a; 设置clk时钟&#xff1a; 添加 Nios II 其余选项保持默认 添加 jtag uart 接口 添加片上存储器 On-Chip Memory(R…

【C++高级】手写线程池项目-经典死锁问题分析-简历项目输出指导

作为五大池之一&#xff0c; 线程池的应用非常广 泛&#xff0c;不管是客户端程序&#xff0c;还是后台服务程序&#xff0c;掌握线程池&#xff0c;是提高业务处理能力的必备模块 本课程将带你从零开始&#xff0c;设计一个支持fixed和cached模式的线程池&#xff0c;玩转C11、…

使用FRP(快速反向代理)实现内网穿透——以腾讯云服务器为例

一、FRP简介 FRP&#xff0c;即快速反向代理技术&#xff08;fast reverse proxy&#xff09;。本文的FRP程序是基于github开源项目GitHub - fatedier/frp。当前&#xff0c;该程序可实现&#xff1a;“将位于 NAT 或防火墙后面的本地服务器暴露给互联网”。它目前支持 TCP 和…