posts - 41,  comments - 8,  trackbacks - 0
          Java下的框架編程之cglib的應用
           

          Proxy可以看作是微型的AOP,明白提供了在繼承和委托之外的第三個代碼封裝途徑,只要有足夠的想象力,可以做得非常好玩,Spring的源碼里用Proxy就用得很隨便,看得我非常眼紅。可惜Proxy必須基于接口。因此Spring的做法,基于接口的用proxy,否則就用cglib。AOP么,一般小事非compoent一級的就不麻煩AspectJ出手了。

          cglib的Enhancer說起來神奇,用起來一頁紙不到就講完了。

          它的原理就是用Enhancer生成一個原有類的子類,并且設置好callback到proxy, 則原有類的每個方法調用都會轉為調用實現(xiàn)了MethodInterceptor接口的proxy的intercept() 函數(shù):

                                  

          public Object intercept(Object o,Method method,Object[] args,MethodProxy proxy)

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

          AOP沒有出現(xiàn)以前,該領域經典的設計模式是Decorator,像Java IO Stream的設計就是如此。不過,如果為每個DAO, 每個方法的寫Decorator函數(shù)會寫死人的,所以用上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();創(chuàng)建子類實例,但在Spring管理下,一些Bean的實例必須由Spring來創(chuàng)建和管理,而不由enhancer來創(chuàng)建的。所以我對上述用法略加修改,使它真正當一個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創(chuàng)建dao,而 調用intercept時則將enhancer創(chuàng)建的dao以Object o參數(shù)傳回。
          而新模式里,dao在getDao()時從外面?zhèn)魅?,enhancer.create()返回的是一個proxy. 而調用intercept時,實際會用之前傳入的dao進行操作,而忽略Object o參數(shù)傳入的proxy。

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

          posted on 2008-10-08 10:38 Loy Fu 閱讀(406) 評論(0)  編輯  收藏 所屬分類: java
          主站蜘蛛池模板: 施甸县| 武陟县| 嘉义市| 广平县| 普陀区| 九台市| 衡水市| 普定县| 正宁县| 湘潭市| 孟津县| 濮阳县| 延寿县| 胶南市| 益阳市| 孝昌县| 什邡市| 抚松县| 黄大仙区| 巩留县| 富宁县| 龙泉市| 霸州市| 白玉县| 柳林县| 城口县| 广昌县| 福海县| 洪洞县| 江西省| 八宿县| 阿勒泰市| 阜南县| 田林县| 崇信县| 鄂托克前旗| 句容市| 平原县| 嵊泗县| 逊克县| 怀化市|