AOP的另一种实现----cglib   
               添加时间:2013-5-22 点击量: 
 
                大师都知道,可以或许实现AOP,然则它有一个毛病,就是所有被的对象必须实现一个接口,不然就会报异常。那么若是被对象没有实现接口那该如何实现AOP呢?当然是能的,应用CGlib就可以实现。
  1、什么是CGlib
  CGlib是一个强大的,高机能,高质量的Code生成类库。它可以在运行期扩大Java类与实现Java接口。 然这些实际的功能是asm所供给的,asm又是什么?Java字节码操控框架,具体是什么大师可以上彀查一查,毕竟?成果我们这里所要评论辩论的是cglib, cglib就是封装了asm,简化了asm的操纵,实现了在运行期动态生成新的class。 可能大师还感触感染不到它的强大,如今就告诉你。 实际上CGlib为spring aop供给了底层的一种实现;为hibernate应用cglib动态生成VO/PO (接口层对象)。
  它的道理就是用Enhancer生成一个原有类的子类,并且设置好callback , 则原有类的每个办法调用都邑转成调用实现了MethodInterceptor接口的proxy的intercept() 函数: 
public Object intercept(Object o,Method method,Object[] args,MethodProxy proxy) 
  在intercept()函数里,你可以在履行Object result=proxy.invokeSuper(o,args);来履行原有函数,在履行前后参加本身的器材,改变它的参数,也可以瞒天过海,完全干此外。说白了,就是AOP中的around advice。
  2、如何应用CGlib
  举个例子:比如DAO层有对表的增、删、改、查操纵,若是要对原有的DAO层的增、删、改、查增长权限把握的话,批改代码是很是疾苦的。所以可以用AOP来实现。然则DAO层没有应用接口,不成用。这时辰CGlib是个很好的选择。
TableDao.java:
 1 package com.cglib;
 2 
 3 public class TableDao {
 4     public void create(){
 5         System.out.println(create() is running...);
 6     }
 7     public void (){
 8         System.out.println(() is running...);
 9     }
10     public void (){
11         System.out.println(() is running...);
12     }
13     public void query(){
14         System.out.println(query() is running...);
15     }
16 }
实现了MethodInterceptor接口的AuthProxy.java:用来对办法进行阻碍,增长办法接见的权限把握,这里只容许张三接见。
 1 package com.cglib;
 2 
 3 import java.lang.reflect.Method;
 4 
 5 import net.sf.cglib.proxy.MethodInterceptor;
 6 import net.sf.cglib.proxy.MethodProxy;
 7 //办法阻碍器
 8 public class AuthProxy implements MethodInterceptor {
 9     private String userName;
10     AuthProxy(String userName){
11         this.userName = userName;
12     }
13     //用来加强原有办法
14     public Object intercept(Object arg0, Method arg1, Object[] arg2,
15             MethodProxy arg3) throws Throwable {
16         //权限断定
17         if(!张三.equals(userName)){
18             System.out.println(你没有权限!);
19             return null;
20         }
21         return arg3.invokeSuper(arg0, arg2);
22     }
23 }
TableDAOFactory.java:用来创建TableDao的子类的工厂类
 1 package com.cglib;
 2 
 3 import net.sf.cglib.proxy.Callback;
 4 import net.sf.cglib.proxy.Enhancer;
 5 import net.sf.cglib.proxy.NoOp;
 6 
 7 public class TableDAOFactory {
 8     private static TableDao tDao = new TableDao();  
 9     public static TableDao getInstance(){  
10         return tDao;  
11     }  
12     public static TableDao getAuthInstance(AuthProxy authProxy){  
13         Enhancer en = new Enhancer();  //Enhancer用来生成一个原有类的子类
14         //进行  
15         en.setSuperclass(TableDao.class); 
16         //设置织入逻辑
17         en.setCallback(authProxy);  
18         //生成实例  
19         return (TableDao)en.create();  
20     } 
21  }
测试类Client.java:
 1 package com.cglib;
 2 
 3 public class Client {
 4 
 5     public static void main(String[] args) {  
 6 //        haveAuth(); 
 7         haveNoAuth();
 8     }  
 9     public static void doMethod(TableDao dao){  
10         dao.create();  
11         dao.query();  
12         dao.();  
13         dao.();  
14     }  
15     //模仿有权限
16     public static void haveAuth(){  
17         TableDao tDao = TableDAOFactory.getAuthInstance(new AuthProxy(张三));  
18         doMethod(tDao);  
19     }  
20     //模仿无权限
21     public static void haveNoAuth(){  
22         TableDao tDao = TableDAOFactory.getAuthInstance(new AuthProxy(李四));  
23         doMethod(tDao);  
24     }
25 }
  如许就可以或许对DAO层的办法进行权限把握了。然则若是又改需求了,要把DAO层的query办法让所有效户都可以接见,而其他办法照样有权限把握,该如何实现呢?这可难不倒我们了,因为我们应用了CGlib。当然最简单的体式格式是去批改我们的办法阻碍器,不过如许会使逻辑变得错杂,且晦气于保护。还好CGlib给我们供给了办法过滤器(CallbackFilter),CallbackFilte可以明白注解,被的类中不合的办法, 被哪个阻碍器所阻碍。下面我们就来做个过滤器用来过滤query办法。 
