代理的本质是非侵入式地对被代理对象方法的增强,即在原有方法上加日志等内容
一、静态代理
1、静态代理实现
接口:
public interface SampleInterface {
void test();
}
被代理类:
public class Sample implements SampleInterface {
@Override
public void test() {
System.out.println("Test");
}
}
代理类:
public class Proxy implements SampleInterface {
private SampleInterface sampleInterface = new Sample();
@Override
public void test() {
System.out.println("Before Test");
sampleInterface.test();
System.out.println("After Test");
}
}
代理类调用:
被代理类被传递给了代理类Proxy,代理类在执行具体方法时通过所持用的被代理类完成调用
public static void main(String[] args) {
Proxy proxy = new Proxy();
proxy.test();
}
使用静态代理很容易就完成了对一个类的代理操作。但是静态代理的缺点也暴露了出来:由于代理只能为一个类服务,如果需要代理的类很多,那么就需要编写大量的代理类,比较繁琐
讲述动态代理实现之前,我们要知道扩展一个类有常见的两种方式:
- 实现接口(JDK动态代理)
- 继承父类(CGLIB动态代理)
二、JDK动态代理
调用处理器接口(InvocationHandler)实现类注入被代理对象, 通过反射机制自动生成代理对象,代理对象调用方法(被invoke方法拦截,在invoke方法中进行增强操作,比如加日志等)
实现JDK动态代理主要用到了反射的两个API:
- java.lang.reflect.Proxy
- java.lang.reflect.InvocationHandler
InvocationHandler接口有一个invoke方法,这是所有代理对象调用方法的入口
1、动态代理实现
接口:
public interface SampleInterface {
void test();
}
被代理类:
public class Sample implements SampleInterface {
@Override
public void test() {
System.out.println("Test");
}
}
实现调用处理器接口(InvocationHandler):
class ProxyFactory implements InvocationHandler {
//被代理对象
private Object object;
public void ProxyFactory(Object object) {
//注入被代理对象
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//增强操作
System.out.println("Before Test");
//方法的正常调用
Object result = method.invoke(object, args);
//增强操作
System.out.println("After Test");
return result;
}
}
执行动态代理:
public static void main(String[] args) {
//生成$Proxy0
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
//创建被代理对象
SampleInterface sample = new Sample();
//创建调用处理器对象
InvocationHandler handler = new ProxyFactory(test);
//生成代理对象
SampleInterface proxy = (SampleInterface) Proxy.newProxyInstance(sample.getClass().getClassLoader(), sample.getClass().getInterfaces(), handler);
//通过代理对象调用方法,实际上会转到invoke方法调用
proxy.test();
}
2、Proxy类的newProxyInstance方法解析
public class Proxy implements java.io.Serializable {
private static final long serialVersionUID = -2222568056686623797L;
/** 代理类构造器的参数类型 */
private static final Class<?>[] constructorParams =
{ InvocationHandler.class };
/**
* 代理类的缓存
*/
private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
/**
* 代理实例的调用处理器
* @serial
*/
protected InvocationHandler h;
/**
* 禁止实例化
*/
private Proxy() {
}
/**
* 构造一个新的实例
*/
protected Proxy(InvocationHandler h) {
Objects.requireNonNull(h);
this.h = h;
}
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
/*
* 判断调用处理器是否为空,为空直接抛空指针异常
*/
Objects.requireNonNull(h);
final Class<?>[] intfs = interfaces.clone();
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
/*
* 查找或者生成代理类
*/
Class<?> cl = getProxyClass0(loader, intfs);
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
if (sm != null) {
/*
* 检查权限
*/
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
/*
* 获取参数类型为InvocationHandler.class的代理类构造器
*/
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
/*
* 设置修饰符
*/
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
/*
* 返回参数为h(InvocationHandler接口实现类)的代理实例$Proxy0
*/
return cons.newInstance(new Object[]{h});
} catch (IllegalAccessException|InstantiationException e) {
throw new InternalError(e.toString(), e);
} catch (InvocationTargetException e) {
Throwable t = e.getCause();
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else {
throw new InternalError(t.toString(), t);
}
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString(), e);
}
}
}
3、$Proxy0解析
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.sun.proxy;
import com.konka.SampleInterface;
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 SampleInterface {
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m0;
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return ((Boolean)super.h.invoke(this, m1, new Object[]{var1})).booleanValue();
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final void test() throws {
try {
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final int hashCode() throws {
try {
return ((Integer)super.h.invoke(this, m0, (Object[])null)).intValue();
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m3 = Class.forName("com.konka.SampleInterface").getMethod("test");
m2 = Class.forName("java.lang.Object").getMethod("toString");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
可以看到,Proxy类的newProxyInstance()方法被调用,该方法返回一个被代理对象的实例,然后向上转型为其对应的接口。问题是该方法在返回之前已经做了什么?我们看看其参数的第三个:handler,它就是InvocationHandler接口实现类(ProxyFactory)的一个实例。因为InvocationHandler接口中原本有个invoke()方法,所以其实现类当然需要实现这个方法,即其实现类(在此是ProxyFactory类)中有invoke()方法,而如果invoke()方法要被调用,只能通过ProxyFactory类对象来调用
而$Proxy0的代码中,有三个地方已经用ProxyFactory类对象来调用invoke()方法,他们分别在这些方法的代码中:public final boolean equals(Object obj) ;public final int hashCode() ;public final String toString()。也许你会有疑问,这个方法也没有看到在哪里被$Proxy0对象调用过,怎么能执行invoke方法呢?但是请看$Proxy0中的static代码块,这个模块是特殊的,因为当newProxyInstance方法创建$Proxy0时,它就被初始化。而这个static模块中的getMethod方法加载了这个三个方法,因而它们里面的代码(h.invoke())被执行
三、CGLIB动态代理
对于JDK动态代理,被代理类必须实现接口,也就是说它是面向接口的,而CGLIB动态代理则可以不实现接口
1、动态代理实现
引入依赖(cglib是第三方类库,需要引入依赖):
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.1</version>
</dependency>
被代理类(这里不再需要实现接口):
public class Sample {
@Override
public void test() {
System.out.println("Test");
}
}
实现方法拦截器接口(MethodInterceptor):
public class ProxyFactory implements MethodInterceptor {
//被代理对象
private Object object;
public ProxyFactory(Object object) {
//注入被代理对象
this.object = object;
}
@Override
public Object intercept(Object var1, Method var2, Object[] var3, MethodProxy var4) throws Throwable {
//增强操作
System.out.println("Before Test");
//方法的正常调用
Object result = method.invoke(object, var3);
//增强操作
System.out.println("After Test");
return result;
}
}
intercept()方法的四个参数:
- var1:需要增强的对象,即实现这个接口类的一个对象
- var2:要被拦截的方法
- var3:要被拦截方法的参数
- var4:要触发父类方法的对象
执行动态代理:
public static void main(String[] args) {
//代理类class文件存入本地磁盘方便反编译查看源码
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\code");
//通过CGLIB动态代理获取代理对象的过程
Enhancer enhancer = new Enhancer();
//指定父类
enhancer.setSuperclass(Sample.class);
//指定回调器
enhancer.setCallback(new ProxyFactory());
//创建代理对象
Sample proxy = (Sample) enhancer.create();
//通过代理对象调用方法
proxy.test();
}
2、源码解析
在上面的main方法中,通过enhancer.create()方法创建代理对象,create()方法的源码如下:
public Object create() {
this.classOnly = false;
this.argumentTypes = null;
return this.createHelper();
}
核心内容在createHelper()方法中,源码如下:
private Object createHelper() {
//校验callbackTypes、filter是否为空以及为空时的处理
this.validate();
if (this.superclass != null) {
this.setNamePrefix(this.superclass.getName());
} else if (this.interfaces != null) {
this.setNamePrefix(this.interfaces[ReflectUtils.findPackageProtected(this.interfaces)].getName());
}
//CGLIB动态代理和JDK动态代理一样,运用了缓存功能
//通过newInstance()方法创建EnhancerKey对象,作为Enhancer父类AbstractClassGenerator.create()方法创建代理对象的参数
return super.create(KEY_FACTORY.newInstance(this.superclass != null ? this.superclass.getName() : null, ReflectUtils.getNames(this.interfaces), this.filter, this.callbackTypes, this.useFactory, this.interceptDuringConstruction, this.serialVersionUID));
}
createHelper()方法执行父类AbstractClassGenerator的create()方法,源码如下:
protected Object create(Object key) {
try {
Class gen = null;
synchronized(this.source) {
ClassLoader loader = this.getClassLoader();
Map cache2 = null;
cache2 = (Map)this.source.cache.get(loader);
if (cache2 == null) {
cache2 = new HashMap();
((Map)cache2).put(NAME_KEY, new HashSet());
this.source.cache.put(loader, cache2);
} else if (this.useCache) {
Reference ref = (Reference)((Map)cache2).get(key);
gen = (Class)(ref == null ? null : ref.get());
}
if (gen == null) {
Object save = CURRENT.get();
CURRENT.set(this);
Object var24;
try {
this.key = key;
if (this.attemptLoad) {
try {
gen = loader.loadClass(this.getClassName());
} catch (ClassNotFoundException var17) {
}
}
if (gen == null) {
//根据策略生成字节码
//根据不同的ClassGenerator去生成不同的字节码,都是用ASM框架去生成字节码的
byte[] b = this.strategy.generate(this);
String className = ClassNameReader.getClassName(new ClassReader(b));
this.getClassNameCache(loader).add(className);
//生成代理类
gen = ReflectUtils.defineClass(className, b, loader);
}
if (this.useCache) {
((Map)cache2).put(key, new WeakReference(gen));
}
//生成代理类对象
var24 = this.firstInstance(gen);
} finally {
CURRENT.set(save);
}
return var24;
}
}
return this.firstInstance(gen);
} catch (RuntimeException var20) {
throw var20;
} catch (Error var21) {
throw var21;
} catch (Exception var22) {
throw new CodeGenerationException(var22);
}
}
根据firstInstance()方法可以找到最终生成代理类对象的方法是ReflectUtils类的nextInstance()方法,源码如下:
public static Object newInstance(Class type) {
return newInstance(type, Constants.EMPTY_CLASS_ARRAY, (Object[])null);
}
public static Object newInstance(Class type, Class[] parameterTypes, Object[] args) {
return newInstance(getConstructor(type, parameterTypes), args);
}
public static Object newInstance(Constructor cstruct, Object[] args) {
boolean flag = cstruct.isAccessible();
Object var4;
try {
cstruct.setAccessible(true);
Object result = cstruct.newInstance(args);
var4 = result;
} catch (InstantiationException var10) {
throw new CodeGenerationException(var10);
} catch (IllegalAccessException var11) {
throw new CodeGenerationException(var11);
} catch (InvocationTargetException var12) {
throw new CodeGenerationException(var12.getTargetException());
} finally {
cstruct.setAccessible(flag);
}
return var4;
}
反编译代理类class文件,源码如下:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.konka.proxy;
import java.lang.reflect.Method;
import net.sf.cglib.core.ReflectUtils;
import net.sf.cglib.core.Signature;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Factory;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class Sample$$EnhancerByCGLIB$$be45efdd extends Sample 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$test$0$Method;
private static final MethodProxy CGLIB$test$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;
static void CGLIB$STATICHOOK1() {
CGLIB$THREAD_CALLBACKS = new ThreadLocal();
CGLIB$emptyArgs = new Object[0];
Class var0 = Class.forName("com.jpeony.spring.proxy.cglib.Sample$$EnhancerByCGLIB$$be45efdd");
Class var1;
Method[] var10000 = ReflectUtils.findMethods(new String[]{"equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"}, (var1 = Class.forName("java.lang.Object")).getDeclaredMethods());
CGLIB$equals$1$Method = var10000[0];
CGLIB$equals$1$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$1");
CGLIB$toString$2$Method = var10000[1];
CGLIB$toString$2$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$2");
CGLIB$hashCode$3$Method = var10000[2];
CGLIB$hashCode$3$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$3");
CGLIB$clone$4$Method = var10000[3];
CGLIB$clone$4$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$4");
CGLIB$test$0$Method = ReflectUtils.findMethods(new String[]{"test", "()V"}, (var1 = Class.forName("com.jpeony.spring.proxy.cglib.Sample")).getDeclaredMethods())[0];
CGLIB$test$0$Proxy = MethodProxy.create(var1, var0, "()V", "test", "CGLIB$test$0");
}
final void CGLIB$test$0() {
super.test();
}
public final void test() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
var10000.intercept(this, CGLIB$test$0$Method, CGLIB$emptyArgs, CGLIB$test$0$Proxy);
} else {
super.test();
}
}
final boolean CGLIB$equals$1(Object var1) {
return super.equals(var1);
}
public final boolean equals(Object var1) {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
Object var2 = var10000.intercept(this, CGLIB$equals$1$Method, new Object[]{var1}, CGLIB$equals$1$Proxy);
return var2 == null ? false : (Boolean)var2;
} else {
return super.equals(var1);
}
}
final String CGLIB$toString$2() {
return super.toString();
}
public final String toString() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
return var10000 != null ? (String)var10000.intercept(this, CGLIB$toString$2$Method, CGLIB$emptyArgs, CGLIB$toString$2$Proxy) : super.toString();
}
final int CGLIB$hashCode$3() {
return super.hashCode();
}
public final int hashCode() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
Object var1 = var10000.intercept(this, CGLIB$hashCode$3$Method, CGLIB$emptyArgs, CGLIB$hashCode$3$Proxy);
return var1 == null ? 0 : ((Number)var1).intValue();
} else {
return super.hashCode();
}
}
final Object CGLIB$clone$4() throws CloneNotSupportedException {
return super.clone();
}
protected final Object clone() throws CloneNotSupportedException {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
return var10000 != null ? var10000.intercept(this, CGLIB$clone$4$Method, CGLIB$emptyArgs, CGLIB$clone$4$Proxy) : super.clone();
}
public static MethodProxy CGLIB$findMethodProxy(Signature var0) {
String var10000 = var0.toString();
switch(var10000.hashCode()) {
case -508378822:
if (var10000.equals("clone()Ljava/lang/Object;")) {
return CGLIB$clone$4$Proxy;
}
break;
case 1535311470:
if (var10000.equals("test()V")) {
return CGLIB$test$0$Proxy;
}
break;
case 1826985398:
if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
return CGLIB$equals$1$Proxy;
}
break;
case 1913648695:
if (var10000.equals("toString()Ljava/lang/String;")) {
return CGLIB$toString$2$Proxy;
}
break;
case 1984935277:
if (var10000.equals("hashCode()I")) {
return CGLIB$hashCode$3$Proxy;
}
}
return null;
}
public Sample$$EnhancerByCGLIB$$be45efdd() {
CGLIB$BIND_CALLBACKS(this);
}
public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) {
CGLIB$THREAD_CALLBACKS.set(var0);
}
public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] var0) {
CGLIB$STATIC_CALLBACKS = var0;
}
private static final void CGLIB$BIND_CALLBACKS(Object var0) {
Sample$$EnhancerByCGLIB$$be45efdd var1 = (Sample$$EnhancerByCGLIB$$be45efdd)var0;
if (!var1.CGLIB$BOUND) {
var1.CGLIB$BOUND = true;
Object var10000 = CGLIB$THREAD_CALLBACKS.get();
if (var10000 == null) {
var10000 = CGLIB$STATIC_CALLBACKS;
if (var10000 == null) {
return;
}
}
var1.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])var10000)[0];
}
}
public Object newInstance(Callback[] var1) {
CGLIB$SET_THREAD_CALLBACKS(var1);
Sample$$EnhancerByCGLIB$$be45efdd var10000 = new Sample$$EnhancerByCGLIB$$be45efdd();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}
public Object newInstance(Callback var1) {
CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});
Sample$$EnhancerByCGLIB$$be45efdd var10000 = new Sample$$EnhancerByCGLIB$$be45efdd();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}
public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
CGLIB$SET_THREAD_CALLBACKS(var3);
Sample$$EnhancerByCGLIB$$be45efdd var10000 = new Sample$$EnhancerByCGLIB$$be45efdd;
switch(var1.length) {
case 0:
var10000.<init>();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
default:
throw new IllegalArgumentException("Constructor not found");
}
}
public Callback getCallback(int var1) {
CGLIB$BIND_CALLBACKS(this);
MethodInterceptor var10000;
switch(var1) {
case 0:
var10000 = this.CGLIB$CALLBACK_0;
break;
default:
var10000 = null;
}
return var10000;
}
public void setCallback(int var1, Callback var2) {
switch(var1) {
case 0:
this.CGLIB$CALLBACK_0 = (MethodInterceptor)var2;
default:
}
}
public Callback[] getCallbacks() {
CGLIB$BIND_CALLBACKS(this);
return new Callback[]{this.CGLIB$CALLBACK_0};
}
public void setCallbacks(Callback[] var1) {
this.CGLIB$CALLBACK_0 = (MethodInterceptor)var1[0];
}
static {
CGLIB$STATICHOOK1();
}
}
可以看到代理对象继承于Sample,拦截器调用intercept()方法,intercept()方法由自定义ProxyFactory实现,所以,最后调用ProxyFactory中的intercept()方法
四、静态代理与动态代理的区别
1、静态代理在编译时就已经实现,编译完成后代理类是一个实际的class文件
2、动态代理是在运行时动态生成的,即编译完成后没有实际的class文件,而是在运行时动态生成类字节码,并加载到JVM中
五、JDK动态代理与CGLIB动态代理的区别
1、JDK动态代理只能对实现了接口的类生成代理,而不能针对类;CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法(继承)
2、Spring在选择用JDK还是CGLIB的依据:
- 当Bean实现接口时,Spring就会用JDK的动态代理
- 当Bean没有实现接口时,Spring使用CGLIB是实现
- 可以强制使用CGLIB(在spring配置中加入<aop:aspectj-autoproxy proxy-target-class="true"/>)
3、CGLIB比JDK快?
- 使用CGLIB实现动态代理,CGLIB底层采用ASM字节码生成框架,使用字节码技术生成代理类,比使用Java反射效率要高。唯一需要注意的是,CGLIB不能对声明为final的方法进行代理,因为CGLIB原理是动态生成被代理类的子类
- 在对JDK动态代理与CGLIB动态代理的代码实验中看,1W次执行下,JDK7及8的动态代理性能比CGLIB要好20%左右