Spring自定义BeanPostProcessor实现bean的代理Java动态代理知识
上文:https://blog.csdn.net/qq_26437925/article/details/145241149 中大致了解了spring aop的代理的实现,其实就是有个BeanPostProcessor代理了bean对象。顺便复习下java代理相关知识
目录
- 自定义BeanPostProcessor实现aop
- Java动态代理知识
- 动态代理的几种实现方式
- Java基于接口的动态代理
- 例子代码和输出
- 为什么一定要有接口
自定义BeanPostProcessor实现aop
bean A:
@Service
public class A {public A() {System.out.println("A()");}public void say(){System.out.println("say A");}
}
- beanPostProcessor
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Service;import java.lang.reflect.Method;@Service
public class ABeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (beanName.equals("a")) {System.out.println("a BeanPostProcessor postProcessAfterInitialization");return getProxy(bean);}return bean;}public Object getProxy(Object targetObject) {Enhancer enhancer = new Enhancer();Class<?> superClass = targetObject.getClass();enhancer.setSuperclass(superClass);MethodInterceptor interceptor = new MethodInterceptor() {@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("cglib before...");Object res = methodProxy.invokeSuper(o, objects);return res;}};enhancer.setCallback(interceptor);Object targetProxy = enhancer.create();return targetProxy;}
}
基于cglib代理
<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.3.0</version>
</dependency>
- config类不用EnableAspectJAutoProxy了
@Configuration
@ComponentScan("com.aop.dependency")
public class ConfigOne {
}
- 测试类
@Test
public void test() throws Exception {ApplicationContext ctx =new AnnotationConfigApplicationContext(ConfigOne.class);A a = (A) ctx.getBean("a");a.say();((AnnotationConfigApplicationContext) ctx).close();
}
测试输出