AuthProxyFilter.java:
 1 package com.cglib;
 2 
 3 import java.lang.reflect.Method;
 4 
 5 import net.sf.cglib.proxy.CallbackFilter;
 6 import net.sf.cglib.proxy.NoOp;
 7 
 8 public class AuthProxyFilter implements CallbackFilter {
 9 
10     public int accept(Method arg0) {
11         /
12           若是调用的不是query办法,则要调用authProxy阻碍器去断定权限
13          /
14         if(!query.equalsIgnoreCase(arg0.getName())){
15             return 0; //调用第一个办法阻碍器,即authProxy
16         }
17         /
18           调用第二个办法阻碍器,即NoOp.INSTANCE,NoOp.INSTANCE是指不做任何工作的阻碍器
19           在这里就是任何人都有权限接见query办法,所以调用默认阻碍器不做任何处理惩罚
20          /
21         return 1;  
22     }
23 
24 }
  至于为什么返回0或者1,注释讲的很具体。
在TableDAOFactory.java里添加如下办法:
1 public static TableDao getAuthInstanceByFilter(AuthProxy authProxy){  
2         Enhancer en = new Enhancer();  
3         en.setSuperclass(TableDao.class);  
4         en.setCallbacks(new Callback[]{authProxy,NoOp.INSTANCE});  //设置两个办法阻碍器
5         en.setCallbackFilter(new AuthProxyFilter());  
6         return (TableDao)en.create();  
7     }  
  这里得重视,en.setCallbacks()办法里的数组参数次序就是上方办法的返回值所代表的办法阻碍器,若是return 0则应用authProxy阻碍器,return 1则应用NoOp.INSTANCE阻碍器,NoOp.INSTANCE是默认的办法阻碍器,不做什么处理惩罚。
  下面在测试类中添加如下办法:
1 //模仿权限过滤器
2     public static void haveAuthByFilter(){  
3         TableDao tDao = TableDAOFactory.getAuthInstanceByFilter(new AuthProxy(张三));  
4         doMethod(tDao);  
5         tDao = TableDAOFactory.getAuthInstanceByFilter(new AuthProxy(李四));  
6         doMethod(tDao);  
7     }  
在main办法中调用该办法,法度运行成果如下:
create() is running...
query() is running...
() is running...
() is running...
你没有权限!
query() is running...
你没有权限!
你没有权限!
  如许的话,所有效户都对query办法有接见权限了,而其他办法只容许张三接见。
参考材料:http://llying.iteye.com/blog/220452
  
