该文章主要讲述代模式以及其实现方式,主要是 静态代理
, 动态代理
, Cglib代理
.
Proxy 概述 代理模式 是一种设计模式,提供了对目标对象额外的访问方式,即通过代理对象访问目标对象,这样可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象的功能。
简言之,代理模式就是设置一个中间代理来控制访问原目标对象,以达到增强原对象的功能和简化访问方式。
在Java
中实现代理主要有三种方式:
静态代理 在静态代理中,需要为每一个被代理对象创建一个代理类,并实现同一个接口。
示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public interface IConsumer { String consumer () ; }class ConsumerProxy implements IConsumer { private Consumer consumer; public ConsumerProxy (Consumer consumer) { this .consumer = consumer; } @Override public String consumer () { System.out.println("代理对象执行前的代码" ); String consumer = this .consumer.consumer(); System.out.println("代理对象执行后的代码" ); return consumer; } }class Consumer implements IConsumer { @Override public String consumer () { System.out.println("消费方法被调用了" ); return "Success" ; } }
从代码中看出,ConsumerProxy
代理对象持有了Consumer
被代理对象的引用,并在consumer方法
中调用了被代理对象的consumer方法
。来看看实际测试代码:
测试代码:
1 2 3 4 5 6 @Test public void testStaticProxy () { Consumer consumer = new Consumer (); IConsumer consumerProxy = new ConsumerProxy (consumer); System.out.println(consumerProxy.consumer()); }
输出结果:
1 2 3 4 代理对象执行前的代码 消费方法被调用了 代理对象执行后的代码 Success
优点:可以最大程度扩展被代理对象的功能。
缺点:被代理对象会随着代理对象的增加而增加,代码冗余。如果接口新增方法,代理对象和被代理对象都需要实现。
基于静态代理的缺点,有没有一种代理能够动态的生成代理对象呢?
动态代理 简介 动态代理利用了JDK API ,动态的在内存中构建代理对象,从而实现对目标对象的代理功能。
动态代理又被称为JDK代理或接口代理。
相比于静态代理, 动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类的函数。
先来看一个示例,了解一下动态代理的基本使用。
示例代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 public interface IDynamic { void dynamicProxy () ; }class Dynamic implements IDynamic { @Override public void dynamicProxy () { System.out.println("目标方法执行了" ); } }class DynamicProxyInvocation implements InvocationHandler { private Object proxyTarget; public DynamicProxyInvocation (Object proxyTarget) { this .proxyTarget = proxyTarget; } @Override public Object invoke (Object proxy, Method method, Object[] args) throws Throwable { System.out.println("代理执行前" ); Object invokeResult = method.invoke(proxyTarget, args); System.out.println("代理执行后" ); return invokeResult; } }
测试类 1 2 3 4 5 6 7 @Test public void testDynamicProxy () { Dynamic proxyTarget = new Dynamic (); IDynamic dynamicProxy = (IDynamic) Proxy.newProxyInstance(proxyTarget.getClass().getClassLoader(), proxyTarget.getClass().getInterfaces(), new DynamicProxyInvocation (proxyTarget)); dynamicProxy.dynamicProxy(); }
测试结果
在上面的代码中,看到了很多未知的接口和类,主要是Proxy类
,InvocationHandler接口
。
Proxy
疑问 Proxy.newProxyInstance()
方法返回的代理类是如何生成
?为什么Jdk 的动态代理被代理类必须实现接口
?
简介 Proxy提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类
。
源代码 从上面的示例代码可以看出代理类的实例是由Proxy.newProxyInstance
返回的,那么我们重点关注Proxy.newProxyInstance
这个方法。
创建代理实例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 protected InvocationHandler h;protected Proxy (InvocationHandler h) { Objects.requireNonNull(h); this .h = h; }public static Object newProxyInstance (ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) { Class<?> cl = getProxyClass0(loader, intfs); if (sm != null ) { checkNewProxyPermission(Reflection.getCallerClass(), cl); } 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 ; } }); } return cons.newInstance(new Object []{h}); }
在newProxyInstance
方法中有两个比较核心的步骤,分别如下:
步骤①:获取代理类的Class
实例。
步骤②:获取代理类带有InvocationHandler
参数的构造方法。
除了上面两个比较重要的步骤,还需要关注InvocationHandler h
和Proxy(InvocationHandler h)
,后面会进行讲解。
获取代理类字节码 getProxyClass0
最终会调用到ProxyClassFactory.apply()
方法中,具体操作细节,可自行Debug查看调用链。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 private static final class ProxyClassFactory implements BiFunction <ClassLoader, Class<?>[], Class<?>> { private static final String proxyClassNamePrefix = "$Proxy" ; @Override public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) { long num = nextUniqueNumber.getAndIncrement(); String proxyName = proxyPkg + proxyClassNamePrefix + num; byte [] proxyClassFile = ProxyGenerator.generateProxyClass( proxyName, interfaces, accessFlags); try { return defineClass0(loader, proxyName, proxyClassFile, 0 , proxyClassFile.length); } catch (ClassFormatError e) { throw new IllegalArgumentException (e.toString()); } }
步骤①:调用ProxyGenerator.generateProxyClass
生成代理类.class的字节数组。
步骤②:调用defineClass0
生成.class文件,并加载到Jvm中。
手动生成Class 从上面我们得知了Proxy类在最后调用了ProxyGenerator.generateProxyClass
方法生成了代理类的.class
字节数组。那么生成的.class
结构是怎样的呢?让我们来手动触发调用一下。
示例代码 1 2 3 4 5 6 7 8 9 10 11 12 public class ProxyGeneratorTest { public static void main (String[] args) throws Exception { byte [] dynamicObj = ProxyGenerator.generateProxyClass( "ManualGeneratorDynamicClass" , new Class []{IDynamic.class}, 17 ); FileOutputStream out = new FileOutputStream (new File ("ManualGeneratorDynamicClass.class" )); out.write(dynamicObj); out.flush(); out.close(); } }
代理类.class
文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 public final class ManualGeneratorDynamicClass extends Proxy implements IDynamic { private static Method m1; private static Method m2; private static Method m3; private static Method m0; public ManualGeneratorDynamicClass (InvocationHandler var1) throws { super (var1); } public final boolean equals (Object var1) throws { try { return (Boolean)super .h.invoke(this , m1, new Object []{var1}); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException (var4); } } 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 void dynamicProxy () throws { try { super .h.invoke(this , m3, (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 ); } 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" )); m2 = Class.forName("java.lang.Object" ).getMethod("toString" ); m3 = Class.forName("io.better.jdk.proxy.dynamicproxy.IDynamic" ).getMethod("dynamicProxy" ); m0 = Class.forName("java.lang.Object" ).getMethod("hashCode" ); } catch (NoSuchMethodException var2) { throw new NoSuchMethodError (var2.getMessage()); } catch (ClassNotFoundException var3) { throw new NoClassDefFoundError (var3.getMessage()); } } }
从代码可以看出ManualGeneratorDynamicClass
类不仅继承了Proxy
类(解释了Porxy为什么是所有代理类的超类),还实现了被代理类
实现的接口(解释了为什么被代理类必须实现接口?)。
InvocationHandler
通过上面对Proxy的了解,我们知道了代理类的方法调用最终会调用到InvocationHandler实例的invoke方法。
简介 InvocationHandler是代理实例的调用处理程序(InvocationHandler实例)实现的接口。每个代理实例都有一个关联的调用处理程序
。 当一个方法是在代理实例调用,方法调用进行编码,并分发给invoke的调用处理程序的方法。
源代码 1 2 3 4 5 6 7 8 9 10 public interface InvocationHandler { public Object invoke (Object proxy, Method method, Object[] args) throws Throwable; }
总结 优缺点 优点:
缺点:
代理机制 动态代理类(以下简称为代理类)是一种类,该类实现创建类时(调用newProxyInstance方法时)
在运行时指定的接口列表(interfaces参数)
,代理接口是由代理类实现的接口。代理实例是代理类的实例。每个代理实例都有一个关联的调用处理程序对象,该对象实现接口InvocationHandler
。
通过其代理接口之一对代理实例进行的方法调用将分派给该实例的调用处理程序的invoke方法,并传递该代理实例(proxy参数)
,一个标识所调用方法的java.lang.reflect.Method对象(method参数)
以及一个数组包含参数的Object类型(args参数)
。
Cglib代理 前言 上面我使用了动态代理,知道了动态代理一些优缺点,为了弥补Jdk动态代理的缺点,Cglib诞生了,被代理类无需实现接口也能被代理。
简介 cglib
-字节码生成库是用于生成和转换Java字节码的高级API。AOP,测试,数据访问框架使用它来生成动态代理对象并拦截字段访问。
示例代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 package io.better.jdk.proxy.cglibproxy;import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;import java.util.Objects;public class CglibBean { void proxy () { System.out.println("proxy execute ...." ); } }class CglibProxyFactory implements MethodInterceptor { private Object proxyTarget; public CglibProxyFactory setProxyTarget (Object proxyTarget) { this .proxyTarget = proxyTarget; return this ; } @Override public Object intercept (Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("cglib 执行前" ); Object result = method.invoke(proxyTarget, objects); System.out.println("cglib 执行后" ); return result; } public Object getProxyInstance () { if (Objects.isNull(proxyTarget)) { throw new IllegalArgumentException ("被代理对象不能为空" ); } Enhancer enhancer = new Enhancer (); enhancer.setSuperclass(proxyTarget.getClass()); enhancer.setCallback(this ); return enhancer.create(); } }
测试代码 1 2 3 4 5 6 @Test public void testCglib () { CglibBean proxyTarget = new CglibBean (); CglibBean proxyInstance = (CglibBean) new CglibProxyFactory ().setProxyTarget(proxyTarget).getProxyInstance(); proxyInstance.proxy(); }
测试结果 1 2 3 cglib 执行前 proxy execute .... cglib 执行后
源代码 从示例代码可以看出Enhancer
类是创建代理对象的核心,那么Enhancer是如何创建代理类的呢?创建的代理类结构是如何呢?
在代码中一共操作了四部:
创建Enhancer对象。
调用setSuperclass设置父类。
调用setCallback设置回调。
调用create创建代理实例。
创建Enhancer对象 构造器描述 创建一个新的增强器。每个生成的对象都应使用一个新的Enhancer对象,并且不应在线程之间共享。要创建生成的类的其他实例,请使用Factory接口。
继承图
Enhancer构造器 1 2 3 4 5 6 7 8 9 10 private static final Source SOURCE = new Source (Enhancer.class.getName());public Enhancer () { super (SOURCE); }protected AbstractClassGenerator (Source source) { this .source = source; }
代码中将Enhancer的名称封装到了Source实例中,并调用父类AbstractClassGenerator构造器进行赋值 。
设置父类 方法描述 设置生成的类将继承的类。 为了方便起见,如果提供的超类实际上是接口,则将使用适当的参数来调用setInterfaces。 非接口参数不能声明为final,并且必须具有可访问的构造函数。
方法setSuperclass
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 private Class superclass;public void setSuperclass (Class superclass) { if (superclass != null && superclass.isInterface()) { setInterfaces(new Class []{ superclass }); } else if (superclass != null && superclass.equals(Object.class)) { this .superclass = null ; } else { this .superclass = superclass; } }private Class[] interfaces;public void setInterfaces (Class[] interfaces) { this .interfaces = interfaces; }
方法逻辑比较简单就是给Enhancer实例中的字段进行赋值。
设置回调 方法描述 设置要使用的单个回调。 如果使用createClass则被忽略。
方法setCallback
1 2 3 4 5 6 7 8 9 10 11 12 private Callback[] callbacks;public void setCallback (final Callback callback) { setCallbacks(new Callback []{ callback }); }public void setCallbacks (Callback[] callbacks) { if (callbacks != null && callbacks.length == 0 ) { throw new IllegalArgumentException ("Array cannot be empty" ); } this .callbacks = callbacks; }
该方法也是给Enhancer实例中的callbacks
字段进行赋值
创建代理实例 方法描述 如有必要,生成一个新类,并使用指定的回调(如果有)来创建一个新的对象实例。 使用超类的no-arg构造函数。
入口-Enhancer.create
1 2 3 4 5 public Object create () { classOnly = false ; argumentTypes = null ; return createHelper(); }
createHelper
1 2 3 4 5 6 7 8 9 10 11 12 13 private Object createHelper () { preValidate(); Object key = KEY_FACTORY.newInstance((superclass != null ) ? superclass.getName() : null , ReflectUtils.getNames(interfaces), filter == ALL_ZERO ? null : new WeakCacheKey <CallbackFilter>(filter), callbackTypes, useFactory, interceptDuringConstruction, serialVersionUID); this .currentKey = key; Object result = super .create(key); return result; }
KEY_FACTORY.newInstance
生成的key
需要特别注意,后面在生成代理类Class时会用此key与Class一对一绑定
。
继续查看父类的create
方法。
AbstractClassGenerator.create
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 protected Object create (Object key) { try { ClassLoader loader = getClassLoader(); Map<ClassLoader, ClassLoaderData> cache = CACHE; ClassLoaderData data = cache.get(loader); this .key = key; Object obj = data.get(this , getUseCache()); if (obj instanceof Class) { return firstInstance((Class) obj); } return nextInstance(obj); } catch (RuntimeException e) { } }
上诉代码中忽略了部分代码,重点关注步骤①
和步骤②
对应的两个方法。
步骤①:调用ClassLoaderData.get()
获取代理类Class对象。
步骤②:使用代理类Class对象创建代理实例。
步骤① 知道了代理对象是通过ClassLoaderData.get
方法获取的,那么必须了解ClassLoaderData
的作用及其结构。
ClassLoaderData
那么ClassLoaderData
类有什么作用呢?通过Debug来看看ClassLoaderData内部结构。
类结构图:
generatedClasses
:用于存储已经生成的Class对象。
reservedClassNames
:用于存储已经解析的Class名称(全路径)。
classLoader
:加载生成Class对象的加载器。
可以看出ClassLoaderData内部管理生成的Class类和加载Class所需的ClassLoader,可以简单理解为生成Class并存储Class的容器
。
init
那么ClassLoaderData
是如何初始化的呢 ?我们进入ClassLoaderData的构造器看看:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public ClassLoaderData (ClassLoader classLoader) { if (classLoader == null ) { throw new IllegalArgumentException ("classLoader == null is not yet supported" ); } this .classLoader = new WeakReference <ClassLoader>(classLoader); Function<AbstractClassGenerator, Object> load = new Function <AbstractClassGenerator, Object>() { public Object apply (AbstractClassGenerator gen) { Class klass = gen.generate(ClassLoaderData.this ); return gen.wrapCachedClass(klass); } }; generatedClasses = new LoadingCache <AbstractClassGenerator, Object, Object>(GET_KEY, load); }
可以看出classLoader,generatedClasses
两个对象被进行了初始化,在这里重点注意load
这个函数 ,这个函数就是创建代理类Class的关键
。
ClassLoaderData.get
了解了ClassLoaderData
后,我们进入 get()
方法一探究竟:
1 2 3 4 5 6 7 8 9 10 public Object get (AbstractClassGenerator gen, boolean useCache) { if (!useCache) { return gen.generate(ClassLoaderData.this ); } else { Object cachedValue = generatedClasses.get(gen); return gen.unwrapCachedValue(cachedValue); } }
如果不修改useCache的值,代码最终会调用generatedClasses.get
方法。到这里是不是感觉generatedClasses
这个对象是不是非常眼熟,没错他就是ClassLoaderData中存放生成过Class的对象
。
接着进入generatedClasses对象一探究竟。
LoadingCache
在如何LoadingCache.get
方法前,我们先来看看LoadingCache
的构造函数:
1 2 3 4 5 6 public LoadingCache (Function<K, KK> keyMapper, Function<K, V> loader) { this .keyMapper = keyMapper; this .loader = loader; this .map = new ConcurrentHashMap <KK, Object>(); }
LoadingCache构造函数主要是在对自身变量进行赋值
操作。
loader
:类型为函数,用于创建代理类Class
keyMapper
:类型为函数,用于获取前面Enhancer.create
方法中通过KEY_FACTORY.newInstance
创建的key
map
:key=keyMapper函数获取到的key
,value=loader函数生成的代理Class数据
。
LoadingCache.get
1 2 3 4 5 6 7 8 9 10 11 public V get (K key) { final KK cacheKey = keyMapper.apply(key); Object v = map.get(cacheKey); if (v != null && !(v instanceof FutureTask)) { return (V) v; } return createEntry(key, cacheKey, v); }
LoadingCache.createEntry
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 protected V createEntry (final K key, KK cacheKey, Object v) { FutureTask<V> task; boolean creator = false ; if (v != null ) { task = (FutureTask<V>) v; } else { task = new FutureTask <V>(new Callable <V>() { public V call () throws Exception { return loader.apply(key); } }); Object prevTask = map.putIfAbsent(cacheKey, task); if (prevTask == null ) { creator = true ; task.run(); } } V result; try { result = task.get(); } catch (InterruptedException e) {} if (creator) { map.put(cacheKey, result); } return result; }
这个方法主要是创建FutureTask用于异步创建Class对象,并对其结果进行了缓存,提高性能。
接下来调用load.apply
执行函数,最终调用至AbstractClassGenerator.generate
方法中。
1 2 3 4 5 6 Function<AbstractClassGenerator, Object> load = new Function <AbstractClassGenerator, Object>() { public Object apply (AbstractClassGenerator gen) { Class klass = gen.generate(ClassLoaderData.this ); return gen.wrapCachedClass(klass); } };
AbstractClassGenerator.generate
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 protected Class generate (ClassLoaderData data) { Class gen; Object save = CURRENT.get(); CURRENT.set(this ); try { ClassLoader classLoader = data.getClassLoader(); byte [] b = strategy.generate(this ); String className = ClassNameReader.getClassName(new ClassReader (b)); ProtectionDomain protectionDomain = getProtectionDomain(); synchronized (classLoader) { if (protectionDomain == null ) { gen = ReflectUtils.defineClass(className, b, classLoader); } else { gen = ReflectUtils.defineClass(className, b, classLoader, protectionDomain); } } return gen; } catch (RuntimeException e) { } finally { CURRENT.set(save); } }
步骤①:
调用strategy.generate
方法生成代理类字节码数组。
其默认实例为GeneratorStrategy strategy = DefaultGeneratorStrategy.INSTANCE;
。
strategy.generate
方法最终会调用到Enhancer.generateClass(ClassVisitor v)
方法,这里面包含了生成代理类字节码具体步骤(这里了不做讲解,有兴趣的可自行查看)。
步骤②:
调用ReflectUtils.defineClass
方法使用传入的ClassLoader加载生成的代理类字节码数组。
1 2 3 4 5 6 7 8 9 10 11 12 public static Class defineClass (String className, byte [] b, ClassLoader loader, ProtectionDomain protectionDomain) throws Exception { Class c; if (DEFINE_CLASS != null ) { Object[] args = new Object []{className, b, new Integer (0 ), new Integer (b.length), protectionDomain }; c = (Class)DEFINE_CLASS.invoke(loader, args); } Class.forName(className, true , loader); return c; }
1 private static Method DEFINE_CLASS, DEFINE_CLASS_UNSAFE;
DEFINE_CLASS
其实是java.lang.ClassLoader.defineClass
对应的Method对象。
步骤② 走完步骤①代理类的Class对象已生成,接下来就是通过该Class对象生成代理实例。
我们进入nextInstance(obj);
方法查看实例化流程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 protected Object nextInstance (Object instance) { EnhancerFactoryData data = (EnhancerFactoryData) instance; if (classOnly) { return data.generatedClass; } Class[] argumentTypes = this .argumentTypes; Object[] arguments = this .arguments; if (argumentTypes == null ) { argumentTypes = Constants.EMPTY_CLASS_ARRAY; arguments = null ; } return data.newInstance(argumentTypes, arguments, callbacks); }
该方法在调用代理类Class构造函数前,处理好对应的构造函数参数类型和参数。
重点关注步骤①:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public Object newInstance (Class[] argumentTypes, Object[] arguments, Callback[] callbacks) { setThreadCallbacks(callbacks); try { if (primaryConstructorArgTypes == argumentTypes || Arrays.equals(primaryConstructorArgTypes, argumentTypes)) { return ReflectUtils.newInstance(primaryConstructor, arguments); } return ReflectUtils.newInstance(generatedClass, argumentTypes, arguments); } finally { setThreadCallbacks(null ); } }
至此Cglib创建代理对象流程分析完毕。
使用Cglib手动生成Class文件 分析完Cglib整个创建流程,我还不能像Jdk动态代理一样了解到生成的代理类字节码到底是怎样的?接下来我们使用Cglib手动生成一个代理类的Class文件。
由于strategy.generate
方法所需参数较为复杂,可Debug
至byte[] b = strategy.generate(this);
这行代码利用IDEA的Evaluate Expression
功能手动输入以下代码:
1 2 3 4 FileOutputStream out = new FileOutputStream (new File ("ManualGeneratorProxyCglibProxy.class" )); out.write(b); out.flush(); out.close();
生成文件如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 public class CglibBean$$EnhancerByCGLIB$$70184645 extends CglibBean 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$proxy$0 $Method; private static final MethodProxy CGLIB$proxy$0 $Proxy; private static final Object[] CGLIB$emptyArgs; static void CGLIB$STATICHOOK1() { CGLIB$THREAD_CALLBACKS = new ThreadLocal (); CGLIB$emptyArgs = new Object [0 ]; Class var0 = Class.forName("io.better.jdk.proxy.cglibproxy.CglibBean$$EnhancerByCGLIB$$70184645" ); Class var1; CGLIB$proxy$0 $Method = ReflectUtils.findMethods(new String []{"proxy" , "()V" }, (var1 = Class.forName("io.better.jdk.proxy.cglibproxy.CglibBean" )).getDeclaredMethods())[0 ]; CGLIB$proxy$0 $Proxy = MethodProxy.create(var1, var0, "()V" , "proxy" , "CGLIB$proxy$0" ); } final void CGLIB$proxy$0 () { super .proxy(); } final void proxy () { 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$proxy$0 $Method, CGLIB$emptyArgs, CGLIB$proxy$0 $Proxy); } else { super .proxy(); } } static { CGLIB$STATICHOOK1(); } }
上诉代码中忽略了equals,hashCode,toString
等方法。感兴趣的同学可以自己操作一下。
总结
静态代理实现较简单,只要代理对象对目标对象进行包装,即可实现增强功能,但静态代理只能为一个目标对象服务,如果目标对象过多,则会产生很多代理类。
JDK动态代理需要目标对象实现业务接口,代理类只需实现InvocationHandler接口。
动态代理生成的类为 lass com.sun.proxy.$Proxy4,cglib代理生成的类为class com.cglib.UserDao$$EnhancerByCGLIB$$552188b6。
静态代理在编译时产生class字节码文件,可以直接使用,效率高。
动态代理必须实现InvocationHandler接口,通过反射代理方法,比较消耗系统性能,但可以减少代理类的数量,使用更灵活。
cglib代理无需实现接口,通过生成类字节码实现代理,比反射稍快,不存在性能问题,但cglib会继承目标对象,需要重写方法,所以目标对象不能为final类