动态代理实现的两种方式

471 阅读2分钟

今天面试美团的时候遇到了这个问题,当时只会实现接口的动态代理方式,后来上网查资料进行了一下浅显的总结(果然太菜了,虽然被据了n次,0offer但是也还得笑着学下去TAT)

jdk方式(实现接口)

jdk实现动态代理的方式是代理类和被代理类都实现了共同的接口,调用方法时,代理类proxy实质是通过InvocationHandler类中的invoke方法来进行调用,而invoke方法是通过反射来调用被代理类实际的方法。 代码框架如下:

/**
 * JDK动态代理类
 */
public class JDKProxy implements InvocationHandler {    
    
    // 需要代理的目标对象
    private Object targetObject;    
    
    public Object newProxy(Object targetObject) {
        // 将目标对象传入进行代理    
        this.targetObject = targetObject;
        // 返回代理对象 
        return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), this);
    }    
    
    // invoke方法
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 进行逻辑处理的函数
        checkPopedom();
        Object ret = null;
        // 调用invoke方法
        ret = method.invoke(targetObject, args);
        return ret;
    }    
    
    private void checkPopedom() {
        // 模拟检查权限   
        System.out.println("检查权限:checkPopedom()!");    
    }    
} 

cglib方式(继承实现)

cglib方式的动态代理是利用asm开源包,将被代理对象的class文件加载进来,通过修改其子节码来生成子类来处理。 这种方式有几个重要的类

  1. Enhancer
  2. MethodeInterceptor 主要的方法拦截类,需要用户实现,其中需要实现intercept方法
public Object intercept(Object object, java.lang.reflect.Method method,
Object[] args, MethodProxy proxy) throws Throwable;

第一个参数是被代理的对象,第二个参数和第三个参数是拦截的方法和方法的参数。 3. MethodProxy Method类的代理类,可以方便实现对原对象方法对调用

代码框架:

/**
 * CGlib动态代理类
 */
 public class CGLibProxy implements MethodInterceptor {    
    
    // CGlib需要代理的目标对象
    private Object targetObject;
    
    public Object createProxyObject(Object obj) {
        this.targetObject = obj;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(obj.getClass());
        enhancer.setCallback(this);
        Object proxyObj = enhancer.create();
        return proxyObj;
    }
    
    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        Object obj = null;
        // 过滤方法
        if ("addUser".equals(method.getName())) {
            // 检查权限
            checkPopedom();
        }
        obj = method.invoke(targetObject, args);
        return obj;
    }    
    
    private void checkPopedom() {
        System.out.println("检查权限:checkPopedom()!");
    }
}

参考链接:blog.csdn.net/weixin_3675…