我们永远不要期待别人的拯救,只有自己才能升华自己。自己已准备好了多少容量,方能吸引对等的人与我们相遇,否则再美好的人出现、再动人的事情降临身边,我们也没有能量去理解与珍惜,终将擦肩而过。—— 姚谦《品味》
                     
                  
     
  
 
    
    
大师都知道,可以或许实现AOP,然则它有一个毛病,就是所有被的对象必须实现一个接口,不然就会报异常。那么若是被对象没有实现接口那该如何实现AOP呢?当然是能的,应用CGlib就可以实现。
1、什么是CGlib
CGlib是一个强大的,高机能,高质量的Code生成类库。它可以在运行期扩大Java类与实现Java接口。 然这些实际的功能是asm所供给的,asm又是什么?Java字节码操控框架,具体是什么大师可以上彀查一查,毕竟?成果我们这里所要评论辩论的是cglib, cglib就是封装了asm,简化了asm的操纵,实现了在运行期动态生成新的class。 可能大师还感触感染不到它的强大,如今就告诉你。 实际上CGlib为spring aop供给了底层的一种实现;为hibernate应用cglib动态生成VO/PO (接口层对象)。
  它的道理就是用Enhancer生成一个原有类的子类,并且设置好callback , 则原有类的每个办法调用都邑转成调用实现了MethodInterceptor接口的proxy的intercept() 函数: 
public Object intercept(Object o,Method method,Object[] args,MethodProxy proxy) 
  在intercept()函数里,你可以在履行Object result=proxy.invokeSuper(o,args);来履行原有函数,在履行前后参加本身的器材,改变它的参数,也可以瞒天过海,完全干此外。说白了,就是AOP中的around advice。
