Duffblog

          前進一步,看看,需要前進更大一步才可以。

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            5 隨筆 :: 53 文章 :: 5 評論 :: 0 Trackbacks
          反射、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?, 則原有類的每個方法調用都會轉成調用實現了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(AOPInstrumenter.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(AOPInstrumenter.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;
          ??????}
          ??}

          有點遺憾, intercept函數里MethodProxy的Signature是固定的 , 即客戶如果調用foo(String),你不可以用proxy.invoke偷換成foo(String,String);
          posted on 2006-06-17 20:30 追球者 閱讀(162) 評論(0)  編輯  收藏 所屬分類: 技術文摘
          主站蜘蛛池模板: 尚义县| 巍山| 邛崃市| 颍上县| 诏安县| 凤冈县| 临邑县| 青海省| 尼木县| 本溪市| 建水县| 海城市| 大洼县| 威海市| 锦屏县| 班戈县| 凯里市| 威信县| 城固县| 化州市| 全州县| 炉霍县| 桂平市| 嘉荫县| 平谷区| 武隆县| 沙洋县| 金坛市| 仲巴县| 福州市| 河北省| 普兰县| 修水县| 南充市| 芜湖市| 淮滨县| 桑日县| 秦皇岛市| 化州市| 米泉市| 二连浩特市|