Java动态代理()
Java动态代理
在学习Spring的时候,对于书上经常讲的动态代理就是一知半解的,学习Spring框架的时候也是囫囵吞枣的
接下来让我来整理一下动态代理的学习思路
首先,什么是动态代理:
照我的理解就是; A想要调用B,但是它不直接调用B,它利用反射的机制创建了一个C,然后让C调用B,在C这个类调用B之前和之后呢,可以分别实现一些登录验证,打印日志之类的操作,然后再让A调用C,这个时候A即调用了B,且A和B的耦合度还降低了,还实现了更多的功能,简直一举两得,好处多多.
代理类在程序运行时创建的代理方式被称为 动态代理。 也就是说,这种情况下,代理类并不是在Java代码中定义的,而是在运行时根据我们在Java代码中的“指示”动态生成的。相比于静态代理, 动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类的函数。
接下来我先来创建一个ArrayList的动态代理,熟悉一下代理流程
package cn.ycl.test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
public class test4 {
public static void main(String[] args) {
// 第一步,创建一个ArrayList对象
List<String> list = new ArrayList<String>();
// 第二步,利用Proxy代理类的newProxyInstance方法,生成一个目标代理类
Object newProxyInstance = Proxy.newProxyInstance(list.getClass().getClassLoader(),
list.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
return method.invoke(list, args);
}
});
// 第三步,利用list的代理类newProxyInstance调用list的方法
boolean add = ((List<String>) newProxyInstance).add("你好");
System.out.println(list);
}
}
结果:
好的,写完这个基本的ArrayList动态代理我感觉自己对代理流程更加清晰了,接下来就来搞一波,复杂一点的,完成前置增强和后置增强吧。
步骤:
①定义一个YCL接口
②定义一个YuanChangLiang类
③定义一个生产代理对象并调用的ProxyYuanChangLiang类
首先第一步,定义一个YCL接口
package cn.ycl.test;
//接口名字是我名字的拼音缩写,6不6?
public interface YCL {
void coding();
void playing();
}
第二步,定义一个YuanChangLiang类
package cn.ycl.test;
//这个类就相当于我前面说的 B
public class YuanChangLiang implements YCL{
@Override
public void coding() {
// TODO Auto-generated method stub
System.out.println("袁昌亮正在敲代码。。。");
}
@Override
public void playing() {
// TODO Auto-generated method stub
System.out.println("袁昌亮正在混吃等死。。。");
}
}
第三步.定义一个生产代理对象并调用的ProxyYuanChangLiang类
package cn.ycl.test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//这个类就相当于我前面说的 A
public class ProxyYuanChangLiang {
public static void main(String[] args) {
//第一步, 按照前面写ArrayList的动态代理的经验,创建被代理类的实例对象
YuanChangLiang ycl = new YuanChangLiang();
// 第二步,利用Proxy代理类生成代理对象,这个实例对象就相当于我前面说的 C
YCL yclProxy = (YCL) Proxy.newProxyInstance(ycl.getClass().getClassLoader(), ycl.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 在方法调用之前就是前置增强啦。。
if (method.getName().equals("coding")) {
System.out.println("hello,我是在打代码前面吗?");
return method.invoke(ycl, args);
}
if (method.getName().equals("playing")) {
// 在方法后面调用就是后置增强啦。。
Object invoke = method.invoke(ycl, args);
System.out.println("hello,我是在混吃等死后面吗?");
return invoke;
}
return null;
}
});
// 第三步,利用代理对象调用YuanChangLiang的方法,easy
yclProxy.coding();
yclProxy.playing();
}
}
结果:
结果可喜,待补充
以上是JDK代理方式,其实动态代理可以分为两种方式,除了JDK代理,还有CGLIB的代理方式,那么两者有什么区别呢。下面是我认为总结的比较好的一张图
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~