CGLIB使用入门

1. Enhancer和MethodInterceptor
Enhancer可以用来动态的生成一个类,这个类可以继承指定的一个类,实现指定的一些接口。
同时,Enhancer在生成一个类之前需要指定一个Callback,当类方法调用时,方法的执行被分配给这个Callback
MethodInterceptor是一个使用比较多的继承自Callback的接口,它只有一个方法声明
Java代码  
  1. public interface MethodInterceptor extends Callback { 
  2.   public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args,MethodProxy proxy) throws Throwable;  
  3. }  
  4.  
我们看一下 JDK自带的Invocationhandler接口中的方法声明
Java代码   收藏代码
  1. public interface InvocationHandler {  
  2.      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;  
  3. }  
  4.  
 从参数构成上,methodInterceptor的输入参数比Invocationhandler多1个,其实前3个参数对象的含义与Invocationhandler的含义是相同的
第一个参数表示调用方法来自哪个对象;
第二个参数表示调用方法的Method对象;
第三个参数表示此次调用的输入参数列表;
多出来的参数是MethodProxy 类型的,它应该是cglib生成用来代替Method对象的一个对象,使用MethodProxy比调用JDK自身的Method直接执行方法效率会有提升


代码示例:
Java代码   收藏代码
  1. import java.lang.reflect.Method;  
  2.   
  3. import net.sf.cglib.proxy.Enhancer;  
  4. import net.sf.cglib.proxy.MethodInterceptor;  
  5. import net.sf.cglib.proxy.MethodProxy;  
  6.   
  7.   
  8. public class MyMethodInterceptor implements MethodInterceptor {  
  9.      
  10.     // 接口1  
  11.     static interface Inter1{  
  12.         public void fun1();  
  13.     }  
  14.     // 接口2  
  15.     static interface Inter2{  
  16.         public String fun2(String arg0);  
  17.     }  
  18.      
  19.     // 内部方法  
  20.     public String myFun1(String arg0){  
  21.         return "hello," + arg0 ;  
  22.     }  
  23.      
  24.     public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {  
  25.         String methodName = method.getName();  
  26.          
  27.         if"fun1" .equals(methodName) ){  
  28.             System. out .println( "[intercept] fun1 invoked" );  
  29.             return null;  
  30.         } else if ( "fun2" .equals(methodName) ){  
  31.             System. out .println( "[intercept] fun2 invoked before" );  
  32.             String result = (String)args[0] + "..." ;  
  33.             System. out .println( result );  
  34.             System. out .println( "[intercept] fun2 invoked after" );  
  35.             return result;  
  36.         } else if ( "myFun1" .equals(methodName) ){  
  37.             System. out .println( "[intercept] myFun1 invoked before" );  
  38.             Object result = proxy. invokeSuper(obj, args);  
  39.             System. out .println( result );  
  40.             System. out .println( "[intercept] myFun1 invoked after" );  
  41.             return result;  
  42.         }  
  43.              
  44.         return null;  
  45.     }  
  46.      
  47.     public Object createProxy(){  
  48.         Enhancer enhancer = new Enhancer();  
  49.         enhancer.setSuperclass(MyMethodInterceptor. class );  
  50.         enhancer.setInterfaces( new Class[]{Inter1. class,Inter2. class});  
  51.         enhancer.setCallback( this );  
  52.         return enhancer.create();  
  53.     }  
  54.      
  55.      
  56.     public static void main(String[] args) {  
  57.         MyMethodInterceptor ss = new MyMethodInterceptor();  
  58.         Object proxy = ss.createProxy();  
  59.          
  60.         // 接口  
  61.         Inter1 inter1 = (Inter1)proxy;  
  62.         inter1.fun1();  
  63.          
  64.         Inter2 inter2 = (Inter2)proxy;  
  65.         inter2.fun2( "code generate library" );  
  66.          
  67.         // 类  
  68.         MyMethodInterceptor c1 = (MyMethodInterceptor)proxy;  
  69.         c1.myFun1( "cglib" );  
  70.          
  71.     }  
  72.   
  73. }  
  74.  
 执行结果:
[intercept] fun1 invoked
[intercept] fun2 invoked before
code generate library...
[intercept] fun2 invoked after
[intercept] myFun1 invoked before
hello,cglib
[intercept] myFun1 invoked after
我们看到,在intercept()方法中,对调用函数名进行了判断,并进行了不同处理。可以再方法执行之前、之后做一些我们想做的事情,甚至是修改输入参数、输出参数。
MethodProxy在对执行函数的时候,提供了2个方法
Java代码   收藏代码
  1. public Object invoke (Object obj, Object[] args) throws Throwable  
  2. public Object invokeSuper(Object obj, Object[] args) throws Throwable  
  我们看到,在例子中使用的是invokeSuper()方法,因为动态生成的类是子类或者是实现类,因此invokeSuper就是执行父类中方法的意思。
那么invoke()方法是做什么的。javadoc上说这个方法可以用于 相同类中的其他对象的方法执行,也就是说这个方法中的obj需要传入相同一个类的另一个对象,否则会进入无限递归循环。
通过这个简单的例子,我们可以看到cglib可以动态的生成一个代理,而且这种方法比JDK的动态代理更强大,因为JDK的动态代理,需要代理的类实现某个接口,而cglib没有这个要求,因为它可以直接生成指定类的子类,同时支持实现接口的方式。cglib提供的MethodProxy的执行效率高于JDK自带的反射。

2. CallbackFilter
一个Enhancer生成类可以指定多个Callback,这样对于每次调用有哪个Callback,就需要指定一个CallbackFilter的策略
Java代码   收藏代码
  1. import java.lang.reflect.Method;  
  2. import net.sf.cglib.proxy.Callback;  
  3. import net.sf.cglib.proxy.CallbackFilter;  
  4. import net.sf.cglib.proxy.Enhancer;  
  5. import net.sf.cglib.proxy.MethodInterceptor;  
  6. import net.sf.cglib.proxy.MethodProxy;  
  7.   
  8. public class CallbackTest {  
  9.      
  10.     public void fun1(){  
  11.         System. out .println( "fun1 invoekd" );  
  12.     }  
  13.      
  14.     public void fun2(){  
  15.         System. out .println( "fun2 invoekd" );  
  16.     }  
  17.      
  18.     static class ClassA implements MethodInterceptor{  
  19.         public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {  
  20.             System. out .println( "ClassA intercept invoked..." );  
  21.             return proxy.invokeSuper(obj, args);  
  22.         }  
  23.     }  
  24.      
  25.     static class ClassB implements MethodInterceptor{  
  26.         public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {  
  27.             System. out .println( "ClassB intercept invoked..." );  
  28.             return proxy.invokeSuper(obj, args);  
  29.         }  
  30.     }  
  31.      
  32.     public Object createProxy(){  
  33.         Enhancer enhancer = new Enhancer();  
  34.         enhancer.setSuperclass(getClass());  
  35.         enhancer.setCallbacks( new Callback[]{ new ClassA(), new ClassB() });  
  36.         enhancer.setCallbackFilter( new CallbackFilter() {  
  37.              
  38.             public int accept(Method method) {  
  39.                 String methodName = method.getName();  
  40.                 if"fun1" .equals(methodName) ){  
  41.                     return 0;  
  42.                 } else {  
  43.                     return 1;  
  44.                 }  
  45.             }  
  46.         });  
  47.         return enhancer.create();  
  48.     }  
  49.      
  50.     public static void main(String[] args) {  
  51.         CallbackTest test = new CallbackTest();  
  52.          
  53.         CallbackTest obj = (CallbackTest)test.createProxy();  
  54.          
  55.         obj.fun1();  
  56.         obj.fun2();  
  57.          
  58.     }  
  59.   
  60. }  
  61.   
 输出结果:
ClassA intercept invoked...
fun1 invoekd
ClassB intercept invoked...
fun2 invoekd
 我们可以看到,CallbackFilter类的accept()方法的返回值是int类型的,它用来指示此次指派的Callback的次序,从0开始,注意这个返回值必须小于当前指定的Callback的总个数
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值