Java中的动态代理

2021-12-07 16:40:22 浏览数 (1)

Java中的动态代理

实现动态代理方式

Java中的代理方式主要分为两种,一种是基于接口的动态代理,另一种是基于类的动态代理,而基于接口的动态代理有JDK Proxy,基于类的动态代理主要有ASM、cglib,本文主要讲述的是JDK Proxy实现动态代理。

JDK动态代理实现

JDK动态代理基于拦截器和反射实现,使用JDK代理时需要传入被代理类的class。

JDK代理的步骤
  • 创建接口类,并实现接口
  • 自定义Handler去实现JDK的InvocationHandler接口
  • 在invoke方法中写入自定义逻辑,以扩展原有逻辑
  • 使用Proxy创建代理对象
  • 使用代理对象调用原对象的方法
talk is cheap,show me your code.
代码语言:javascript复制
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;


/**
 * @author Liutx
 * @date 2021/3/6 10:57
 * @Description 使用JDK的动态代理方式
 */

public class MyDynamicProxy {
    public static void main(String[] args) {
        HelloImpl hello = new HelloImpl();
        MyInvocationHandler handler = new MyInvocationHandler(hello);
        // 构造代码实例
        Hello proxyHello = (Hello) Proxy.newProxyInstance(HelloImpl.class.getClassLoader(), HelloImpl.class.getInterfaces(), handler);
        // 调用代理方法
        proxyHello.sayHello();
    }
}

interface Hello {
    void sayHello();
}

class HelloImpl implements Hello {
    @Override
    public void sayHello() {
        //原方法逻辑
        System.out.println("Hello World");
    }
}

/**
 * 使用JDK Proxy代理为应用插入额外的逻辑
 */
class MyInvocationHandler implements InvocationHandler {
    private Object target;

    public MyInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("------插入前置通知代码-------------");
        // 执行相应的目标方法
        Object rs = method.invoke(target, args);
        System.out.println("------插入后置处理代码-------------");
        return rs;
    }
}
JDK Proxy存在的缺陷

JDK 动态代理是基于接口实现的代理操作,如果该类没有需要实现的接口则无法使用JDK代理,由于JDK的动态代理无需引入第三方的包,所以,在个人看来这既是JDK动态代理的优势又是其短板,在我们企业级开发常用的Spring框架中,经常使用到的Spring AOP技术使用了两种代理模式:JDK代理和cglib动态代理。

引用一下以下文字:

If the target class implements one or more interfaces, then Spring will create a JDK dynamic proxy that implements every interface. If the target class implements no interfaces, Spring will use CGLIB to create a new class on the fly that is a subclass (“extends”) the target class. This leads to one important difference: a JDK dynamic proxy cannot be casted to the original target class because it’s simply a dynamic proxy that happens to implement the same interface(s) as the target. This has the effect of “nudging” you to program to interfaces if they’re being used in your application’s model, since proxies will usually be invoked through those interfaces 如果被调用者没有实现接口,而我们还是希望利用动态代理机制,那么可以考虑其他方式。我们知道 Spring AOP 支持两种模式的动态代理,JDK Proxy 或者 cglib,如果我们选择 cglib 方式,你会发现对接口的依赖被克服了。

cglib的优势
  • 在被代理类不便实现接口时,cglib可以实现代理
  • 只需操作我们关心的类,不需要增加其他的类
  • 性能较反射更高

0 人点赞