代理
首先,代理是一种设计模式,是行为型设计模式中的一个,其思想是修改原来的行为,但是对外暴露的方式不变,比如网络代理。 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。
相对应的概念:
切点:委托类
切面:代理类