当前位置: 首页 > news >正文

JavaDemo——使用CGLIB动态代理

cglib动态代理和jdk动态代理是java中常用的两种动态代理;

  • cglib动态代理:基于继承机制,可以代理类或接口,不能代理final类和方法,采用ASM字节码框架生成子类,性能好,占用内存多;
  • jdk动态代理:基于接口反射机制,必须依赖接口,使用反射,有一定性能消耗,占内存低;

cglib使用方法:

  1. 先maven导入:

    <dependency>

    <groupId>cglib</groupId>

    <artifactId>cglib</artifactId>

    <version>3.3.0</version>

    </dependency>

  2. 实例化一个Enhancer对象;
  3. 使用setSuperclass()或者setInterfaces()设置代理类或接口;
  4. 使用setCallback()设置代理方法,或者setCallbacks()和setCallbackFilter()搭配使用;

关于public void setCallback(final Callback callback)的参数Callback接口:

  • NoOp:使用NoOp.INSTANCE表示直接调用原始方法;
  • MethodInterceptor:比较常用增强方法,可以使用参数MethodProxy的invokeSuper()方法调用父类方法,直接使用索引方式绕过反射,提升性能;(返回值为方法返回值)
  • FixedValue:直接返回固定值;(返回值为方法返回值)
  • LazyLoader:只会在第一次的时候调用,后续复用该对象;(返回值为真实代理对象)
  • Dispatcher:每次调用都会生成新的对象;(返回值为真实代理对象)
  • ProxyRefDispatcher:类似Dispatcher,不过可以从参数里获得proxy对象;(返回值为真实代理对象)
  • InvocationHandler:类似jdk的动态代理,参数里没有MethodProxy,只能使用method.invoke()反射调用;(返回值为方法返回值)

关于public void setCallbackFilter(CallbackFilter filter)的参数CallbackFilter接口:

实现int accept(Method method)方法,返回值为public void setCallbacks(Callback[] callbacks)参数中数组的索引,可以根据Method条件返回不同的索引从而调用Callback[]中不同索引的回调方法;

测试代码:

测试类ABC.java:

package testcglib;public class ABC {private String str;public ABC(String s) {System.out.println("newABC,s=" + s);this.str = s;}public void a() {System.out.println("ABC -> a()");}public void b() {System.out.println("ABC -> b()");}public String c(String arg) {return this.str + arg;}public int d(int x, int y) {return x + y;}public void lazyloader() {}public void dispatcher() {System.out.println("ABC -> dispatcher()");}public void testProxydispatcher() {System.out.println("ABC -> proxydispatcher()");}
}

ABC.java的子类ChABC.java:

package testcglib;public class ChABC extends ABC {public ChABC(String s) {super(s);System.out.println("newChABC(" + s + ")");}@Overridepublic void a() {System.out.println("ChABC -> a()");}@Overridepublic void lazyloader() {System.out.println("chabc -> lazyloader()");}@Overridepublic void dispatcher() {System.out.println("chabc -> dispatcher()");}}

测试主类:

