代理
首先,代理是一种设计模式,是行为型设计模式中的一个,其思维是批改原来的行为,然而对外裸露的形式不变,比方网络代理。 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 $Proxy0extends Proxyimplements 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$$c5a6599bextends Calculatorimplements 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。
绝对应的概念:
切点:委托类切面:代理类