成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

CGlib:AOP的另一種實現

開發 后端
大家都知道,動態代理能夠實現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 delete(){ 
  8.          System.out.println("delete() is running..."); 
  9.      } 
  10.      public void update(){ 
  11.          System.out.println("update() 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.update();   
  13.          dao.delete();   
  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.     }   
  8.  

  這里得注意,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...
update() is running...
delete() is running...
你沒有權限!
query() is running...
你沒有權限!
你沒有權限!

  這樣的話,所有用戶都對query方法有訪問權限了,而其他方法只允許張三訪問。

責任編輯:周立方 來源: 博客園
相關推薦

2014-09-17 14:37:06

2018-04-18 07:34:58

2010-07-21 16:23:09

運行telnet程序

2023-06-18 23:19:17

ChatGPTPPT方式

2011-12-29 21:28:31

Metro UI

2016-03-03 10:29:31

用戶信息改進

2016-07-11 16:18:26

互聯網

2019-01-02 08:04:29

GAN損失函數神經網絡

2014-01-13 10:36:53

C++錯誤

2013-09-30 10:13:08

IT女程序員

2011-07-21 14:17:15

Ceylon

2015-07-28 13:36:04

2009-06-17 09:05:05

Linux隱藏網絡鏈接命令

2010-09-02 09:14:35

CSS浮動

2009-06-17 12:01:21

Linux

2013-10-21 15:11:15

OrmsqlOrm設計

2021-10-20 12:20:08

深度學習AI賦能

2013-09-12 14:26:47

百度云網盤

2010-06-09 16:17:20

TCP IP協議網絡故

2019-03-17 15:59:05

Android PAPIAPP
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲精品一区二三区不卡 | 久久久久久国产 | 精品国产欧美一区二区三区成人 | 99pao成人国产永久免费视频 | 久久91av | 一区在线视频 | 国产精品亚洲一区二区三区在线 | 狠狠av | 懂色av一区二区三区在线播放 | 日韩中文在线观看 | 亚洲精色 | 国产视频三级 | 久久久久久久久国产精品 | 天天干天天插 | 国产精品久久国产精品 | 精品久久久网站 | 狠狠操狠狠操 | 国产一区不卡 | h视频在线播放 | 久久久久久毛片免费观看 | av日韩在线播放 | 91久久国产综合久久 | 日韩久久综合网 | 在线免费观看欧美 | aaa级片 | 在线91| 精品国产久 | 精品久久久久久久久久 | 亚洲成人在线视频播放 | 国产在线精品免费 | 国产日韩久久 | 久久伊人操 | 精品一二区 | 91视视频在线观看入口直接观看 | 欧美三级在线 | 欧美日韩久久精品 | 欧美精品在欧美一区二区少妇 | 成人网在线看 | 91精品久久久久久久 | 91久久久久 | 综合二区|