/*** 2025年7月10日14:18:07*/
package testcglib;import java.lang.reflect.Method;import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.CallbackFilter;
import net.sf.cglib.proxy.Dispatcher;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.FixedValue;
import net.sf.cglib.proxy.InvocationHandler;
import net.sf.cglib.proxy.LazyLoader;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import net.sf.cglib.proxy.NoOp;
import net.sf.cglib.proxy.ProxyRefDispatcher;/*** @author XWF*/
public class TestCGLIB {/*** @param args*/public static void main(String[] args) {Enhancer enhancer = new Enhancer();// 设置代理类或者接口enhancer.setSuperclass(ABC.class);
//		enhancer.setInterfaces(new Class[] {});// 设置代理方法
//		enhancer.setCallback(null);enhancer.setCallbacks(new Callback[] {NoOp.INSTANCE, // 第0个,调用原方法new MethodInterceptor() { // 第1个代理方法@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("1-callback-method:" + method.getName());System.out.println("1-before");int a = (int) args[0];int b = (int) args[1];args[0] = a * 10;args[1] = b * 10;return proxy.invokeSuper(obj, args); // 返回方法结果(使用直接索引绕过反射)}},new MethodInterceptor() { // 第2个代理方法@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("2-callback-method:" + method.getName());System.out.println("2-before");Object res = proxy.invokeSuper(obj, args);System.out.println("2-after");return res;}},new FixedValue() { // 第3个,直接返回固定值@Overridepublic Object loadObject() throws Exception {System.out.println("3-fixedvalue");return "FIXED"; // 返回方法结果}},new InvocationHandler() { // 4 跟JDK的动态代理类似@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {return method.invoke(proxy, args); // 返回方法结果(反射)}},new LazyLoader() { // 5 只第一次调用一次@Overridepublic Object loadObject() throws Exception {return new ChABC("LazyLoader"); // 返回真实代理对象,第一次生成,后续调用复用}},new Dispatcher() { // 6 每次都调用@Overridepublic Object loadObject() throws Exception {return new ABC("Dispatcher"); // 返回真实代理对象,每次都生成新的}},new ProxyRefDispatcher() { // 7 相比Dispatcher,可以拿到proxy对象@Overridepublic Object loadObject(Object proxy) throws Exception {System.out.println("7-proxy:" + proxy.getClass());return new ChABC("proxy"); // 返回真实代理对象}}});// 指定调用哪个代理方法enhancer.setCallbackFilter(new CallbackFilter() {@Overridepublic int accept(Method method) { // 返回值为调用回调方法的索引if("a".equals(method.getName())) { // 名字为“a”的方法调用第0个return 0;} else if("c".equals(method.getName())) { // 名字为“c”的方法调用第3个return 3;} else if("d".equals(method.getName())) { // 名字为“d”的方法调用第1个return 1;} else if("lazyloader".equals(method.getName())) {return 5;} else if("dispatcher".equals(method.getName())) {return 6;} else if("testProxydispatcher".equals(method.getName())) {return 7;} else { // 其余方法都调用第2个return 2;}}});//		ABC obj = (ABC) enhancer.create(); // 使用无参构造方法System.out.println("  使用有参构造方法");ABC obj = (ABC) enhancer.create(new Class[] {String.class}, new Object[] {"abc"});System.out.println("  调用a方法");obj.a(); // 直接调用原方法System.out.println("  调用b方法");obj.b();System.out.println("  调用c方法");System.out.println("c()返回:" + obj.c("xyz")); // 返回固定值System.out.println("  调用d方法");System.out.println("d()返回:" + obj.d(2, 3));System.out.println("  调用lazyloader方法");obj.lazyloader(); // 第一次newobj.lazyloader();obj.lazyloader();System.out.println("  调用dispatcher方法");obj.dispatcher(); // 每次都newobj.dispatcher();obj.dispatcher();System.out.println("  调用testProxydispatcher方法");obj.testProxydispatcher(); // 每次都newobj.testProxydispatcher();}}

执行结果:


文章转载自:
http://pandowdy.sxnf.com.cn
http://superscribe.sxnf.com.cn
http://fructiferous.sxnf.com.cn
http://nilgai.sxnf.com.cn
http://eroticism.sxnf.com.cn
http://ngbandi.sxnf.com.cn
http://pecksniff.sxnf.com.cn
http://crump.sxnf.com.cn
http://sinhala.sxnf.com.cn
http://pretermission.sxnf.com.cn
http://homeless.sxnf.com.cn
http://occurent.sxnf.com.cn
http://deformity.sxnf.com.cn
http://redeye.sxnf.com.cn
http://opisthograph.sxnf.com.cn
http://nebulated.sxnf.com.cn
http://palynomorph.sxnf.com.cn
http://teutophobe.sxnf.com.cn
http://mirk.sxnf.com.cn
http://operculiform.sxnf.com.cn
http://chid.sxnf.com.cn
http://lockram.sxnf.com.cn
http://insectifuge.sxnf.com.cn
http://difficile.sxnf.com.cn
http://rheobase.sxnf.com.cn
http://micturition.sxnf.com.cn
http://carshops.sxnf.com.cn
http://equivoque.sxnf.com.cn
http://advertise.sxnf.com.cn
http://linguistry.sxnf.com.cn
http://www.dtcms.com/a/280395.html

相关文章:

  • I3C通信驱动开发注意事项
  • 【雅思播客016】New Year Resolution 新年决心
  • docker搭建freeswitch实现点对点视频,多人视频
  • 极致cms多语言建站|设置主站默认语言与设置后台固定语言为中文
  • 嵌入式学习-PyTorch(4)-day21
  • 多相机depth-rgb图组完整性分拣器_MATLAB实现
  • @[TOC](模拟) # 1.替换所有的问号(easy)
  • 学C++做游戏,先搞懂这些基础要点
  • 《大数据技术原理与应用》实验报告六 Flink编程实践
  • 使用JS编写用户信息采集表单
  • 【Python3-Django】快速掌握DRF:ModelViewSet实战指南
  • OneCode 3.0 从0到1干货——AIGC及MCP注解驱动开发物联网AI决策应用
  • 全新 Python 项目托管到 Gitee 私有仓库完整流程(带详细命令注释)
  • OpenVINO initialization error: Failed to find plugins.xml file
  • uv 使用指导文档
  • 【机器学习深度学习】LoRA 微调详解:大模型时代的高效适配利器
  • BlueLotus XSS管理后台使用指南
  • GeoTools 工厂设计模式
  • 传输协议和消息队列
  • AR眼镜:重塑医学教育,开启智能教学新时代
  • 同步辐射XAFS和XRD协同用于高熵合金的研究应用
  • 香港站群服务器租用:为什么需要选择不同C类IP?
  • python的广东省家庭旅游接待信息管理系统
  • k8s之Attach 和 Mount
  • C++回顾 Day7
  • k8s之Snapshots 详解
  • Linux C IO多路复用
  • 静态补丁脚本 - 修改 libtolua.so
  • Unity音游开发全指南:模板与免费资源高效构建节奏游戏
  • Ubuntu 22.04 安装 mysql-server服务端