动态代理
动态代理
1. 什么是代理模式
代理模式是一种设计模式,就是通过代理对象操作原对象并且给原对象添加一些额外功能。
代理模式分为静态代理和动态代理两种
2. 静态代理
静态代理中,我们对目标对象的每个方法的增强都是手动完成的(*后面会具体演示代码*),非常不灵活(*比如接口一旦新增加方法,目标对象和代理对象都要进行修改*)且麻烦(*需要对每个目标类都单独写一个代理类*)。 实际应用场景非常非常少,日常开发几乎看不到使用静态代理的场景。
上面我们是从实现和应用角度来说的静态代理,从 JVM 层面来说, 静态代理在编译时就将接口、实现类、代理类这些都变成了一个个实际的 class 文件。
----- 著作权归Guide哥所有。 链接: https://javaguide.cn/java/basis/proxy/#_1-代理模式
3. 动态代理
动态代理无序在编码阶段为每一个带代理类编码代理类,通过字节码技术等,在运行时动态生成代理对象。
常见的动态代理技术有:
- jdk动态代理
- cglib动态代理
3.1 jdk动态代理
Proxy的newProxyInstance(ClassLoader classloader,Class<?>[] interfaces,InvocationHandler handler);
这个方法一共有 3 个参数:
- loader :类加载器,用于加载代理对象。
- interfaces : 被代理类实现的一些接口;
- h : 实现了
InvocationHandler接口的对象;
InvocationHandler类
public interface InvocationHandler {
/**
* 当你使用代理对象调用方法的时候实际会调用到这个方法
*/
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
使用步骤:
- 定义一个接口及其实现类;
- 自定义
InvocationHandler并重写invoke方法,在invoke方法中我们会调用原生方法(被代理类的方法)并自定义一些处理逻辑; - 通过
Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)方法创建代理对象;
代码示例:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
interface SendMessage{
void send();
}
class MyProxy implements SendMessage{
@Override
public void send() {
System.out.println ("发送短信");
}
}
class MyInvocationHandler implements InvocationHandler{
private Object object;
public MyInvocationHandler(Object o){
this.object = o;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println ("执行之前统计");
Object re = method.invoke (object,args);
System.out.println ("执行之后统计");
return re;
}
}
public class ProxyExample {
public static void main(String[] args) {
MyProxy p = new MyProxy ();
InvocationHandler handler = new MyInvocationHandler (p);
SendMessage o = (SendMessage) Proxy.newProxyInstance (p.getClass ().getClassLoader (), p.getClass ().getInterfaces (), handler);
o.send ();
}
}
3.2 cglib动态代理
3.3 jdk 和 cglib的对比
JDK 动态代理只能代理实现了接口的类或者直接代理接口,而 CGLIB 可以代理未实现任何接口的类。 另外, CGLIB 动态代理是通过生成一个被代理类的子类来拦截被代理类的方法调用,因此不能代理声明为 final 类型的类和方法。
就二者的效率来说,大部分情况都是 JDK 动态代理更优秀,随着 JDK 版本的升级,这个优势更加明显。
----- 著作权归Guide哥所有。 链接: https://javaguide.cn/java/basis/proxy/#_3-2-cglib-动态代理机制

浙公网安备 33010602011771号