方法执行的代理输出正常
因为Cglib是用父类继承,新增了一个完整的class字节码。所以可以看到A()构造函数执行了两次, 一次是spring bean生命周期的实例化,一次则是Cglib创建出代理对象执行的。
Java动态代理知识
动态代理的几种实现方式
java对象的产生流程如下:
编译 ClassLoader加载 实例化| | || | || | |.java ------> .class(字节码) ---------------> Class Obj ---------> Class Instance
正因为这个流程,所以在你编写Java代码到运行时具体的Java对象,这个过程可以进行很多操作去改变
常见的动态代理技术如下:
- Java Proxy(接口&反射机制,新增一个完整的class字节码:继承Proxy,实现接口类)
- CGLib(父类继承,新增一个完整的class字节码)
- AspectJ(修改现有字节码)
- JavaAgent(修改现有字节码)
- Byte Buddy,提供api可以在Java应用程序运行时创建和修改Java类,使用例子:https://doctording.blog.csdn.net/article/details/114787289
Java基于接口的动态代理
例子代码和输出
- 接口
public interface Go {void out();
}
- 其中一个实现类
public class CarGo implements Go{@Overridepublic void out() {System.out.println("car go");}
}
- 代理handler
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;class GoProxyHandler implements InvocationHandler {private Go go;private Go goProxy;public GoProxyHandler(Go go) {this.go = go;// newProxyInstance方法的三个参数:// 1. 用哪个类加载器去加载代理对象// 2. 动态代理类需要实现的接口// 3. 动态代理方法在执行时,会调用this里面的invoke方法去执行this.goProxy = (Go)Proxy.newProxyInstance(Go.class.getClassLoader(),new Class<?>[] { Go.class },this);}// 实现方法的增强, 对PayService内部的所有方法都能应用该代理方法@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {String methodName = method.getName();System.out.println("before go " + methodName);// 这里注意是go,即实际的实现类Object rs = method.invoke(go, args);System.out.println("after go " + methodName);return rs;}// 返回原接口的代理对象,通过反射方式new出来的:Proxy.newProxyInstancepublic Go getProxy() {return goProxy;}
}
- 测试代码
public class ProxyTest {public static void main(String[] args) {Go go = new CarGo();GoProxyHandler goProxyHandler = new GoProxyHandler(go);Go goProxy = goProxyHandler.getProxy();goProxy.out();Class<?> clazz = goProxy.getClass();// 输出类的直接超类Class<?> superclass = clazz.getSuperclass();System.out.println("直接超类: " + superclass.getName());// 输出类实现的接口Class<?> interfaces[] = clazz.getInterfaces();System.out.print("实现的接口: ");if (interfaces.length > 0) {System.out.println(Arrays.stream(interfaces).map(Class::getName).collect(Collectors.joining(", ")));} else {System.out.println("无");}}
}

为什么一定要有接口
直观的来看,可以看到最后的代理类是继承了 java.lang.reflect.Proxy,实现了自己的接口
而java是单继承,可实现多接口的模式。
假如没有接口,而又要改变这个类,则必然要继承这个类,而java动态代理的实现必须要继承java.lang.reflect.Proxy,这就变成多继承了,不允许。
另外接口本身就是一种行为规范,基于接口可以有多种实现类。所以java自身的这种动态代理没有问题。
相关文章:
Spring自定义BeanPostProcessor实现bean的代理Java动态代理知识
上文:https://blog.csdn.net/qq_26437925/article/details/145241149 中大致了解了spring aop的代理的实现,其实就是有个BeanPostProcessor代理了bean对象。顺便复习下java代理相关知识 目录 自定义BeanPostProcessor实现aopJava动态代理知识动态代理的几…...
三篇物联网漏洞挖掘综述
由于物联网设备存在硬件资源受限、硬件复杂异构, 代码、文档未公开的问题, 物联网设备的漏洞挖掘存在较大的挑战: 硬件资源受限性: 通用动态二进分析技术需要在运行程序外围实施监控分析。由于物联网设备存储资源(存储)的受限性,…...
Pytorch深度学习指南 卷I --编程基础(A Beginner‘s Guide) 第1章 一个简单的回归
本章正式开始使用pytorch的接口来实现对应的numpy的学习的过程,来学习模型的实现,我们会介绍numpy是如何学习的,以及我们如何一步步的通过torch的接口来实现简单化的过程,优雅的展示我们的代码,已经我们的代码完成的事…...
【EXCEL_VBA_实战】多工作薄合并深入理解
工作背景:多个工作薄存在冲突的名称,需快速合并 困难点:工作表移动复制时,若有冲突的名称,会不断弹出对话框待人工确认 思路:利用代码确认弹出的对话框 关键代码:Application.DisplayAlerts …...
mysql之表的外键约束
MySQL表的外键约束详细介绍及代码示例 外键约束是数据库中用于维护数据完整性和一致性的重要机制。它确保一个表中的数据与另一个表中的数据相关联,防止无效的数据引用。本文将详细介绍了外键约束的各个方面,并通过具体的代码示例进行演示。 1. 外键约束…...
Tuning the Go HTTP Client Settings
记录一次Go HTTP Client TIME_WAIT的优化 业务流程 分析 通过容器监控发现服务到事件总线的负载均衡之间有大量的短链接,回看一下代码 发送请求的代码 func SendToKEvent(ev *KEvent) error {data, err : json.Marshal(ev.Data)if err ! nil {return err}log.Pri…...
第二十四课 Vue中子组件调用父组件数据
Vue中子组件调用父组件数据 Vue是不建议在不同的组件直接传递值的,我们需要使用props方法来进行组件间的值传递 子组件调用父组件数据 父模板的数据,子组件是无法直接调用的 无法直接调用 1)组件调用顶级对象中的data <div class&quo…...
Jenkins-pipeline语法说明
一. 简述: Jenkins Pipeline 是一种持续集成和持续交付(CI/CD)工具,它允许用户通过代码定义构建、测试和部署流程。 二. 关于jenkinsfile: 1. Sections部分: Pipeline里的Sections通常包含一个或多个Direc…...
小米Vela操作系统开源:AIoT时代的全新引擎
小米近日正式开源了其物联网嵌入式软件平台——Vela操作系统,并将其命名为OpenVela。这一举动在AIoT(人工智能物联网)领域掀起了不小的波澜,也为开发者们提供了一个强大的AI代码生成器和开发平台。OpenVela项目源代码已托管至GitH…...
NodeJs如何做API接口单元测试? --【elpis全栈项目】
NodeJs API接口单元测试 api单元测试需要用到的 assert:断言库 (还要一些断言库比如:Chai)supertest: 模拟http请求 简单的例子: const express require(express); const supertest require(supertest); const assert require(assert);…...
bundletool来特定设备规范的json安装aab包
1、获取自己设备的设备规范json java -jar ./bundletool.jar get-device-spec --outputj:/device-spec.json 2、根据设备规范生成apks包 java -jar ./bundletool.jar build-apks --device-specj:/device-spec.json --bundleapp-dev-release.aab --output随便的文件名.apks -…...
2024年第十五届蓝桥杯青少组国赛(c++)真题—快速分解质因数
快速分解质因数 完整题目和在线测评可点击下方链接前往: 快速分解质因数_C_少儿编程题库学习中心-嗨信奥https://www.hixinao.com/tiku/cpp/show-3781.htmlhttps://www.hixinao.com/tiku/cpp/show-3781.html 若如其他赛事真题可自行前往题库中心查找,题…...
.Net Core微服务入门全纪录(四)——Ocelot-API网关(上)
系列文章目录 1、.Net Core微服务入门系列(一)——项目搭建 2、.Net Core微服务入门全纪录(二)——Consul-服务注册与发现(上) 3、.Net Core微服务入门全纪录(三)——Consul-服务注…...
chrome游览器JSON Formatter插件无效问题排查,FastJsonHttpMessageConverter导致Content-Type返回不正确
问题描述 chrome游览器又一款JSON插件叫JSON Formatter,游览器GET请求调用接口时,如果返回的数据是json格式,则会自动格式化展示,类似这样: 但是今天突然发现怎么也格式化不了,打开一个json文件倒是可以格…...
[Qt]系统相关-网络编程-TCP、UDP、HTTP协议
目录 前言 一、UDP网络编程 1.Qt项目文件 2.UDP类 QUdpSocket QNetworkDatagram 3.UDP回显服务器案例 细节 服务器设计 客户端设计 二、TCP网络编程 1.TCP类 QTcpServer QTcpSocket 2.TCP回显服务器案例 细节 服务器设计 客户端设计 三、HTTP客户端 1.HTTP…...
docker 安装 nginx 详解
在平常的开发工作中,我们经常会用到 nginx,那么在 docker 中 如何安装 nginx呢?又有哪些需要注意的事项呢?简单来说,第一步:拉取 nginx 镜像;第二步:创建 挂载目录并设置 nginx.conf…...
2025年大模型气象预测架构与商业化影响
随着人工智能技术,尤其是大模型(如深度学习、大规模神经网络)的飞速发展,气象预测的传统方法正在经历深刻变革。2025年,气象预测将借助大模型技术进入一个新的阶段。本文将从架构角度详细探讨2025年大模型在气象预测中的应用,并分析其对商业化的潜在影响。 一、2025年大模…...
基于51单片机和ESP8266(01S)、八位数码管、独立按键的WiFi定时器时钟
目录 系列文章目录前言一、效果展示二、原理分析三、各模块代码1、延时函数2、定时器03、串口4、数码管扫描5、独立按键扫描 四、主函数总结 系列文章目录 前言 有三个版本: ①普中开发板版本1:28800bps11.0592MHz,12T ②普中开发板版本2&am…...
Androidstudio 中,project下的.gitignore和module下的.gitignore有什么区别,生效优先级是什么
在 Android Studio 项目中,project 根目录下的 .gitignore 文件和 module 目录下的 .gitignore 文件作用和生效优先级是不同的,理解它们之间的区别非常重要,可以避免不必要的提交和冲突。 1. project 根目录下的 .gitignore: 作…...
python学习笔记3-字符串常用的方法
一、判断(9个): 二、查找和替换(8个) 三、⼤⼩写转换(5个) 四、⽂本对⻬(3个) 五、去除空⽩字符(3个) 六、拆分和连接 (6个࿰…...
【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
VB.net复制Ntag213卡写入UID
本示例使用的发卡器:https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...
JavaScript 数据类型详解
JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型(Primitive) 和 对象类型(Object) 两大类,共 8 种(ES11): 一、原始类型(7种) 1. undefined 定…...
代码规范和架构【立芯理论一】(2025.06.08)
1、代码规范的目标 代码简洁精炼、美观,可持续性好高效率高复用,可移植性好高内聚,低耦合没有冗余规范性,代码有规可循,可以看出自己当时的思考过程特殊排版,特殊语法,特殊指令,必须…...
[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.
ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #:…...
【SpringBoot自动化部署】
SpringBoot自动化部署方法 使用Jenkins进行持续集成与部署 Jenkins是最常用的自动化部署工具之一,能够实现代码拉取、构建、测试和部署的全流程自动化。 配置Jenkins任务时,需要添加Git仓库地址和凭证,设置构建触发器(如GitHub…...
ZYNQ学习记录FPGA(一)ZYNQ简介
一、知识准备 1.一些术语,缩写和概念: 1)ZYNQ全称:ZYNQ7000 All Pgrammable SoC 2)SoC:system on chips(片上系统),对比集成电路的SoB(system on board) 3)ARM:处理器…...
