动态代理(JDK CGLIB)
动态代理是由静态代理发展而来.
类加载:加载-链接-初始化-使用-卸载.
动态代理就是在加载阶段完成的,类加载可以从指定文件,网络 等加载class文件到运行时数据区 java.lang.class.
静态代理:A需要让C做一件事件,但是只有B能联系到C,那我就交给B让他帮忙代理即可。
动态代理是在底层增强逻辑,用不同方法在运行期间生成不同的class再去进行代理类的类加载然后使用。
JDK代理
使用接口实现方式,运行时,在内存中动态构建出一个类,然后编译,执行。这个类是一次性的,JVM停止,代理类就消失。
$ProxyX的代理类(其中的X是序号,一般默认为0),这代理类由JDK动态构建出来
public class JdkProxyDemo {
interface Foo {
String foo();
}
static class Target implements Foo {
@Override
public String foo() {
System.out.println("target foo");
return "result";
}
}
/**
* jdk代理只能针对接口进行代理
* 内部采用asm技术动态生成字节码()
* @param args
*/
public static void main(String[] args) {
//JDK8之前
System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
//JDK8之后
System.setProperty("jdk.proxy.ProxyGenerator.saveGeneratedFiles", "true");
Target target = new Target();
Foo proxy = (Foo) Proxy.newProxyInstance(JdkProxyDemo.class.getClassLoader(), new Class[]{Foo.class}, new InvocationHandler() {
/**
* @param proxy 代理对象自身
* @param method 正在执行的方法
* @param args 方法参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before");
Object result = method.invoke(target, args);
//代理类返回的是目标方法执行的结果
System.out.println(result+" after");
return result;
}
});
proxy.foo();
}
}
上述代理类生成
final class $Proxy0 extends java.lang.reflect.Proxy implements com.algorithm.jdk.JdkProxyDemo.Foo {
private static java.lang.reflect.Method m1;
private static java.lang.reflect.Method m2;
private static java.lang.reflect.Method m3;
private static java.lang.reflect.Method m0;
public $Proxy0(java.lang.reflect.InvocationHandler invocationHandler) { /* compiled code */ }
public final boolean equals(java.lang.Object o) { /* compiled code */ }
public final java.lang.String toString() { /* compiled code */ }
public final java.lang.String foo() { /* compiled code */ }
public final int hashCode() { /* compiled code */ }
}
从上面应该能反映出 JDK代理为啥只支持接口代理了 因为在实现原理上继承了java.lang.reflect.Proxy,而Java类是单继承。
CGLIB代理
public class CglibProxyDemo implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("before");
Object invoke = methodProxy.invokeSuper(o, objects);
System.out.println("after");
return invoke;
}
}
class Zoo {
public void show() {
System.out.println("zoo");
}
}
class TestCglib {
public static void main(String[] args) {
//在指定目录下生成动态代理类
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\java");
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Zoo.class);
enhancer.setCallback(new CglibProxyDemo());
Zoo proxyDog = (Zoo)enhancer.create();
proxyDog.show();
}
}
CGLIB代理会生成代理类class 如图,CGLIB原理是继承代理类
想看内容的同学可以使用反编译工具进行查看。
本文来自博客园,作者:苏子墨,转载请注明原文链接:https://www.cnblogs.com/li-xiaotian/p/16595232.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix