Java下的架構編程(5)–cglib的應用

來源:互聯網
上載者:User
反射、Proxy和中繼資料是Java最強的三個特徵,再加上CGLib (Code Generation Library)和ASM,使得Java雖然沒有Ruby,Python般後生可畏,一樣能做出強悍的架構。
   Proxy可以看作是微型的AOP,明白提供了在繼承和委託之外的第三個代碼封裝途徑,只要有足夠的想象力,可以做得非常好玩,Spring的源碼裡用Proxy就用得很隨便,看得我非常眼紅。可惜Proxy必須基於介面。因此Spring的做法,基於介面的用proxy,否則就用cglib。AOP麼,一般小事非compoent一級的就不麻煩AspectJ出手了。

    cglib的Enhancer說起來神奇,用起來一頁紙不到就講完了。
    它的原理就是用Enhancer產生一個原有類的子類,並且設定好callback到proxy, 則原有類的每個方法調用都會轉為調用實現了MethodInterceptor介面的proxy的intercept() 函數:public Object intercept(Object o,Method method,Object[] args,MethodProxy proxy)

 在intercept()函數裡,你可以在執行Object result=proxy.invokeSuper(o,args);來執行原有函數,在執行前後加入自己的東西,改變它的參數值,也可以瞞天過海,完全乾別的。說白了,就是AOP中的around advice。

    AOP沒有出現以前,該領域經典的設計模式是Decorator,像Java IO Stream的設計就是如此.不過,如果為每個DAO, 每個方法的寫Decorator函數會寫死人的,所以用上cglib的好處是一次過攔截所有方法。 

     另外,cglib除了Enhancer之外,還有BulkBean和Transform,都是Hibernate持久化的基礎,但文檔貧乏,一時還沒去看怎麼用。

1.AOP裡講了一百遍阿一百遍的log aspect在cglib是這樣做的:


   public class LogDAOProxy implements MethodInterceptor
   {
       private Logger log=Logger.getLogger(LogDAOProxy.class);
       private Enhancer enhancer=new Enhancer();
        //返回DAO的子類
       public Object getDAO(Class clz)
       {
           enhancer.setSuperclass(clz);
           enhancer.setCallback(this);
           return enhancer.create();
       }
       //預設的攔截方法
      public Object intercept(Object o,Method method,Object[] args,MethodProxy proxy) throws Throwable
      {
           log.info("調用日誌方法"+method.getName());
           Object result=proxy.invokeSuper(o,args);
           return result;
      }
   }

    應用的代碼:    LogDAOProxy proxy = new LogDAOProxy();
    GoodsDAO  dao = (GoodsDAO)proxy.getDAO(GoodsDAO.class);
    dao.insert(goods);

2.而在Spring的管理下應該略加修改的進階Decorator
   上面的例子用return enhancer.create();建立子類執行個體,但在Spring管理下,一些Bean的執行個體必須由Spring來建立和管理,而不由enhancer來建立的。所以我對上述用法略加修改,使它真正當一個Proxy的角色,請對比黑體字的部分

  public class LogDAOProxy implements MethodInterceptor
  {
       private Logger log=Logger.getLogger(LogDAOProxy.class);
         private Object dao=null ;
       private Enhancer enhancer=new Enhancer();
        //返回DAO的子類
       public Object getDAO(Class clz,Object dao)
       {
            this.dao =  dao;
           enhancer.setSuperclass(clz);
           enhancer.setCallback(this);
           return enhancer.create();
       }      
       //預設的攔截方法
      public Object intercept(Object o,Method method,Object[] args,MethodProxy proxy) throws Throwable
      {
           log.info("調用日誌方法"+method.getName());
            Object result = proxy.invoke(dao, args);
           return result;
      }
  }

可見,原來模式裡在getDao()時由enhancer建立dao,而 調用intercept時則將enhancer建立的dao以Object o參數傳回。
而新模式裡,dao在getDao()時從外面傳入,enhancer.create()返回的是一個proxy. 而調用intercept時,實際會用之前傳入的dao進行操作,而忽略Object o參數傳入的proxy.

有點遺憾, intercept函數裡MethodProxy的Signature是固定的 , 即客戶如果調用foo(String),你不可以用proxy.invoke偷換成foo(String,String);

系列文章:
Java下的架構編寫(1)--序
Java下的架構編程(2)-對泛型的無聊用法和為擦拭法月台 
Java下的架構編程(3)--關於反射的碎話 
Java下的架構編程(4)--Annotation vs XML vs Interface 最新一Round 
Java下的架構編程(5)--cglib應用
Java下的架構編程(6)--asm(待寫) 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.