1.动态代理 1.1什么是动态代理? 动态代理(理解) 基于反射机制 举个例子,生活中一般在打官司的时候都会请代理律师,为什么要请律师呢?是因为开庭的时候大部人对于打官司没有经验,只会说出自己案件的陈述,并不会根据法律等争取自己权益
动态代理(理解) 基于反射机制
举个例子,生活中一般在打官司的时候都会请代理律师,为什么要请律师呢?是因为开庭的时候大部人对于打官司没有经验,只会说出自己案件的陈述,并不会根据法律等争取自己权益的最大化,此时就可以请律师帮助自己不仅完成对案件的陈述,还能争取权益最大化。那么Java中也是一样,如果要对功能进行增强就可以使用动态代理。
我们知道spring是通过jdk或者CGLib实现动态代理的,今天我们讨论一下JDK实现动态代理的原理。
相比于静态代理(在静态代理中,对于类的每一个接口,我们都要单独写一个代理类),动态代理在创建代理对象上更加的灵活。
有需求,有问题,才会有解决方法和改进创新。那么产生动态代理的问题根源或者需求是什么呢?在静态代理中,由于每个接口都需要我们单独的写一个代理类,比较麻烦,因此我们就想,我们能不能写一个类,我们只需要把委托对象(目标对象),还有全部接口(共同行为,其实委托对象中就已经包含接口了)作为参数传给这个类的方法,然后这个方法就可以给我们返回一个我们想要的代理对象呢,并且这个代理对象可以给我们代理全部的共同行为,像是租房,结婚等?
先说一个需要注意的点:JDK动态代理的目标对象必须要有接口实现,也就是说:委托类必须要继承接口。
在JDK中,有一个Proxy类(名词,代理人)。Proxy类是专门完成代理的操作类,可以通过此类为一个或多个接口动态的生成实现类(对这个类的其他方法我了解的也不是很多,我们可以看JDK的在线api文档,百度搜一下好像挺多的)。这个类提供的有一个静态方法:newProxyInstance()方法。这个方法的目的就是给我们的目标对象(委托对象)返回一个代理对象。
newProxyInstance()方法需要有三个参数:
下面粘贴一张图片:
- jdk动态代理(理解):使用java反射包中的类和接口实现动态代理的功能,反射包java.lang.reflect,里面有三个类:InvocationHandler,Method,Proxy
- cglib动态代理(了解): cglib是第三方的工具库,创建代理对象
CGLB动态代理即Code Generation Library,是一个开源的第三方工具库,其原理是继承,去生成目标类的子类对象,这样对子类的功能进行增强。但是要求:目标类不能用final修饰,目标类中的方法也不能被final修饰。
CGLB动态代理的效率要大于JDK动态代理的效率。
package com.zhao.service.impl;import com.zhao.service.Actor;public class CXK implements Actor { @Override public void sing(int money) { System.out.println("听"+money); } @Override public String dance() { System.out.println("吹灰舞"); return "发放签名"; } @Override public void rap() { System.out.println("练习时长两年"); }}
这样操作发现出现了大量重复的代码,如果有十处、一百处需要同样的处理那么代码需要重复十次、一百次。当然我们可以把这些功能封装成一个增强方法,然后在功能方法中进行调用,但是也出现了方法的十处、一百处的调用操作,一旦增强方法名字改变,就需要完成所有调用处代码的修改。或者有一天不需要这些增强操作了,就再次需要在这十处、一百处删除方法调用。所以这种操作不适用于大型的项目开发的需求,此时我们就必须使用Java的动态代理机制。
在Java开发中如果一个类中的方法在基本功能之外需要进行功能扩充或者功能增强,如:事务控制、权限判断、日志记录等等操作,此时可以使用动态代理机制。
Java的JDK中Proxy类可以实现基于接口的动态代理,实现步骤示例如下:
package com.zhao.service;public interface Actor { //唱歌 void sing(int money); //跳舞 String dance(); //rap void rap();}
package com.zhao.service.impl;import com.zhao.service.Actor;public class CXK implements Actor { @Override public void sing(int money) { System.out.println("听"+money); } @Override public String dance() { System.out.println("吹灰舞"); return "发放签名"; } @Override public void rap() { System.out.println("练习时长两年"); }}
package com.zhao.advice;import com.zhao.service.Actor;import com.zhao.service.impl.CXK;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class JJGS { public static void main(String[] args) { //1.创建被代理类的对象----具体的人物cxk Actor cxk=new CXK(); //2.创建代理对象--- 具体某人为上面cxk Actor jjr=(Actor) Proxy.newProxyInstance(CXK.class.getClassLoader(), CXK.class.getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //被代理对象方法的执行,并获得返回值 Object result=null; result=method.invoke(cxk,args); System.out.println("演出后的增强:结算费用并纳税"); return result; } }); //3.执行功能// jjr.sing(5000); String dance = jjr.dance(); System.out.println(dance); }}
测试结果:
package com.zhao.service.impl;public class Actor { public void sing(int money) { System.out.println("听" + money); } public String dance(int money) { System.out.println("吹灰舞"+money); return "发放签名"; } public void rap(int money) { System.out.println("练习时长两年"+money); }}
package com.zhao.advice;import com.zhao.service.impl.Actor;import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;public class JJGss { public static void main(String[] args) { //1.被代理的对象 Actor actor=new Actor(); //2.使用CGLIb的Enhancer类创建代理对象 Actor proxyActor = (Actor) Enhancer.create(Actor.class, new MethodInterceptor() { @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { String methodName=method.getName(); String money=args[0]; Object result=null; if(methodName.equals("danceAct")){ System.out.println("对方法执行前进性代理增强..."); result=method.invoke(actor,money); System.out.println("对方法执行后进性代理增强..."); return result; } return result; } }); // proxyActor.dance(3000); }}
来源地址:https://blog.csdn.net/m0_73671382/article/details/129876351
--结束END--
本文标题: Java——JDK动态代理
本文链接: https://lsjlt.com/news/386669.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-04-01
2024-04-03
2024-04-03
2024-01-21
2024-01-21
2024-01-21
2024-01-21
2023-12-23
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0