1.CGLIB包的介绍
代理为控制要访问的目标对象提供了一种途径。当访问对象时,它引入了一个间接的层。JDK自从1.3版本开始,就引入了动态代理,并且经常被用来动态地创
建代理。JDK的动态代理用起来非常简单,当它有一个限制,就是使用动态代理的对象必须实现一个或多个接口。如果想代理没有实现接口的继承的类,该怎么
办?现在我们可以使用CGLIB包 CGLIB是一个强大的高性能的代码生成包。它广泛的被许多AOP的框架使用,例如Spring
AOP和dynaop,为他们提供方法的interception(拦截)。最流行的OR
Mapping工具hibernate也使用CGLIB来代理单端single-ended(多对一和一对一)关联(对集合的延迟抓取,是采用其他机制实
现的)。EasyMock和jMock是通过使用模仿(moke)对象来测试java代码的包。它们都通过使用CGLIB来为那些没有接口的类创建模仿
(moke)对象。 CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。除了CGLIB包,脚本语言例如
Groovy和BeanShell,也是使用ASM来生成java的字节码。当不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文
件的格式和指令集都很熟悉。
Figure 1: CGLIB Library and ASM Bytecode Framework
图
一显示了和CGLIB包和一些框架和语言的关系图。需要注意的是一些框架例如Spring
AOP和Hibernate,它们为了满足需要经常同时使用JDK的动态代理和CGLIB包。Hiberater使用JDK的动态代理实现一个专门为
WebShere应用服务器的事务管理适配器;Spring AOP,如果不强制使用CGLIB包,默认情况是使用JDK的动态代理来代理接口。
2.CGLIB 代理的APIS CGLIB包的基本代码很少,当学起来有一定的困难,主要是缺少文档,这也是开源软件的一个不足之处。目前CGLIB的版本是(2.1.2),主要由一下部分组成: net.sf.cglib.core 底层字节码处理类,他们大部分与ASM有关系。 · net.sf.cglib.transform 编译期或运行期类和类文件的转换 · net.sf.cglib.proxy 实现创建代理和方法拦截器的类 · net.sf.cglib.reflect 实现快速反射和C#风格代理的类 · net.sf.cglib.util 集合排序工具类 · net.sf.cglib.beans JavaBean相关的工具类 大多时候,仅仅为了动态地创建代理,你仅需要使用到代理包中很少的一些API。
正
如我们先前所讨论的,CGLIB包是在ASM之上的一个高级别的层。对代理那些没有实现接口的类非常有用。本质上,它是通过动态的生成一个子类去覆盖所要
代理类的不是final的方法,并设置好callback,则原有类的每个方法调用就会转变成调用用户定义的拦截方法(interceptors),这比
JDK动态代理方法快多了。
Figure 2: CGLIB library APIs commonly used for proxying classes 图2
为我们演示了创建一个具体类的代理时,通常要用到的CGLIB包的APIs。net.sf.cglib.proxy.Callback接口在CGLIB包
中是一个很关键的接口,所有被net.sf.cglib.proxy.Enhancer类调用的回调(callback)接口都要继承这个接口。
net.sf.cglib.pr用oxy.MethodInterceptor接口是最通用的回调(callback)类型,它经常被基于代理的AOP用
来实现拦截(intercept)方法的调用。这个接口只定义了一个方法 public Object intercept(Object object, java.lang.reflect.Method method, Object[] args, MethodProxy proxy) throws Throwable; 当net.sf.cglib.proxy.MethodInterceptor做为所有代理方法的回调
(callback)时,当对基于代理的方法调用时,在调用原对象的方法的之前会调用这个方法,如图3所示。第一个参数是代理对像,第二和第三个参数分别
是拦截的方法和方法的参数。原来的方法可能通过使用java.lang.reflect.Method对象的一般反射调用,或者使用
net.sf.cglib.proxy.MethodProxy对象调用。net.sf.cglib.proxy.MethodProxy通常被首选使
用,因为它更快。在这个方法中,我们可以在调用原方法之前或之后注入自己的代码。
Figure 3: CGLIB MethodInterceptor net.sf.cglib.proxy.MethodInterceptor能够满足任何的拦截(interception )需要,当对有些情况下可能过度。为了简化和提高性能,CGLIB包提供了一些专门的回调(callback)类型。例如:net.sf.cglib.proxy.FixedValue 为提高性能,FixedValue回调对强制某一特别方法返回固定值是有用的。 net.sf.cglib.proxy.NoOp NoOp回调把对方法调用直接委派到这个方法在父类中的实现。 net.sf.cglib.proxy.LazyLoader 当实际的对象需要延迟装载时,可以使用LazyLoader回调。一旦实际对象被装载,它将被每一个调用代理对象的方法使用。 net.sf.cglib.proxy.Dispatcher Dispathcer回调和LazyLoader回调有相同的特点,不同的是,当代理方法被调用时,装载对象的方法也总要被调用。 net.sf.cglib.proxy.ProxyRefDispatcher ProxyRefDispatcher回调和Dispatcher一样,不同的是,它可以把代理对象作为装载对象方法的一个参数传递。 如
图3所示,代理类的所以方法经常会用到回调(callback),当是你也可以使用net.sf.cglib.proxy.CallbackFilter
有选择的对一些方法使用回调(callback),这种考虑周详的控制特性在JDK的动态代理中是没有的。在JDK代理中,对
java.lang.reflect.InvocationHandler方法的调用对代理类的所以方法都有效。 除了代理类外,CGLIB通过提供一个对java.lang.reflect.Proxy的drop-in替代来实现对对接口的代理。因为这种代理能力的替代很少被用到,因此相应的APIs也很少提到。
CGLIB的代理包也对net.sf.cglib.proxy.Mixin提供支持。基本上,它允许多个对象被绑定到一个单个的大对象。在代理中对方法的调用委托到下面相应的对象中。
接下来我们看看如何使用CGLIB代理APIs创建代理。
创建一个简单的代理CGLIB代理最核心的是net.sf.cglib.proxy.Enhancer类,为了创建一个代理,最起码你要用到这个类。首先,让我们使用NoOp回调创建一个代理: /** * Create a proxy using NoOp callback. The target class * must have a default zero-argument constructor. * * @param targetClass the super class of the proxy * @return a new proxy for a target class instance */ public Object createProxy(Class targetClass) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(targetClass); enhancer.setCallback(NoOp.INSTANCE); return enhancer.create(); } 返
回值是target类一个实例的代理。在这个例子中,我们为net.sf.cglib.proxy.Enhancer
配置了一个单一的回调(callback)。我们可以看到很少直接创建一个简单的代理,而是创建一个
net.sf.cglib.proxy.Enhancer的实例,在net.sf.cglib.proxy.Enhancer类中你可使用静态帮助方法创
建一个简单的代理。一般推荐使用上面例子的方法创建代理,因为它允许你通过配置net.sf.cglib.proxy.Enhancer实例很好的控制代
理的创建。
要注意的是,target类是作为产生的代理的父类传进来的。不同于JDK的动态代理,它不能在创建代理时传target对
象,target对象必须被CGLIB包来创建。在这个例子中,默认的无参数构造器时用来创建target实例的。如果你想用CGLIB来创建有参数的实
例,用net.sf.cglib.proxy.Enhancer.create(Class[],
Object[])方法替代net.sf.cglib.proxy.Enhancer.create()就可以了。方法中第一个参数定义了参数的类型,第
二个是参数的值。在参数中,基本类型应被转化成类的类型。 Use a MethodInterceptor为了更好的使用代理,我们可以使用自己定义的MethodInterceptor类型回调(callback)来代替net.sf.cglib.proxy.NoOp回调。当对代理中所有方法的调用时,都会转向MethodInterceptor类型的拦截(intercept)方法,在拦截方法中再调用底层对象相应的方法。下面我们举个例子,假设你想对目标对象的所有方法调用进行权限的检查,如果没有经过授权,就抛出一个运行时的异常AuthorizationException。其中AuthorizationService.java接口的代码如下:
package com.lizjason.cglibproxy;
import java.lang.reflect.Method;
/** * A simple authorization service for illustration purpose. * * @author Jason Zhicheng Li (jason@) */ public interface AuthorizationService { /** * Authorization check for a method call. An AuthorizationException * will be thrown if the check fails. */ void authorize(Method method); } 对net.sf.cglib.proxy.MethodInterceptor接口的实现的类AuthorizationInterceptor.java代码如下: package com.lizjason.cglibproxy.impl; import java.lang.reflect.Method; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import com.lizjason.cglibproxy.AuthorizationService; /** * A simple MethodInterceptor implementation to * apply authorization checks for proxy method calls. * * @author Jason Zhicheng Li (jason@) * */ public class AuthorizationInterceptor implements MethodInterceptor { private AuthorizationService authorizationService; /** * Create a AuthorizationInterceptor with the given * AuthorizationService */ public AuthorizationInterceptor (AuthorizationService authorizationService) { this.authorizationService = authorizationService; } /** * Intercept the proxy method invocations to inject authorization check. * The original method is invoked through MethodProxy. * @param object the proxy object * @param method intercepted Method * @param args arguments of the method * @param proxy the proxy used to invoke the original method * @throws Throwable any exception may be thrown; if so, super method will not be invoked * @return any value compatible with the signature of the proxied method. */ public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy ) throws Throwable { if (authorizationService != null) { //may throw an AuthorizationException if authorization failed authorizationService.authorize(method); } return methodProxy.invokeSuper(object, args); } } 我们可以看到在拦截方法中,首先进行权限的检查,如果通过权限的检查,拦截方法再调用目标对象的原始方法。由于性能的原因,对原始方法的调用我们使用CGLIB的net.sf.cglib.proxy.MethodProxy对象,而不是反射中一般使用 java.lang.reflect.Method对象。
Use a CallbackFilter
net.sf.cglib.proxy.CallbackFilter允许我们在方法层设置回调(callback)。假如你有一个PersistenceServiceImpl类,它有两个方法:save和load,其中方法save需要权限检查,而方法load不需要权限检查。
package com.lizjason.cglibproxy.impl; import com.lizjason.cglibproxy.PersistenceService; /** * A simple implementation of PersistenceService interface * * @author Jason Zhicheng Li (jason@) */ public class PersistenceServiceImpl implements PersistenceService { public void save(long id, String data) { System.out.println(data + " has been saved successfully."); } public String load(long id) { return "Jason Zhicheng Li"; } } 注意到PersistenceServiceImpl类实现了PersistenceService 接口,因此没有要求要使用CGLIB创建代理。 net.sf.cglib.proxy.CallbackFilter 接口的实现如下: package com.lizjason.cglibproxy.impl; import java.lang.reflect.Method; import net.sf.cglib.proxy.CallbackFilter; /** * An implementation of CallbackFilter for PersistenceServiceImpl * * @author Jason Zhicheng Li (jason@) */ public class PersistenceServiceCallbackFilter implements CallbackFilter { //callback index for save method private static final int SAVE = 0; //callback index for load method private static final int LOAD = 1; /** * Specify which callback to use for the method being invoked. * @method the method being invoked. * @return the callback index in the callback array for this method */ public int accept(Method method) { String name = method.getName(); if ("save".equals(name)) { return SAVE; } // for other methods, including the load method, use the // second callback return LOAD; } } accept方法中对代理方法和回调进行了匹配,返回的值是某方法在回调数组中的索引。下面是PersistenceServiceImpl类代理的实现。
...
Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(PersistenceServiceImpl.class); CallbackFilter callbackFilter = new PersistenceServiceCallbackFilter(); enhancer.setCallbackFilter(callbackFilter); AuthorizationService authorizationService = ... Callback saveCallback = new AuthorizationInterceptor(authorizationService); Callback loadCallback = NoOp.INSTANCE; Callback[] callbacks = new Callback[]{saveCallback, loadCallback }; enhancer.setCallbacks(callbacks); ... return (PersistenceServiceImpl)enhancer.create(); 在这个例子中save方法使用了AuthorizationInterceptor实例,load方法使用了NoOp实例。此外,你也可以通过 net.sf.cglib.proxy.Enhancer.setInterfaces(Class[])方法指定代理对象所实现的接口。
除了为net.sf.cglib.proxy.Enhancer指定回调数组,你还可以通过net.sf.cglib.proxy.Enhancer.setCallbackTypes(Class[]) 方法指定回调类型数组。当创建代理时,如果你没有回调实例的数组,就可以使用回调类型。象使用回调一样,你必须使用,net.sf.cglib.proxy.CallbackFilter为每一个方法指定一个回调类型索引。你可以从http://www./downloads/下载设置回调类型和接口的完整代码。 cglib 的几个测试demo
增强一个已有类
- <span style="color: rgb(0, 0, 0); font-weight: bold;">public</span> <span style="color: rgb(0, 0, 0); font-weight: bold;">class</span> MyClass <span style="color: rgb(102, 204, 102);">{</span><br> <br> <span style="color: rgb(0, 0, 0); font-weight: bold;">public</span> <span style="color: rgb(153, 51, 51);">void</span> method<span style="color: rgb(102, 204, 102);">(</span><span style="color: rgb(102, 204, 102);">)</span> <span style="color: rgb(102, 204, 102);">{</span><br> <a href="http://www.google.com/search?hl=en&q=allinurl%3ASystem+java.sun.com&bntI=I%27m%20Feeling%20Lucky"><span style="color: rgb(170, 170, 221); font-weight: bold;">System</span></a>.<span style="color: rgb(0, 102, 0);">out</span>.<span style="color: rgb(0, 102, 0);">println</span><span style="color: rgb(102, 204, 102);">(</span><span style="color: rgb(255, 0, 0);">"MyClass.method()"</span><span style="color: rgb(102, 204, 102);">)</span>;<br> <span style="color: rgb(102, 204, 102);">}</span><br><span style="color: rgb(102, 204, 102);">}</span>
- <span style="color: rgb(161, 161, 0);">import java.lang.reflect.Method;</span><br> <br><span style="color: rgb(161, 161, 0);">import net.sf.cglib.proxy.Enhancer;</span><br><span style="color: rgb(161, 161, 0);">import net.sf.cglib.proxy.MethodProxy;</span><br><span style="color: rgb(161, 161, 0);">import net.sf.cglib.proxy.MethodInterceptor;</span><br> <br><span style="color: rgb(0, 0, 0); font-weight: bold;">public</span> <span style="color: rgb(0, 0, 0); font-weight: bold;">class</span> Main <span style="color: rgb(102, 204, 102);">{</span><br> <br> <span style="color: rgb(0, 0, 0); font-weight: bold;">public</span> <span style="color: rgb(0, 0, 0); font-weight: bold;">static</span> <span style="color: rgb(153, 51, 51);">void</span> main<span style="color: rgb(102, 204, 102);">(</span><a href="http://www.google.com/search?hl=en&q=allinurl%3AString+java.sun.com&bntI=I%27m%20Feeling%20Lucky"><span style="color: rgb(170, 170, 221); font-weight: bold;">String</span></a><span style="color: rgb(102, 204, 102);">[</span><span style="color: rgb(102, 204, 102);">]</span> args<span style="color: rgb(102, 204, 102);">)</span> <span style="color: rgb(102, 204, 102);">{</span><br> <br> Enhancer enhancer = <span style="color: rgb(0, 0, 0); font-weight: bold;">new</span> Enhancer<span style="color: rgb(102, 204, 102);">(</span><span style="color: rgb(102, 204, 102);">)</span>;<br> <br> enhancer.<span style="color: rgb(0, 102, 0);">setSuperclass</span><span style="color: rgb(102, 204, 102);">(</span>MyClass.<span style="color: rgb(0, 0, 0); font-weight: bold;">class</span><span style="color: rgb(102, 204, 102);">)</span>;<br> enhancer.<span style="color: rgb(0, 102, 0);">setCallback</span><span style="color: rgb(102, 204, 102);">(</span> <span style="color: rgb(0, 0, 0); font-weight: bold;">new</span> MethodInterceptorImpl<span style="color: rgb(102, 204, 102);">(</span><span style="color: rgb(102, 204, 102);">)</span> <span style="color: rgb(102, 204, 102);">)</span>;<br> <br> <br> MyClass my = <span style="color: rgb(102, 204, 102);">(</span>MyClass<span style="color: rgb(102, 204, 102);">)</span>enhancer.<span style="color: rgb(0, 102, 0);">create</span><span style="color: rgb(102, 204, 102);">(</span><span style="color: rgb(102, 204, 102);">)</span>;<br> <br> my.<span style="color: rgb(0, 102, 0);">method</span><span style="color: rgb(102, 204, 102);">(</span><span style="color: rgb(102, 204, 102);">)</span>;<br> <span style="color: rgb(102, 204, 102);">}</span><br> <br> <span style="color: rgb(0, 0, 0); font-weight: bold;">private</span> <span style="color: rgb(0, 0, 0); font-weight: bold;">static</span> <span style="color: rgb(0, 0, 0); font-weight: bold;">class</span> MethodInterceptorImpl <span style="color: rgb(0, 0, 0); font-weight: bold;">implements</span> MethodInterceptor <span style="color: rgb(102, 204, 102);">{</span><br> <br> <span style="color: rgb(0, 0, 0); font-weight: bold;">public</span> <a href="http://www.google.com/search?hl=en&q=allinurl%3AObject+java.sun.com&bntI=I%27m%20Feeling%20Lucky"><span style="color: rgb(170, 170, 221); font-weight: bold;">Object</span></a> intercept<span style="color: rgb(102, 204, 102);">(</span><a href="http://www.google.com/search?hl=en&q=allinurl%3AObject+java.sun.com&bntI=I%27m%20Feeling%20Lucky"><span style="color: rgb(170, 170, 221); font-weight: bold;">Object</span></a> obj, <br> <a href="http://www.google.com/search?hl=en&q=allinurl%3AMethod+java.sun.com&bntI=I%27m%20Feeling%20Lucky"><span style="color: rgb(170, 170, 221); font-weight: bold;">Method</span></a> method, <br> <a href="http://www.google.com/search?hl=en&q=allinurl%3AObject+java.sun.com&bntI=I%27m%20Feeling%20Lucky"><span style="color: rgb(170, 170, 221); font-weight: bold;">Object</span></a><span style="color: rgb(102, 204, 102);">[</span><span style="color: rgb(102, 204, 102);">]</span> args, <br> MethodProxy proxy<span style="color: rgb(102, 204, 102);">)</span> <span style="color: rgb(0, 0, 0); font-weight: bold;">throws</span> <a href="http://www.google.com/search?hl=en&q=allinurl%3AThrowable+java.sun.com&bntI=I%27m%20Feeling%20Lucky"><span style="color: rgb(170, 170, 221); font-weight: bold;">Throwable</span></a> <span style="color: rgb(102, 204, 102);">{</span><br> <br> <a href="http://www.google.com/search?hl=en&q=allinurl%3ASystem+java.sun.com&bntI=I%27m%20Feeling%20Lucky"><span style="color: rgb(170, 170, 221); font-weight: bold;">System</span></a>.<span style="color: rgb(0, 102, 0);">out</span>.<span style="color: rgb(0, 102, 0);">println</span><span style="color: rgb(102, 204, 102);">(</span>method<span style="color: rgb(102, 204, 102);">)</span>;<br> <br> proxy.<span style="color: rgb(0, 102, 0);">invokeSuper</span><span style="color: rgb(102, 204, 102);">(</span>obj, args<span style="color: rgb(102, 204, 102);">)</span>;<br> <br> <span style="color: rgb(0, 0, 0); font-weight: bold;">return</span> <span style="color: rgb(0, 0, 0); font-weight: bold;">null</span>;<br> <span style="color: rgb(102, 204, 102);">}</span><br> <span style="color: rgb(102, 204, 102);">}</span><br><span style="color: rgb(102, 204, 102);">}</span>
执行结果:
- <span style="color: rgb(0, 0, 0); font-weight: bold;">public</span> <span style="color: rgb(153, 51, 51);">void</span> cglib_test.<span style="color: rgb(0, 102, 0);">MyClass</span>.<span style="color: rgb(0, 102, 0);">method</span><span style="color: rgb(102, 204, 102);">(</span><span style="color: rgb(102, 204, 102);">)</span><br>MyClass.<span style="color: rgb(0, 102, 0);">method</span><span style="color: rgb(102, 204, 102);">(</span><span style="color: rgb(102, 204, 102);">)</span>
使用CallbackFilter
- <span style="color: rgb(0, 0, 0); font-weight: bold;">public</span> <span style="color: rgb(0, 0, 0); font-weight: bold;">class</span> MyClass <span style="color: rgb(102, 204, 102);">{</span><br> <br> <span style="color: rgb(0, 0, 0); font-weight: bold;">public</span> <span style="color: rgb(153, 51, 51);">void</span> method<span style="color: rgb(102, 204, 102);">(</span><span style="color: rgb(102, 204, 102);">)</span> <span style="color: rgb(102, 204, 102);">{</span><br> <a href="http://www.google.com/search?hl=en&q=allinurl%3ASystem+java.sun.com&bntI=I%27m%20Feeling%20Lucky"><span style="color: rgb(170, 170, 221); font-weight: bold;">System</span></a>.<span style="color: rgb(0, 102, 0);">out</span>.<span style="color: rgb(0, 102, 0);">println</span><span style="color: rgb(102, 204, 102);">(</span><span style="color: rgb(255, 0, 0);">"MyClass.method()"</span><span style="color: rgb(102, 204, 102);">)</span>;<br> <span style="color: rgb(102, 204, 102);">}</span><br> <br> <span style="color: rgb(0, 0, 0); font-weight: bold;">public</span> <span style="color: rgb(153, 51, 51);">void</span> method2<span style="color: rgb(102, 204, 102);">(</span><span style="color: rgb(102, 204, 102);">)</span> <span style="color: rgb(102, 204, 102);">{</span><br> <a href="http://www.google.com/search?hl=en&q=allinurl%3ASystem+java.sun.com&bntI=I%27m%20Feeling%20Lucky"><span style="color: rgb(170, 170, 221); font-weight: bold;">System</span></a>.<span style="color: rgb(0, 102, 0);">out</span>.<span style="color: rgb(0, 102, 0);">println</span><span style="color: rgb(102, 204, 102);">(</span><span style="color: rgb(255, 0, 0);">"MyClass.method2()"</span><span style="color: rgb(102, 204, 102);">)</span>;<br> <span style="color: rgb(102, 204, 102);">}</span><br><span style="color: rgb(102, 204, 102);">}</span>
- <span style="color: rgb(161, 161, 0);">import java.lang.reflect.Method;</span><br> <br><span style="color: rgb(161, 161, 0);">import net.sf.cglib.proxy.Enhancer;</span><br><span style="color: rgb(161, 161, 0);">import net.sf.cglib.proxy.MethodProxy;</span><br><span style="color: rgb(161, 161, 0);">import net.sf.cglib.proxy.MethodInterceptor;</span><br><span style="color: rgb(161, 161, 0);">import net.sf.cglib.proxy.NoOp;</span><br><span style="color: rgb(161, 161, 0);">import net.sf.cglib.proxy.Callback;</span><br><span style="color: rgb(161, 161, 0);">import net.sf.cglib.proxy.CallbackFilter;</span><br> <br> <br><span style="color: rgb(0, 0, 0); font-weight: bold;">public</span> <span style="color: rgb(0, 0, 0); font-weight: bold;">class</span> Main <span style="color: rgb(102, 204, 102);">{</span><br> <br> <span style="color: rgb(0, 0, 0); font-weight: bold;">public</span> <span style="color: rgb(0, 0, 0); font-weight: bold;">static</span> <span style="color: rgb(153, 51, 51);">void</span> main<span style="color: rgb(102, 204, 102);">(</span><a href="http://www.google.com/search?hl=en&q=allinurl%3AString+java.sun.com&bntI=I%27m%20Feeling%20Lucky"><span style="color: rgb(170, 170, 221); font-weight: bold;">String</span></a><span style="color: rgb(102, 204, 102);">[</span><span style="color: rgb(102, 204, 102);">]</span> args<span style="color: rgb(102, 204, 102);">)</span> <span style="color: rgb(102, 204, 102);">{</span><br> <br> Callback<span style="color: rgb(102, 204, 102);">[</span><span style="color: rgb(102, 204, 102);">]</span> callbacks =<br> <span style="color: rgb(0, 0, 0); font-weight: bold;">new</span> Callback<span style="color: rgb(102, 204, 102);">[</span><span style="color: rgb(102, 204, 102);">]</span> <span style="color: rgb(102, 204, 102);">{</span> <span style="color: rgb(0, 0, 0); font-weight: bold;">new</span> MethodInterceptorImpl<span style="color: rgb(102, 204, 102);">(</span><span style="color: rgb(102, 204, 102);">)</span>, NoOp.<span style="color: rgb(0, 102, 0);">INSTANCE</span> <span style="color: rgb(102, 204, 102);">}</span>;<br> <br> Enhancer enhancer = <span style="color: rgb(0, 0, 0); font-weight: bold;">new</span> Enhancer<span style="color: rgb(102, 204, 102);">(</span><span style="color: rgb(102, 204, 102);">)</span>;<br> <br> enhancer.<span style="color: rgb(0, 102, 0);">setSuperclass</span><span style="color: rgb(102, 204, 102);">(</span>MyClass.<span style="color: rgb(0, 0, 0); font-weight: bold;">class</span><span style="color: rgb(102, 204, 102);">)</span>;<br> enhancer.<span style="color: rgb(0, 102, 0);">setCallbacks</span><span style="color: rgb(102, 204, 102);">(</span> callbacks <span style="color: rgb(102, 204, 102);">)</span>;<br> enhancer.<span style="color: rgb(0, 102, 0);">setCallbackFilter</span><span style="color: rgb(102, 204, 102);">(</span> <span style="color: rgb(0, 0, 0); font-weight: bold;">new</span> CallbackFilterImpl<span style="color: rgb(102, 204, 102);">(</span><span style="color: rgb(102, 204, 102);">)</span> <span style="color: rgb(102, 204, 102);">)</span>;<br> <br> <br> MyClass my = <span style="color: rgb(102, 204, 102);">(</span>MyClass<span style="color: rgb(102, 204, 102);">)</span>enhancer.<span style="color: rgb(0, 102, 0);">create</span><span style="color: rgb(102, 204, 102);">(</span><span style="color: rgb(102, 204, 102);">)</span>;<br> <br> my.<span style="color: rgb(0, 102, 0);">method</span><span style="color: rgb(102, 204, 102);">(</span><span style="color: rgb(102, 204, 102);">)</span>;<br> my.<span style="color: rgb(0, 102, 0);">method2</span><span style="color: rgb(102, 204, 102);">(</span><span style="color: rgb(102, 204, 102);">)</span>;<br> <span style="color: rgb(102, 204, 102);">}</span><br> <br> <span style="color: rgb(0, 0, 0); font-weight: bold;">private</span> <span style="color: rgb(0, 0, 0); font-weight: bold;">static</span> <span style="color: rgb(0, 0, 0); font-weight: bold;">class</span> CallbackFilterImpl <span style="color: rgb(0, 0, 0); font-weight: bold;">implements</span> CallbackFilter <span style="color: rgb(102, 204, 102);">{</span><br> <br> <span style="color: rgb(0, 0, 0); font-weight: bold;">public</span> <span style="color: rgb(153, 51, 51);">int</span> accept<span style="color: rgb(102, 204, 102);">(</span><a href="http://www.google.com/search?hl=en&q=allinurl%3AMethod+java.sun.com&bntI=I%27m%20Feeling%20Lucky"><span style="color: rgb(170, 170, 221); font-weight: bold;">Method</span></a> method<span style="color: rgb(102, 204, 102);">)</span> <span style="color: rgb(102, 204, 102);">{</span><br> <br> <span style="color: rgb(177, 177, 0);">if</span> <span style="color: rgb(102, 204, 102);">(</span> method.<span style="color: rgb(0, 102, 0);">getName</span><span style="color: rgb(102, 204, 102);">(</span><span style="color: rgb(102, 204, 102);">)</span>.<span style="color: rgb(0, 102, 0);">equals</span><span style="color: rgb(102, 204, 102);">(</span><span style="color: rgb(255, 0, 0);">"method2"</span><span style="color: rgb(102, 204, 102);">)</span> <span style="color: rgb(102, 204, 102);">)</span> <span style="color: rgb(102, 204, 102);">{</span><br> <span style="color: rgb(0, 0, 0); font-weight: bold;">return</span> <span style="color: rgb(204, 102, 204);">1</span>;<br> <br> <span style="color: rgb(102, 204, 102);">}</span> <span style="color: rgb(177, 177, 0);">else</span> <span style="color: rgb(102, 204, 102);">{</span><br> <span style="color: rgb(0, 0, 0); font-weight: bold;">return</span> <span style="color: rgb(204, 102, 204);">0</span>;<br> <span style="color: rgb(102, 204, 102);">}</span><br> <span style="color: rgb(102, 204, 102);">}</span><br> <span style="color: rgb(102, 204, 102);">}</span><br> <br> <span style="color: rgb(0, 0, 0); font-weight: bold;">private</span> <span style="color: rgb(0, 0, 0); font-weight: bold;">static</span> <span style="color: rgb(0, 0, 0); font-weight: bold;">class</span> MethodInterceptorImpl <span style="color: rgb(0, 0, 0); font-weight: bold;">implements</span> MethodInterceptor <span style="color: rgb(102, 204, 102);">{</span><br> <br> <span style="color: rgb(0, 0, 0); font-weight: bold;">public</span> <a href="http://www.google.com/search?hl=en&q=allinurl%3AObject+java.sun.com&bntI=I%27m%20Feeling%20Lucky"><span style="color: rgb(170, 170, 221); font-weight: bold;">Object</span></a> intercept<span style="color: rgb(102, 204, 102);">(</span><a href="http://www.google.com/search?hl=en&q=allinurl%3AObject+java.sun.com&bntI=I%27m%20Feeling%20Lucky"><span style="color: rgb(170, 170, 221); font-weight: bold;">Object</span></a> obj, <br> <a href="http://www.google.com/search?hl=en&q=allinurl%3AMethod+java.sun.com&bntI=I%27m%20Feeling%20Lucky"><span style="color: rgb(170, 170, 221); font-weight: bold;">Method</span></a> method, <br> <a href="http://www.google.com/search?hl=en&q=allinurl%3AObject+java.sun.com&bntI=I%27m%20Feeling%20Lucky"><span style="color: rgb(170, 170, 221); font-weight: bold;">Object</span></a><span style="color: rgb(102, 204, 102);">[</span><span style="color: rgb(102, 204, 102);">]</span> args, <br> MethodProxy proxy<span style="color: rgb(102, 204, 102);">)</span> <span style="color: rgb(0, 0, 0); font-weight: bold;">throws</span> <a href="http://www.google.com/search?hl=en&q=allinurl%3AThrowable+java.sun.com&bntI=I%27m%20Feeling%20Lucky"><span style="color: rgb(170, 170, 221); font-weight: bold;">Throwable</span></a> <span style="color: rgb(102, 204, 102);">{</span><br> <br> <a href="http://www.google.com/search?hl=en&q=allinurl%3ASystem+java.sun.com&bntI=I%27m%20Feeling%20Lucky"><span style="color: rgb(170, 170, 221); font-weight: bold;">System</span></a>.<span style="color: rgb(0, 102, 0);">out</span>.<span style="color: rgb(0, 102, 0);">println</span><span style="color: rgb(102, 204, 102);">(</span>method<span style="color: rgb(102, 204, 102);">)</span>;<br> <br> <span style="color: rgb(0, 0, 0); font-weight: bold;">return</span> proxy.<span style="color: rgb(0, 102, 0);">invokeSuper</span><span style="color: rgb(102, 204, 102);">(</span>obj, args<span style="color: rgb(102, 204, 102);">)</span>;<br> <span style="color: rgb(102, 204, 102);">}</span><br> <span style="color: rgb(102, 204, 102);">}</span><br><span style="color: rgb(102, 204, 102);">}</span>
执行结果:
- <span style="color: rgb(0, 0, 0); font-weight: bold;">public</span> <span style="color: rgb(153, 51, 51);">void</span> cglib_test.<span style="color: rgb(0, 102, 0);">MyClass</span>.<span style="color: rgb(0, 102, 0);">method</span><span style="color: rgb(102, 204, 102);">(</span><span style="color: rgb(102, 204, 102);">)</span><br>MyClass.<span style="color: rgb(0, 102, 0);">method</span><span style="color: rgb(102, 204, 102);">(</span><span style="color: rgb(102, 204, 102);">)</span><br>MyClass.<span style="color: rgb(0, 102, 0);">method2</span><span style="color: rgb(102, 204, 102);">(</span><span style="color: rgb(102, 204, 102);">)</span>
使用Mixin
- <span style="color: rgb(0, 0, 0); font-weight: bold;">public</span> <span style="color: rgb(0, 0, 0); font-weight: bold;">interface</span> MyInterfaceA <span style="color: rgb(102, 204, 102);">{</span><br> <br> <span style="color: rgb(0, 0, 0); font-weight: bold;">public</span> <span style="color: rgb(153, 51, 51);">void</span> methodA<span style="color: rgb(102, 204, 102);">(</span><span style="color: rgb(102, 204, 102);">)</span>;<br><span style="color: rgb(102, 204, 102);">}</span><br> <br><span style="color: rgb(0, 0, 0); font-weight: bold;">public</span> <span style="color: rgb(0, 0, 0); font-weight: bold;">interface</span> MyInterfaceB <span style="color: rgb(102, 204, 102);">{</span><br> <span style="color: rgb(0, 0, 0); font-weight: bold;">public</span> <span style="color: rgb(153, 51, 51);">void</span> methodB<span style="color: rgb(102, 204, 102);">(</span><span style="color: rgb(102, 204, 102);">)</span>;<br><span style="color: rgb(102, 204, 102);">}</span><br> <br><span style="color: rgb(0, 0, 0); font-weight: bold;">public</span> <span style="color: rgb(0, 0, 0); font-weight: bold;">class</span> MyInterfaceAImpl <span style="color: rgb(0, 0, 0); font-weight: bold;">implements</span> MyInterfaceA <span style="color: rgb(102, 204, 102);">{</span><br> <br> <span style="color: rgb(0, 0, 0); font-weight: bold;">public</span> <span style="color: rgb(153, 51, 51);">void</span> methodA<span style="color: rgb(102, 204, 102);">(</span><span style="color: rgb(102, 204, 102);">)</span> <span style="color: rgb(102, 204, 102);">{</span><br> <a href="http://www.google.com/search?hl=en&q=allinurl%3ASystem+java.sun.com&bntI=I%27m%20Feeling%20Lucky"><span style="color: rgb(170, 170, 221); font-weight: bold;">System</span></a>.<span style="color: rgb(0, 102, 0);">out</span>.<span style="color: rgb(0, 102, 0);">println</span><span style="color: rgb(102, 204, 102);">(</span><span style="color: rgb(255, 0, 0);">"MyInterfaceAImpl.methodA()"</span><span style="color: rgb(102, 204, 102);">)</span>;<br> <span style="color: rgb(102, 204, 102);">}</span><br><span style="color: rgb(102, 204, 102);">}</span><br> <br><span style="color: rgb(0, 0, 0); font-weight: bold;">public</span> <span style="color: rgb(0, 0, 0); font-weight: bold;">class</span> MyInterfaceBImpl <span style="color: rgb(0, 0, 0); font-weight: bold;">implements</span> MyInterfaceB <span style="color: rgb(102, 204, 102);">{</span><br> <br> <span style="color: rgb(0, 0, 0); font-weight: bold;">public</span> <span style="color: rgb(153, 51, 51);">void</span> methodB<span style="color: rgb(102, 204, 102);">(</span><span style="color: rgb(102, 204, 102);">)</span> <span style="color: rgb(102, 204, 102);">{</span><br> <a href="http://www.google.com/search?hl=en&q=allinurl%3ASystem+java.sun.com&bntI=I%27m%20Feeling%20Lucky"><span style="color: rgb(170, 170, 221); font-weight: bold;">System</span></a>.<span style="color: rgb(0, 102, 0);">out</span>.<span style="color: rgb(0, 102, 0);">println</span><span style="color: rgb(102, 204, 102);">(</span><span style="color: rgb(255, 0, 0);">"MyInterfaceBImpl.methodB()"</span><span style="color: rgb(102, 204, 102);">)</span>;<br> <span style="color: rgb(102, 204, 102);">}</span><br><span style="color: rgb(102, 204, 102);">}</span>
- <span style="color: rgb(161, 161, 0);">import net.sf.cglib.proxy.Mixin;</span><br> <br><span style="color: rgb(0, 0, 0); font-weight: bold;">public</span> <span style="color: rgb(0, 0, 0); font-weight: bold;">class</span> Main <span style="color: rgb(102, 204, 102);">{</span><br> <br> <span style="color: rgb(0, 0, 0); font-weight: bold;">public</span> <span style="color: rgb(0, 0, 0); font-weight: bold;">static</span> <span style="color: rgb(153, 51, 51);">void</span> main<span style="color: rgb(102, 204, 102);">(</span><a href="http://www.google.com/search?hl=en&q=allinurl%3AString+java.sun.com&bntI=I%27m%20Feeling%20Lucky"><span style="color: rgb(170, 170, 221); font-weight: bold;">String</span></a><span style="color: rgb(102, 204, 102);">[</span><span style="color: rgb(102, 204, 102);">]</span> args<span style="color: rgb(102, 204, 102);">)</span> <span style="color: rgb(102, 204, 102);">{</span><br> <br> <span style="color: rgb(0, 0, 0); font-weight: bold;">Class</span><span style="color: rgb(102, 204, 102);">[</span><span style="color: rgb(102, 204, 102);">]</span> interfaces =<br> <span style="color: rgb(0, 0, 0); font-weight: bold;">new</span> <span style="color: rgb(0, 0, 0); font-weight: bold;">Class</span><span style="color: rgb(102, 204, 102);">[</span><span style="color: rgb(102, 204, 102);">]</span> <span style="color: rgb(102, 204, 102);">{</span> MyInterfaceA.<span style="color: rgb(0, 0, 0); font-weight: bold;">class</span>, MyInterfaceB.<span style="color: rgb(0, 0, 0); font-weight: bold;">class</span> <span style="color: rgb(102, 204, 102);">}</span>;<br> <br> <a href="http://www.google.com/search?hl=en&q=allinurl%3AObject+java.sun.com&bntI=I%27m%20Feeling%20Lucky"><span style="color: rgb(170, 170, 221); font-weight: bold;">Object</span></a><span style="color: rgb(102, 204, 102);">[</span><span style="color: rgb(102, 204, 102);">]</span> delegates =<br> <span style="color: rgb(0, 0, 0); font-weight: bold;">new</span> <a href="http://www.google.com/search?hl=en&q=allinurl%3AObject+java.sun.com&bntI=I%27m%20Feeling%20Lucky"><span style="color: rgb(170, 170, 221); font-weight: bold;">Object</span></a><span style="color: rgb(102, 204, 102);">[</span><span style="color: rgb(102, 204, 102);">]</span> <span style="color: rgb(102, 204, 102);">{</span> <span style="color: rgb(0, 0, 0); font-weight: bold;">new</span> MyInterfaceAImpl<span style="color: rgb(102, 204, 102);">(</span><span style="color: rgb(102, 204, 102);">)</span>, <span style="color: rgb(0, 0, 0); font-weight: bold;">new</span> MyInterfaceBImpl<span style="color: rgb(102, 204, 102);">(</span><span style="color: rgb(102, 204, 102);">)</span> <span style="color: rgb(102, 204, 102);">}</span>;<br> <br> <br> <a href="http://www.google.com/search?hl=en&q=allinurl%3AObject+java.sun.com&bntI=I%27m%20Feeling%20Lucky"><span style="color: rgb(170, 170, 221); font-weight: bold;">Object</span></a> obj = Mixin.<span style="color: rgb(0, 102, 0);">create</span><span style="color: rgb(102, 204, 102);">(</span>interfaces, delegates<span style="color: rgb(102, 204, 102);">)</span>;<br> <br> <br> MyInterfaceA myA = <span style="color: rgb(102, 204, 102);">(</span>MyInterfaceA<span style="color: rgb(102, 204, 102);">)</span>obj;<br> myA.<span style="color: rgb(0, 102, 0);">methodA</span><span style="color: rgb(102, 204, 102);">(</span><span style="color: rgb(102, 204, 102);">)</span>;<br> <br> <br> MyInterfaceB myB = <span style="color: rgb(102, 204, 102);">(</span>MyInterfaceB<span style="color: rgb(102, 204, 102);">)</span>obj;<br> myB.<span style="color: rgb(0, 102, 0);">methodB</span><span style="color: rgb(102, 204, 102);">(</span><span style="color: rgb(102, 204, 102);">)</span>;<br> <span style="color: rgb(102, 204, 102);">}</span><br><span style="color: rgb(102, 204, 102);">}</span>
执行结果:
- MyInterfaceAImpl.<span style="color: rgb(0, 102, 0);">methodA</span><span style="color: rgb(102, 204, 102);">(</span><span style="color: rgb(102, 204, 102);">)</span><br>MyInterfaceBImpl.<span style="color: rgb(0, 102, 0);">methodB</span><span style="color: rgb(102, 204, 102);">(</span><span style="color: rgb(102, 204, 102);">)</span>
|