共计 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。
绝对应的概念:
切点:委托类
切面:代理类
正文完