代理模式:为其他对象提供一种代理以控制对这个对象的访问。
代理模式中有三种角色:Subject抽象主题角色、RealSubject真实主题角色、Proxy代理主题角色。Subject描述了业务行为,RealSubject执行具体的业务逻辑,Proxy代理会拦截对RealSubject对象方法的调用,并在方法调用前后做预处理以及一些善后工作。
代理模式可以很好地在不侵入原代码的情况下,拓展原来的功能。
下图为Proxy模式的静态类图:
下图为Proxy模式的调用关系:
静态代理由于硬编码,难以应对真实对象和调用方法灵活多变的情况,动态代理则对这些场景应付自如。
动态代理主要有两种实现方式:1、JDK自带的Proxy 2、CGLIB字节码生成库
基于JDK的动态代理关键在于两个类:InvocationHandler和Proxy。
其主要实现逻辑是,由InvocationHandler定义方法执行前后的增强逻辑,由Proxy类去生成一个继承自Proxy并且实现了真实对象接口的新对象–代理对象,对该代理对象的方法调用经由InvocationHandler拦截,执行增强逻辑和调用真实对象执行业务逻辑。
下面我们先看一个例子:
定义接口:
public interface UserService {
public String getName(int id);
public Integer getAge(int id);
}
定义真实对象:
public class UserServiceImpl implements UserService {
public UserServiceImpl() {
}
@Override
public String getName(int id) {
System.out.println("---getName---");
return "John";
}
@Override
public Integer getAge(int id) {
System.out.println("---getAge---");
return 10;
}
}
定义InvocationHandler:
public class MyInvocationHandler implements InvocationHandler {
private Object target;
public MyInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("getName")) {
System.out.println("+++before get name+++");
Object res = method.invoke(target, args);
System.out.println("+++after get name+++");
return res;
} else {
Object res = method.invoke(target, args);
return res;
}
}
public static void main(String[] args) {
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
UserService us = new UserServiceImpl();
InvocationHandler ih = new MyInvocationHandler(us);
UserService usProxy = (UserService) Proxy.newProxyInstance(us.getClass().getClassLoader(),
us.getClass().getInterfaces(), ih);
System.out.println(usProxy.getName(1));
System.out.println(usProxy.getAge(1));
System.out.println(usProxy.getClass());
}
}
可以看到,对于getName方法的增强逻辑执行了。
下面我们从源码角度分析一下这个过程的实现原理,先看InvocationHandler:
InvocationHandler是一个接口,只有一个方法:
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
在定义增强逻辑类时,需要实现该接口,并在invoke方法里实现增强逻辑和对真实对象方法的调用。对于invoke方法的三个参数,proxy表示代理对象,method表示真实对象的方法,args表示真实对象方法的参数,这里也可以看出对真实对象方法的调用是通过反射来实现的。
增强逻辑定义好了以后,我们需要一个代理对象来执行,先看如何产生这个代理对象。代理对象的产生是通过调用Proxy类的静态方法:newProxyInstance,以下源码分析部分篇幅原因仅截取部分代码片段。
public static Object newProxyInstance(ClassLoader loader,
Class>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
//该方法需要三个参数:ClassLoader确保返回的代理对象和真实对象由同一个类
加载器加载,interfaces用于定义代理类应该实现的方法,
invocationHandler用于定义代理类的增强逻辑
{
if (h == null) {
throw new NullPointerException();
}
final Class>[] intfs = interfaces.clone();
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
/*
* Look up or generate the designated proxy class.
*/
//这一行代码很关键,这里是获取代理对象Class对象,Proxy类内部维护了代理
//对象的缓存,如果缓存里有则直接返回,如果没有,则生成它
Class> cl = getProxyClass0(loader, intfs);
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
//由Class对象获取构造器
final Constructor> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) {
// create proxy instance with doPrivilege as the proxy class may
// implement non-public interfaces that requires a special permission
return AccessController.doPrivileged(new PrivilegedAction
接下来我们看代理对象的Class对象是如何生成的,缓存逻辑略去不表,直接看没有缓存的情况,代理类Class对象由ProxyClassFactory工厂生成:
private static final class ProxyClassFactory
implements BiFunction<ClassLoader, Class>[], Class>>
{
// prefix for all proxy class names
private static final String proxyClassNamePrefix = "$Proxy";
// next number to use for generation of unique proxy class names
private static final AtomicLong nextUniqueNumber = new AtomicLong();
//验证代码略去
/*
* Generate the specified proxy class.
*/
//这里生成了代理对象二进制字节码流
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces);
try {
//通过二进制字节码流加载代理类
return defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
} catch (ClassFormatError e) {
throw new IllegalArgumentException(e.toString());
}
}
}
最终生成二进制字节码流用到了Sun的ProxyGenerator类,反编译:
public static byte[] generateProxyClass(String s, Class aclass[])
{
ProxyGenerator proxygenerator = new ProxyGenerator(s, aclass);
//该方法生成代理对象的二进制字节码流
byte abyte0[] = proxygenerator.generateClassFile();
//如果要保存该字节码文件,可以将其写到硬盘上,我们稍后分析
if(saveGeneratedFiles)
//保存文件部分略去
return abyte0;
}
具体生成源码如下:
private byte[] generateClassFile() {
addProxyMethod(hashCodeMethod, java / lang / Object);
addProxyMethod(equalsMethod, java / lang / Object);
addProxyMethod(toStringMethod, java / lang / Object);
for (int i = 0; i < interfaces.length; i++) {
Method amethod[] = interfaces[i].getMethods();
for (int k = 0; k < amethod.length; k++)
addProxyMethod(amethod[k], interfaces[i]);
}
List list;
for (Iterator iterator = proxyMethods.values().iterator(); iterator.hasNext(); checkReturnTypes(list))
list = (List) iterator.next();
try {
methods.add(generateConstructor());
for (Iterator iterator1 = proxyMethods.values().iterator(); iterator1.hasNext();) {
List list1 = (List) iterator1.next();
Iterator iterator2 = list1.iterator();
while (iterator2.hasNext()) {
ProxyMethod proxymethod = (ProxyMethod) iterator2.next();
fields.add(new FieldInfo(proxymethod.methodFieldName, "Ljava/lang/reflect/Method;", 10));
methods.add(proxymethod.generateMethod());
}
}
methods.add(generateStaticInitializer());
} catch (IOException ioexception) {
throw new InternalError("unexpected I/O Exception");
}
if (methods.size() > 65535)
throw new IllegalArgumentException("method limit exceeded");
if (fields.size() > 65535)
throw new IllegalArgumentException("field limit exceeded");
cp.getClass(dotToSlash(className));
cp.getClass("java/lang/reflect/Proxy");
for (int j = 0; j < interfaces.length; j++)
cp.getClass(dotToSlash(interfaces[j].getName()));
cp.setReadOnly();
ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream();
DataOutputStream dataoutputstream = new DataOutputStream(bytearrayoutputstream);
try {
dataoutputstream.writeInt(-889275714);
dataoutputstream.writeShort(0);
dataoutputstream.writeShort(49);
cp.write(dataoutputstream);
dataoutputstream.writeShort(49);
dataoutputstream.writeShort(cp.getClass(dotToSlash(className)));
dataoutputstream.writeShort(cp.getClass("java/lang/reflect/Proxy"));
dataoutputstream.writeShort(interfaces.length);
for (int l = 0; l < interfaces.length; l++)
dataoutputstream.writeShort(cp.getClass(dotToSlash(interfaces[l].getName())));
dataoutputstream.writeShort(fields.size());
FieldInfo fieldinfo;
for (Iterator iterator3 = fields.iterator(); iterator3.hasNext(); fieldinfo.write(dataoutputstream))
fieldinfo = (FieldInfo) iterator3.next();
dataoutputstream.writeShort(methods.size());
MethodInfo methodinfo;
for (Iterator iterator4 = methods.iterator(); iterator4.hasNext(); methodinfo.write(dataoutputstream))
methodinfo = (MethodInfo) iterator4.next();
dataoutputstream.writeShort(0);
} catch (IOException ioexception1) {
throw new InternalError("unexpected I/O Exception");
}
return bytearrayoutputstream.toByteArray();
}
至此,总结一下,Proxy类通过ProxyClassFactory生成了继承Proxy类并实现了真实对象接口的 $ProxyX代理对象的二进制字节码流,并加载该字节码返回代理对象Class对象,由该Class对象经反射得到构造器构造了代理对象的实例。
在源码中我们可以通过saveGeneratedFiles变量保存生成的class文件,我们反编译上面的示例生成的class文件:
public final class $Proxy0 extends Proxy implements UserService {
private static Method m1;
private static Method m4;
private static Method m0;
private static Method m3;
private static Method m2;
public $Proxy0(InvocationHandler invocationhandler) {
super(invocationhandler);
}
public final boolean equals(Object obj) {
try {
return ((Boolean) super.h.invoke(this, m1, new Object[]{obj})).booleanValue();
} catch (Error _ex) {
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
//这里是UserService接口的getAge方法,在代理对象$Proxy0上的调用被invocationHandler拦截,
//经由其invoke方法调用(即我们之前定义的MyinvocationHandler的invoke方法),
//留意invoke方法的参数,我们在MyinvocationHandler里定义invoke方法时并没有使用proxy参数,
//这里proxy参数的位置传入了this变量,即代理对象本身。
public final Integer getAge(int i) {
try {
return (Integer) super.h.invoke(this, m4, new Object[]{Integer.valueOf(i)});
} catch (Error _ex) {
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
public final int hashCode() {
try {
return ((Integer) super.h.invoke(this, m0, null)).intValue();
} catch (Error _ex) {
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
public final String getName(int i) {
try {
return (String) super.h.invoke(this, m3, new Object[]{Integer.valueOf(i)});
} catch (Error _ex) {
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
public final String toString() {
try {
return (String) super.h.invoke(this, m2, null);
} catch (Error _ex) {
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")});
m4 = Class.forName("cn.john.test.dynamicProxy.UserService").getMethod("getAge", new Class[]{Integer.TYPE});
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
m3 = Class.forName("cn.john.test.dynamicProxy.UserService").getMethod("getName", new Class[]{Integer.TYPE});
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
} catch (NoSuchMethodException nosuchmethodexception) {
throw new NoSuchMethodError(nosuchmethodexception.getMessage());
} catch (ClassNotFoundException classnotfoundexception) {
throw new NoClassDefFoundError(classnotfoundexception.getMessage());
}
}
}
public class UserServiceB {
public String getName(int id) {
System.out.println("---getName---");
return "John";
}
public Integer getAge(int id) {
System.out.println("---getAge---");
return 10;
}
public static void main(String[] args) throws InterruptedException, IOException {
//将cglib生成的Class对象写成文件存入硬盘,后面反编译出来用以分析
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\class");
UserServiceB us = new UserServiceB();
// 定义增强器
Enhancer en = new Enhancer();
// 定义要代理的对象
en.setSuperclass(us.getClass());
// 定义回调函数
en.setCallback(new MethodInterceptor() {
//这里要理解intercept方法的几个参数代表的意思
//obj指的是代理类对象
//Method指的是 目标类中被拦截的方法
//args指的是 调用拦截方法所需的参数
//MethodProxy指的是用来调用目标类被拦截方法的方法,这个方法比反射更快
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy)
throws Throwable {
System.out.println("-----before-------");
//这里只能用invokeSuper,原因稍后解释
methodProxy.invokeSuper(obj, args);
System.out.println("-----after--------");
return null;
}
});
// 生成代理对象
UserServiceB usb = (UserServiceB) en.create();
// 在代理对象上调用方法
usb.getName(1);
}
}
同时生成了三个class文件:一个是代理类,一个是代理类的FastClass,一个是目标类的FastClass
从上面的示例代码中,我们知道通过cglib生成代理类只需要一个目标类和一个回调函数(增强逻辑),下面我们从在代理对象上调用getName()方法出发,一步一步分析cglib动态代理的实现原理。
先来看生成的代理对象Class文件反编译后的源码(代码很长,代理了Object中的finalize,equals, toString,hashCode,clone方法,这里仅留下getName()方法):
public class UserServiceB$$EnhancerByCGLIB$$a33459ad extends UserServiceB implements Factory {
//cglib基于继承,可以看到代理类继承了目标类,并实现了Factory接口,Factory接口可以简化回调函数的变更
private boolean CGLIB$BOUND;
private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
private static final Callback[] CGLIB$STATIC_CALLBACKS;
private MethodInterceptor CGLIB$CALLBACK_0;//回调函数
private static final Method CGLIB$getName$0$Method;//目标类的getName方法
private static final MethodProxy CGLIB$getName$0$Proxy;//getName方法的代理方法
//初始化变量
static void CGLIB$STATICHOOK1() {
CGLIB$THREAD_CALLBACKS = new ThreadLocal();
CGLIB$emptyArgs = new Object[0];
//代理类
Class class_ = Class.forName("cn.john.test.dynamicProxy.UserServiceB$$EnhancerByCGLIB$$a33459ad");
//目标类
Class class_2 = Class.forName("cn.john.test.dynamicProxy.UserServiceB");
Method[] arrmethod = ReflectUtils.findMethods(
(String[]) new String[]{"getName", "(I)Ljava/lang/String;", "getAge", "(I)Ljava/lang/Integer;"},
(Method[]) class_2.getDeclaredMethods());
//getName方法
CGLIB$getName$0$Method = arrmethod[0];
//建立更快的方法索引访问方式,这里通过目标类和代理类的Class对象和方法签名为这两个对象
//的所有方法都建立了索引,并提供了通过索引调用的方法。
//这里CGLIB$getName$0$Proxy提供在目标类(或者兼容类)上快速调用getName和在代理类上
//快速调用CGLIB$getName$0的功能
CGLIB$getName$0$Proxy = MethodProxy.create(class_2, class_, (String) "(I)Ljava/lang/String;",
(String) "getName", (String) "CGLIB$getName$0");
}
//直接调用了目标类的方法,这个方法即用来执行目标类真实逻辑,通过索引调用来快速访问该方法
final String CGLIB$getName$0(int n) {
return super.getName(n);
}
//代理方法getName入口
public final String getName(int n) {
//先获取回调函数
MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
if (methodInterceptor == null) {
UserServiceB$$EnhancerByCGLIB$$a33459ad.CGLIB$BIND_CALLBACKS((Object) this);
methodInterceptor = this.CGLIB$CALLBACK_0;
}
//获取了回调函数之后
if (methodInterceptor != null) {
//调用回调函数的拦截方法。
//注意这里传入的参数,代理类传入的this,被拦截的方法传入的是目标类对象的
//被拦截的方法,methodProxy传入的是getName方法的快速访问代理
return (String) methodInterceptor.intercept((Object) this, CGLIB$getName$0$Method,
new Object[]{new Integer(n)}, CGLIB$getName$0$Proxy);
}
return super.getName(n);
}
public UserServiceB$$EnhancerByCGLIB$$a33459ad() {
UserServiceB$$EnhancerByCGLIB$$a33459ad userServiceB$$EnhancerByCGLIB$$a33459ad = this;
UserServiceB$$EnhancerByCGLIB$$a33459ad.CGLIB$BIND_CALLBACKS((Object) userServiceB$$EnhancerByCGLIB$$a33459ad);
}
public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] arrcallback) {
CGLIB$THREAD_CALLBACKS.set(arrcallback);
}
public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] arrcallback) {
CGLIB$STATIC_CALLBACKS = arrcallback;
}
private static final void CGLIB$BIND_CALLBACKS(Object object) {
UserServiceB$$EnhancerByCGLIB$$a33459ad userServiceB$$EnhancerByCGLIB$$a33459ad = (UserServiceB$$EnhancerByCGLIB$$a33459ad) ((Object) object);
if (!userServiceB$$EnhancerByCGLIB$$a33459ad.CGLIB$BOUND) {
userServiceB$$EnhancerByCGLIB$$a33459ad.CGLIB$BOUND = true;
Object t = CGLIB$THREAD_CALLBACKS.get();
if (t != null || (v13465 = CGLIB$STATIC_CALLBACKS) != null) {
userServiceB$$EnhancerByCGLIB$$a33459ad.CGLIB$CALLBACK_0 = (MethodInterceptor) ((Callback[]) t)[0];
}
}
}
static {
UserServiceB$$EnhancerByCGLIB$$a33459ad.CGLIB$STATICHOOK1();
}
}
进入回调函数后,跟JDK动态代理InvocationHandler一样,先执行前置增强逻辑,然后将目标类的真实逻辑。注意此处目标类的真实逻辑执行cglib的实现方式与JDK实现方式不同:JDK使用的是反射技术,而cglib则使用了FastClass构建方法索引+继承的方式访问目标类的方法。
CGLIB$getName$0$Proxy = MethodProxy.create(class_2, class_, (String) "(I)Ljava/lang/String;",
(String) "getName", (String) "CGLIB$getName$0");
//注意这里class_2是目标类,class_是代理类
我们截取MethodProxy类的部分代码:
private static class CreateInfo {
Class c1;
Class c2;
NamingPolicy namingPolicy;
GeneratorStrategy strategy;
boolean attemptLoad;
public CreateInfo(Class c1, Class c2) {
this.c1 = c1;
this.c2 = c2;
AbstractClassGenerator fromEnhancer = AbstractClassGenerator.getCurrent();
if (fromEnhancer != null) {
this.namingPolicy = fromEnhancer.getNamingPolicy();
this.strategy = fromEnhancer.getStrategy();
this.attemptLoad = fromEnhancer.getAttemptLoad();
}
}
}
//注意在MethodProxy类内部变量命名:这里目标类为1,而代理类变为了2
public static MethodProxy create(Class c1, Class c2, String desc, String name1, String name2) {
//准备数据阶段,目标类和代理类的Class对象,需要映射的方法签名,这里并不会
//触发实际上的建立方法索引
MethodProxy proxy = new MethodProxy();
proxy.sig1 = new Signature(name1, desc);
proxy.sig2 = new Signature(name2, desc);
proxy.createInfo = new CreateInfo(c1, c2);
return proxy;
}
实际建立方法索引发生在回调函数中方法调用时(Lazyinit):
//MethodProxy类中的InvokeSuper
public Object invokeSuper(Object obj, Object[] args) throws Throwable {
try {
this.init();//实际的方法索引在此时建立
FastClassInfo fci = this.fastClassInfo;
//在代理类FastClass对象上调用索引为i2的方法
return fci.f2.invoke(fci.i2, obj, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
}
}
//内部类FastClassInfo
private static class FastClassInfo {
FastClass f1;//目标类fc
FastClass f2;//代理类fc
int i1;//目标类getName方法索引
int i2;//代理类CGLIB$getName$0方法索引
private FastClassInfo() {
}
}
private void init() {
if (this.fastClassInfo == null) {
Object object = this.initLock;
synchronized (object) {
if (this.fastClassInfo == null) {
CreateInfo ci = this.createInfo;
FastClassInfo fci = new FastClassInfo();
//这里通过字节码技术生成目标类和代理类的FastClass类的实例
//FastClass关键有两类方法:
//一类是getIndex方法,通过方法签名获取某方法的索引
//一类是invoke方法,通过方法的索引来找到方法并调用
fci.f1 = MethodProxy.helper(ci, ci.c1);//生成目标类的FastClass对象
fci.f2 = MethodProxy.helper(ci, ci.c2);//生成代理类的FastClass对象
//获取目标类和代理类的方法索引
fci.i1 = fci.f1.getIndex(this.sig1);
fci.i2 = fci.f2.getIndex(this.sig2);
this.fastClassInfo = fci;//至此,getName方法的索引建立、获取完毕
this.createInfo = null;
}
}
}
}
回到示例上层代码:methodProxy.invokeSuper(obj, args);
这里obj是代理对象,再看invokeSuper:
public Object invokeSuper(Object obj, Object[] args) throws Throwable {
try {
init();//建立和获取索引
FastClassInfo fci = fastClassInfo;
//在obj即代理对象上调用索引为i2的方法
return fci.f2.invoke(fci.i2, obj, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
}
}
现在我们反编译代理类的FastClass类看一下,fci.f2.invoke(fci.i2, obj, args);
到底意味着什么。
代理类FastClass(部分代码):
public class UserServiceB$$EnhancerByCGLIB$$a33459ad$$FastClassByCGLIB$$9e4fc4c5 extends FastClass {
public UserServiceB$$EnhancerByCGLIB$$a33459ad$$FastClassByCGLIB$$9e4fc4c5(Class class_) {
super(class_);
}
public int getIndex(Signature signature) {
String string = signature.toString();
switch (string.hashCode()) {
case -2024387448 : {
//在上面的Init方法中我们已经获取了CGLIB$getName$0的索引,值为18
if (!string.equals("CGLIB$getName$0(I)Ljava/lang/String;"))
break;
return 18;
}
case 206620625 : {
if (!string.equals("getName(I)Ljava/lang/String;"))
break;
return 3;
}
}
return -1;
}
//在代理对象上调用索引为18的方法
public Object invoke(int n, Object object, Object[] arrobject) throws InvocationTargetException {
UserServiceB$$EnhancerByCGLIB$$a33459ad userServiceB$$EnhancerByCGLIB$$a33459ad = (UserServiceB$$EnhancerByCGLIB$$a33459ad) ((Object) object);
try {
switch (n) {
case 3 : {
return userServiceB$$EnhancerByCGLIB$$a33459ad.getName(((Number) arrobject[0]).intValue());
}
//在代理对象上调用了CGLIB$getName$0方法,回到代理类源码,它调用super.getName,即目标类的真实逻辑
case 18 : {
return userServiceB$$EnhancerByCGLIB$$a33459ad.CGLIB$getName$0(((Number) arrobject[0]).intValue());
}
}
} catch (Throwable v1) {
throw new InvocationTargetException(v1);
}
throw new IllegalArgumentException("Cannot find matching method/constructor");
}
}
现在我们来回答一下为什么示例代码中不能调用invoke,而是只能调用invokeSuper。invoke代码:
public Object invoke(Object obj, Object[] args) throws Throwable {
try {
init();
FastClassInfo fci = fastClassInfo;
//因为在回调函数中obj传入的代理对象,这里实际上是在代理对象上调用
//getName方法,将陷入无限递归,直至栈溢出
return fci.f1.invoke(fci.i1, obj, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
} catch (IllegalArgumentException e) {
if (fastClassInfo.i1 < 0)
throw new IllegalArgumentException("Protected method: " + sig1);
throw e;
}
}
类型 | 机制 | 回调方式 | 适用场景 | 效率 |
---|---|---|---|---|
JDK动态代理 | 委托机制,代理类和目标类都实现了同样的接口,InvocationHandler持有目标类,代理类委托InvocationHandler去调用目标类的原始方法 | 反射 | 目标类是接口类 | 效率瓶颈在反射调用稍慢 |
CGLIB动态代理 | 继承机制,代理类继承了目标类并重写了目标方法,通过回调函数MethodInterceptor调用父类方法执行原始逻辑 | 通过FastClass方法索引调用 | 非接口类,非final类,非final方法 | 第一次调用因为要生成多个Class对象较JDK方式慢,多次调用因为有方法索引较反射方式快,如果方法过多switch case过多其效率还需测试 |
http://ifeve.com/jdk%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86%E4%BB%A3%E7%90%86%E4%B8%8Ecglib%E4%BB%A3%E7%90%86%E5%8E%9F%E7%90%86%E6%8E%A2%E7%A9%B6/
https://www.jianshu.com/p/9a61af393e41?from=timeline&isappinstalled=0
https://www.jianshu.com/p/13aa63e1ac95
https://www.cnblogs.com/cruze/p/3865180.html
spring技术内幕