关于java:java动态代理

36次阅读

共计 12481 个字符,预计需要花费 32 分钟才能阅读完成。

代理

首先,代理是一种设计模式,是行为型设计模式中的一个,其思维是批改原来的行为,然而对外裸露的形式不变,比方网络代理。UML 图如下:

代理中的角色有:形象接口、委托类、代理类。
依据代理类产生的形式和期间不同,分为动态代理和动静代理。
动态代理间接在代码编写阶段实现,所以叫做动态代理。动静代理是在运行时生成,所以叫动静代理。

动态代理

这里动态的意思是代理类代码是手工编写的,在 java 文件时曾经确定了,流程如下:

动静代理

动态代理问题是他是动态的,必须实现写好代码。然而如果当初有个订单零碎,对订单操作须要防并发,我就要在每个订单操作的办法中增加防并发代码。这时,动静代理就能够派上用场了,我不批改代码,只有写好防并发的代码,在运行时动静生成最终的代码。
动静代理的流程如下:

动静代理有两种,别离是 JDK 动静代理和 Cglib 代理。
他们的区别晓得是两点:

类型 原理 适用范围
JDK 动静代理 反射 接口
Cglib 字节码改写

JDK 动静代理

JDK 动静代理,是 JDK 自带的,次要有两个类:Proxy 类(用于生成代理类),InvocationHandler 类(用于实现改写的逻辑)。
代码如下:

public class DynamicProxyJdk {public static void main(String[] args) throws IOException {ICalculator calculatorImpl = new ICalculator() {
            @Override
            public int add(int n1, int n2) {System.out.println("开始计算加法");

                return n1 + n2;
            }
        };

        ICalculator calculatorProxy =  (ICalculator) getProxy(calculatorImpl);
        System.out.println(calculatorProxy.getClass());
        int sumNum = calculatorProxy.add(1, 2);
        System.out.println("计算结果:" + sumNum);

        System.in.read();}

    public static Object getProxy(Object target){return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("代理开始");
                        Object result = method.invoke(target, args);
                        System.out.println("代理完结");

                        return result;
                    }
                });
    }

    public interface ICalculator{int add(int n1, int n2);
    }
}

通过 arthas,反编译出代理类,如下:

package com.sun.proxy;

import com.zx.java.reflect.proxy.DynamicProxyJdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class $Proxy0
extends Proxy
implements DynamicProxyJdk.ICalculator {
    private static Method m1;
    private static Method m2;
    private static Method m3;
    private static Method m0;

    public $Proxy0(InvocationHandler invocationHandler) {super(invocationHandler);
    }

    static {
        try {m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
            m3 = Class.forName("com.zx.java.reflect.proxy.DynamicProxyJdk$ICalculator").getMethod("add", Integer.TYPE, Integer.TYPE);
            m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
            return;
        }
        catch (NoSuchMethodException noSuchMethodException) {throw new NoSuchMethodError(noSuchMethodException.getMessage());
        }
        catch (ClassNotFoundException classNotFoundException) {throw new NoClassDefFoundError(classNotFoundException.getMessage());
        }
    }

    public final int add(int n, int n2) {
        try {return (Integer)this.h.invoke(this, m3, new Object[]{n, n2});
        }
        catch (Error | RuntimeException throwable) {throw throwable;}
        catch (Throwable throwable) {throw new UndeclaredThrowableException(throwable);
        }
    }

    public final boolean equals(Object object) {
        try {return (Boolean)this.h.invoke(this, m1, new Object[]{object});
        }
        catch (Error | RuntimeException throwable) {throw throwable;}
        catch (Throwable throwable) {throw new UndeclaredThrowableException(throwable);
        }
    }

    public final String toString() {
        try {return (String)this.h.invoke(this, m2, null);
        }
        catch (Error | RuntimeException throwable) {throw throwable;}
        catch (Throwable throwable) {throw new UndeclaredThrowableException(throwable);
        }
    }

    public final int hashCode() {
        try {return (Integer)this.h.invoke(this, m0, null);
        }
        catch (Error | RuntimeException throwable) {throw throwable;}
        catch (Throwable throwable) {throw new UndeclaredThrowableException(throwable);
        }
    }
}

能够看到,反射进去的代理类,继承 Proxy(提供了批改的办法以及而额定的办法)以及委托类接口(提供了类信息)。