2、如何应用CGlib
举个例子:比如DAO层有对表的增、删、改、查操纵,若是要对原有的DAO层的增、删、改、查增长权限把握的话,批改代码是很是疾苦的。所以可以用AOP来实现。然则DAO层没有应用接口,不成用。这时辰CGlib是个很好的选择。
TableDao.java:
1 package com.cglib;
2
3 public class TableDao {
4 public void create(){
5 System.out.println(create() is running...);
6 }
7 public void (){
8 System.out.println(() is running...);
9 }
10 public void (){
11 System.out.println(() is running...);
12 }
13 public void query(){
14 System.out.println(query() is running...);
15 }
16 }
实现了MethodInterceptor接口的AuthProxy.java:用来对办法进行阻碍,增长办法接见的权限把握,这里只容许张三接见。
1 package com.cglib;
2
3 import java.lang.reflect.Method;
4
5 import net.sf.cglib.proxy.MethodInterceptor;
6 import net.sf.cglib.proxy.MethodProxy;
7 //办法阻碍器
8 public class AuthProxy implements MethodInterceptor {
9 private String userName;
10 AuthProxy(String userName){
11 this.userName = userName;
12 }
13 //用来加强原有办法
14 public Object intercept(Object arg0, Method arg1, Object[] arg2,
15 MethodProxy arg3) throws Throwable {
16 //权限断定
17 if(!张三.equals(userName)){
18 System.out.println(你没有权限!);
19 return null;
20 }
21 return arg3.invokeSuper(arg0, arg2);
22 }
23 }
TableDAOFactory.java:用来创建TableDao的子类的工厂类
1 package com.cglib;
2
3 import net.sf.cglib.proxy.Callback;
4 import net.sf.cglib.proxy.Enhancer;
5 import net.sf.cglib.proxy.NoOp;
6
7 public class TableDAOFactory {
8 private static TableDao tDao = new TableDao();
9 public static TableDao getInstance(){
10 return tDao;
11 }
12 public static TableDao getAuthInstance(AuthProxy authProxy){
13 Enhancer en = new Enhancer(); //Enhancer用来生成一个原有类的子类
14 //进行
15 en.setSuperclass(TableDao.class);
16 //设置织入逻辑
17 en.setCallback(authProxy);
18 //生成实例
19 return (TableDao)en.create();
20 }
21 }
测试类Client.java:
1 package com.cglib;
2
3 public class Client {
4
5 public static void main(String[] args) {
6 // haveAuth();
7 haveNoAuth();
8 }
9 public static void doMethod(TableDao dao){
10 dao.create();
11 dao.query();
12 dao.();
13 dao.();
14 }
15 //模仿有权限
16 public static void haveAuth(){
17 TableDao tDao = TableDAOFactory.getAuthInstance(new AuthProxy(张三));
18 doMethod(tDao);
19 }
20 //模仿无权限
21 public static void haveNoAuth(){
22 TableDao tDao = TableDAOFactory.getAuthInstance(new AuthProxy(李四));
23 doMethod(tDao);
24 }
25 }
如许就可以或许对DAO层的办法进行权限把握了。然则若是又改需求了,要把DAO层的query办法让所有效户都可以接见,而其他办法照样有权限把握,该如何实现呢?这可难不倒我们了,因为我们应用了CGlib。当然最简单的体式格式是去批改我们的办法阻碍器,不过如许会使逻辑变得错杂,且晦气于保护。还好CGlib给我们供给了办法过滤器(CallbackFilter),CallbackFilte可以明白注解,被的类中不合的办法, 被哪个阻碍器所阻碍。下面我们就来做个过滤器用来过滤query办法。
AuthProxyFilter.java:
1 package com.cglib;
2
3 import java.lang.reflect.Method;
4
5 import net.sf.cglib.proxy.CallbackFilter;
6 import net.sf.cglib.proxy.NoOp;
7
8 public class AuthProxyFilter implements CallbackFilter {
9
10 public int accept(Method arg0) {
11 /
12 若是调用的不是query办法,则要调用authProxy阻碍器去断定权限
13 /
14 if(!query.equalsIgnoreCase(arg0.getName())){
15 return 0; //调用第一个办法阻碍器,即authProxy
16 }
17 /
18 调用第二个办法阻碍器,即NoOp.INSTANCE,NoOp.INSTANCE是指不做任何工作的阻碍器
19 在这里就是任何人都有权限接见query办法,所以调用默认阻碍器不做任何处理惩罚
20 /
21 return 1;
22 }
23
24 }
至于为什么返回0或者1,注释讲的很具体。
在TableDAOFactory.java里添加如下办法:
1 public static TableDao getAuthInstanceByFilter(AuthProxy authProxy){
2 Enhancer en = new Enhancer();
3 en.setSuperclass(TableDao.class);
4 en.setCallbacks(new Callback[]{authProxy,NoOp.INSTANCE}); //设置两个办法阻碍器
5 en.setCallbackFilter(new AuthProxyFilter());
6 return (TableDao)en.create();
7 }
这里得重视,en.setCallbacks()办法里的数组参数次序就是上方办法的返回值所代表的办法阻碍器,若是return 0则应用authProxy阻碍器,return 1则应用NoOp.INSTANCE阻碍器,NoOp.INSTANCE是默认的办法阻碍器,不做什么处理惩罚。
下面在测试类中添加如下办法:
1 //模仿权限过滤器
2 public static void haveAuthByFilter(){
3 TableDao tDao = TableDAOFactory.getAuthInstanceByFilter(new AuthProxy(张三));
4 doMethod(tDao);
5 tDao = TableDAOFactory.getAuthInstanceByFilter(new AuthProxy(李四));
6 doMethod(tDao);
7 }
在main办法中调用该办法,法度运行成果如下:
create() is running...
query() is running...
() is running...
() is running...
你没有权限!
query() is running...
你没有权限!
你没有权限!
如许的话,所有效户都对query办法有接见权限了,而其他办法只容许张三接见。
参考材料:http://llying.iteye.com/blog/220452
我们永远不要期待别人的拯救,只有自己才能升华自己。自己已准备好了多少容量,方能吸引对等的人与我们相遇,否则再美好的人出现、再动人的事情降临身边,我们也没有能量去理解与珍惜,终将擦肩而过。—— 姚谦《品味》