Cglib

Cglib(Code Generation Library) 是一个功能强大、高性能的代码生成包。

贴代码。

public class CglibMethodInterceptor implements MethodInterceptor {public static void main(String[] args) throws IOException {Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(Calculator.class);
        enhancer.setCallback(new CglibMethodInterceptor());
        Calculator calculatorProxy = (Calculator) enhancer.create();
        System.out.println("计算结果:" +  calculatorProxy.add(1, 2));
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("intercept start");

        Object result = methodProxy.invokeSuper(o, objects);

        System.out.println("intercept end");

        return result;
    }

    public class Calculator {public int add(int n1, int n2){System.out.println("开始计算");

          return n1 + n2;
      }
    }
}

后果:

intercept start
开始计算
intercept end
计算结果:3

代理类的源代码如下:

public class Calculator$$EnhancerByCGLIB$$c5a6599b
extends Calculator
implements Factory {
    private boolean CGLIB$BOUND;
    public static Object CGLIB$FACTORY_DATA;
    private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
    private static final Callback[] CGLIB$STATIC_CALLBACKS;
    private MethodInterceptor CGLIB$CALLBACK_0;
    private static Object CGLIB$CALLBACK_FILTER;
    private static final Method CGLIB$add$0$Method;
    private static final MethodProxy CGLIB$add$0$Proxy;
    private static final Object[] CGLIB$emptyArgs;
    private static final Method CGLIB$equals$1$Method;
    private static final MethodProxy CGLIB$equals$1$Proxy;
    private static final Method CGLIB$toString$2$Method;
    private static final MethodProxy CGLIB$toString$2$Proxy;
    private static final Method CGLIB$hashCode$3$Method;
    private static final MethodProxy CGLIB$hashCode$3$Proxy;
    private static final Method CGLIB$clone$4$Method;
    private static final MethodProxy CGLIB$clone$4$Proxy;

    public static MethodProxy CGLIB$findMethodProxy(Signature signature) {String string = ((Object)signature).toString();
        switch (string.hashCode()) {
            case -1287932281: {if (!string.equals("add(II)I")) break;
                return CGLIB$add$0$Proxy;
            }
            case -508378822: {if (!string.equals("clone()Ljava/lang/Object;")) break;
                return CGLIB$clone$4$Proxy;
            }
            case 1826985398: {if (!string.equals("equals(Ljava/lang/Object;)Z")) break;
                return CGLIB$equals$1$Proxy;
            }
            case 1913648695: {if (!string.equals("toString()Ljava/lang/String;")) break;
                return CGLIB$toString$2$Proxy;
            }
            case 1984935277: {if (!string.equals("hashCode()I")) break;
                return CGLIB$hashCode$3$Proxy;
            }
        }
        return null;
    }

    public void setCallback(int n, Callback callback) {switch (n) {
            case 0: {this.CGLIB$CALLBACK_0 = (MethodInterceptor)callback;
                break;
            }
        }
    }

    final boolean CGLIB$equals$1(Object object) {return super.equals(object);
    }

    final int CGLIB$add$0(int n, int n2) {return super.add(n, n2);
    }

    static void CGLIB$STATICHOOK1() {CGLIB$THREAD_CALLBACKS = new ThreadLocal();
        CGLIB$emptyArgs = new Object[0];
        Class<?> clazz = Class.forName("com.zx.java.reflect.proxy.base.Calculator$$EnhancerByCGLIB$$c5a6599b");
        Class<?> clazz2 = Class.forName("java.lang.Object");
        Method[] methodArray = ReflectUtils.findMethods(new String[]{"equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"}, clazz2.getDeclaredMethods());
        CGLIB$equals$1$Method = methodArray[0];
        CGLIB$equals$1$Proxy = MethodProxy.create(clazz2, clazz, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$1");
        CGLIB$toString$2$Method = methodArray[1];
        CGLIB$toString$2$Proxy = MethodProxy.create(clazz2, clazz, "()Ljava/lang/String;", "toString", "CGLIB$toString$2");
        CGLIB$hashCode$3$Method = methodArray[2];
        CGLIB$hashCode$3$Proxy = MethodProxy.create(clazz2, clazz, "()I", "hashCode", "CGLIB$hashCode$3");
        CGLIB$clone$4$Method = methodArray[3];
        CGLIB$clone$4$Proxy = MethodProxy.create(clazz2, clazz, "()Ljava/lang/Object;", "clone", "CGLIB$clone$4");
        clazz2 = Class.forName("com.zx.java.reflect.proxy.base.Calculator");
        CGLIB$add$0$Method = ReflectUtils.findMethods(new String[]{"add", "(II)I"}, clazz2.getDeclaredMethods())[0];
        CGLIB$add$0$Proxy = MethodProxy.create(clazz2, clazz, "(II)I", "add", "CGLIB$add$0");
    }

    private static final void CGLIB$BIND_CALLBACKS(Object object) {
        block2: {
            Object object2;
            block3: {Calculator$$EnhancerByCGLIB$$c5a6599b calculator$$EnhancerByCGLIB$$c5a6599b = (Calculator$$EnhancerByCGLIB$$c5a6599b)object;
                if (calculator$$EnhancerByCGLIB$$c5a6599b.CGLIB$BOUND) break block2;
                calculator$$EnhancerByCGLIB$$c5a6599b.CGLIB$BOUND = true;
                object2 = CGLIB$THREAD_CALLBACKS.get();
                if (object2 != null) break block3;
                object2 = CGLIB$STATIC_CALLBACKS;
                if (CGLIB$STATIC_CALLBACKS == null) break block2;
            }
            calculator$$EnhancerByCGLIB$$c5a6599b.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])object2)[0];
        }
    }

    final String CGLIB$toString$2() {return super.toString();
    }

    final int CGLIB$hashCode$3() {return super.hashCode();
    }

    final Object CGLIB$clone$4() throws CloneNotSupportedException {return super.clone();
    }

    public void setCallbacks(Callback[] callbackArray) {Callback[] callbackArray2 = callbackArray;
        Calculator$$EnhancerByCGLIB$$c5a6599b calculator$$EnhancerByCGLIB$$c5a6599b = this;
        this.CGLIB$CALLBACK_0 = (MethodInterceptor)callbackArray[0];
    }

    public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] callbackArray) {CGLIB$STATIC_CALLBACKS = callbackArray;}

    public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] callbackArray) {CGLIB$THREAD_CALLBACKS.set(callbackArray);
    }

    public Callback getCallback(int n) {
        MethodInterceptor methodInterceptor;
        Calculator$$EnhancerByCGLIB$$c5a6599b.CGLIB$BIND_CALLBACKS(this);
        switch (n) {
            case 0: {
                methodInterceptor = this.CGLIB$CALLBACK_0;
                break;
            }
            default: {methodInterceptor = null;}
        }
        return methodInterceptor;
    }

    public Callback[] getCallbacks() {Calculator$$EnhancerByCGLIB$$c5a6599b.CGLIB$BIND_CALLBACKS(this);
        Calculator$$EnhancerByCGLIB$$c5a6599b calculator$$EnhancerByCGLIB$$c5a6599b = this;
        return new Callback[]{this.CGLIB$CALLBACK_0};
    }

    public Calculator$$EnhancerByCGLIB$$c5a6599b() {
        Calculator$$EnhancerByCGLIB$$c5a6599b calculator$$EnhancerByCGLIB$$c5a6599b = this;
        Calculator$$EnhancerByCGLIB$$c5a6599b.CGLIB$BIND_CALLBACKS(calculator$$EnhancerByCGLIB$$c5a6599b);
    }

    static {Calculator$$EnhancerByCGLIB$$c5a6599b.CGLIB$STATICHOOK1();
    }

    public final int add(int n, int n2) {
        MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
        if (methodInterceptor == null) {Calculator$$EnhancerByCGLIB$$c5a6599b.CGLIB$BIND_CALLBACKS(this);
            methodInterceptor = this.CGLIB$CALLBACK_0;
        }
        if (methodInterceptor != null) {Object object = methodInterceptor.intercept(this, CGLIB$add$0$Method, new Object[]{new Integer(n), new Integer(n2)}, CGLIB$add$0$Proxy);
            return object == null ? 0 : ((Number)object).intValue();}
        return super.add(n, n2);
    }

    public final boolean equals(Object object) {
        MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
        if (methodInterceptor == null) {Calculator$$EnhancerByCGLIB$$c5a6599b.CGLIB$BIND_CALLBACKS(this);
            methodInterceptor = this.CGLIB$CALLBACK_0;
        }
        if (methodInterceptor != null) {Object object2 = methodInterceptor.intercept(this, CGLIB$equals$1$Method, new Object[]{object}, CGLIB$equals$1$Proxy);
            return object2 == null ? false : (Boolean)object2;
        }
        return super.equals(object);
    }

    public final String toString() {
        MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
        if (methodInterceptor == null) {Calculator$$EnhancerByCGLIB$$c5a6599b.CGLIB$BIND_CALLBACKS(this);
            methodInterceptor = this.CGLIB$CALLBACK_0;
        }
        if (methodInterceptor != null) {return (String)methodInterceptor.intercept(this, CGLIB$toString$2$Method, CGLIB$emptyArgs, CGLIB$toString$2$Proxy);
        }
        return super.toString();}

    public final int hashCode() {
        MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
        if (methodInterceptor == null) {Calculator$$EnhancerByCGLIB$$c5a6599b.CGLIB$BIND_CALLBACKS(this);
            methodInterceptor = this.CGLIB$CALLBACK_0;
        }
        if (methodInterceptor != null) {Object object = methodInterceptor.intercept(this, CGLIB$hashCode$3$Method, CGLIB$emptyArgs, CGLIB$hashCode$3$Proxy);
            return object == null ? 0 : ((Number)object).intValue();}
        return super.hashCode();}

    protected final Object clone() throws CloneNotSupportedException {
        MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
        if (methodInterceptor == null) {Calculator$$EnhancerByCGLIB$$c5a6599b.CGLIB$BIND_CALLBACKS(this);
            methodInterceptor = this.CGLIB$CALLBACK_0;
        }
        if (methodInterceptor != null) {return methodInterceptor.intercept(this, CGLIB$clone$4$Method, CGLIB$emptyArgs, CGLIB$clone$4$Proxy);
        }
        return super.clone();}

    public Object newInstance(Callback[] callbackArray) {Calculator$$EnhancerByCGLIB$$c5a6599b.CGLIB$SET_THREAD_CALLBACKS(callbackArray);
        Calculator$$EnhancerByCGLIB$$c5a6599b calculator$$EnhancerByCGLIB$$c5a6599b = new Calculator$$EnhancerByCGLIB$$c5a6599b();
        Calculator$$EnhancerByCGLIB$$c5a6599b.CGLIB$SET_THREAD_CALLBACKS(null);
        return calculator$$EnhancerByCGLIB$$c5a6599b;
    }

    public Object newInstance(Callback callback) {Calculator$$EnhancerByCGLIB$$c5a6599b.CGLIB$SET_THREAD_CALLBACKS(new Callback[]{callback});
        Calculator$$EnhancerByCGLIB$$c5a6599b calculator$$EnhancerByCGLIB$$c5a6599b = new Calculator$$EnhancerByCGLIB$$c5a6599b();
        Calculator$$EnhancerByCGLIB$$c5a6599b.CGLIB$SET_THREAD_CALLBACKS(null);
        return calculator$$EnhancerByCGLIB$$c5a6599b;
    }

    public Object newInstance(Class[] classArray, Object[] objectArray, Callback[] callbackArray) {
        Calculator$$EnhancerByCGLIB$$c5a6599b calculator$$EnhancerByCGLIB$$c5a6599b;
        Calculator$$EnhancerByCGLIB$$c5a6599b.CGLIB$SET_THREAD_CALLBACKS(callbackArray);
        Class[] classArray2 = classArray;
        switch (classArray.length) {
            case 0: {calculator$$EnhancerByCGLIB$$c5a6599b = new Calculator$$EnhancerByCGLIB$$c5a6599b();
                break;
            }
            default: {throw new IllegalArgumentException("Constructor not found");
            }
        }
        Calculator$$EnhancerByCGLIB$$c5a6599b.CGLIB$SET_THREAD_CALLBACKS(null);
        return calculator$$EnhancerByCGLIB$$c5a6599b;
    }
}

能够看到也是继承委托类。

Spring aop

spring aop,如果是接口应用 JDK 动静代理,如果是类则应用 Cglib。
绝对应的概念:

 切点:委托类
切面:代理类

正文完
 0