<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    無為

    無為則可為,無為則至深!

      BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
      190 Posts :: 291 Stories :: 258 Comments :: 0 Trackbacks
    Ruby為助力的Ruby on Rails 橫空出世,又刷新了一次人們對Framework的認識:Closures、Maxin、Continuations、Metaprogramming、Reflection,又一堆名詞砸得人悴不及防。
    ????? Java 雖然沒有動態語言般暴起,但仍然天連天,水接水的生出好多框架技術---反射(reflection),泛型(generics),元數據(annotation),proxies(proxy/cglib),代碼動態生成(asm),AOP(aspectJ),動態語言嵌入(groovy/javascript/beanshell)。面對著這些,我們像一夜暴富的農企,有點手足無措的樣子。

    ??? 第一感覺,應該出現新的Design Pattern書籍了。
    ??? 多年前基于純C++語法寫就的那本經典,很多模式都可以被更優雅的實現,還有更多的新模式,會隨著這些技術的推廣而出現。

    ??? 第二感覺,新的框架模式出現了。
    ??? 不斷升級自己的Spring,綜合運用了除泛型外的大部分技術,把編程界的想像力MFC/ EJB2.0 Container這樣傳統的template模式/鉤子函數的思路,向完全無侵入的標準過渡。
    ??? 當你不顧性能狂用反射時,C++下的遺憾感開始越來越遠。
    ????
    ??? 第三感覺,自己應該重新充電了。
    ??? 從C++下編寫框架的經歷到盡用“反射,泛型,元數據,proxy,代碼動態生成,AOP,動態語言嵌入”是一條明顯的分界線,自己應該調度足夠的業余時間,沉實的學習一遍。

    ??? 這個系列開始一個個介紹上述的積木。





    反射,所有教科書都正兒八經的講了,這里只能再隨便講兩句。

    ?????反射是一種讓框架能夠根據 "以字符串形式存在的信息" 來調用對象的屬性和函數的技術,是Java對C++最大的進步之一---讓框架編程真正走向平民化。MFC年代,無論侯捷如何深入淺出,還在念大學的我就是搞不懂那些注冊"消息--函數映射"的魔法宏。

    ?????不過Java的反射也就是對著C++比較自豪而以,因為C#,Ruby,Python甚至php都標配了反射的功能。而且,人家的反射語法都是內嵌在基礎Object類的,拿最弱的php來看:
    $func_name="helloworld";
    $foo->$func_name;

    ???? 而Java,卻搞出了Class,Methed, Field,Constructor這么一大堆類出來。本來這是Java設計師很嚴謹,很cool的體現,問題是它居然不提供一種集成的簡便的寫法......相同的情形還出現在Java的I/O 類庫里。
    ????微軟這方面就做得好些,懂得討好開發人員。

    ??? 因為Java的無情,就搞得大家的項目里要自制BeanUtils了。幸虧Apache Jakarta Commons 已經做了一個比較好的,可以直接使用--以前寫的介紹文章。
    ??? 另外Spring也做了一個。

    ????閑得沒事做的,還可以emule一本〈Relection in action〉回來看。

    ??? 而C++下面的"反射",見我偶像di文章。另還有一個比較BT的C++框架叫ACDK的,把自己整得和Java很像,有反射和垃圾收集,甚至和JSDK差不多的線程,Unicode,I/O,網絡,XML API??上У氖牵词沟搅薈++0x, B大叔還是不準備在語言級支持反射。



    1.因為兩者的用途不同,所以Annotation與XML應該并存

     Anootation vs XML 到了現在,在Spring和EJB3各占一邊的持續演示下,各自的用途已清晰。
    ?? 雖然兩者之間完全可以相互替代,沒有絕對不能做的事情,但卻存在好不好的問題,兩者的用途不同,應該并用:

    ?? "size=10,db_user=ito"這樣的參數,仍然適合放在XML,YAML(ruby),properties,ini文件里。
    ??? 而Annotation中所放,是真正程序的一部分,是舊編程體系中所缺的那一塊東西。
     看看編程語言的發展:
    ????一開始只是函數的封裝;
    ??? 到了OO語言,對象有了自己的屬性和方法;
    ??? 到了框架滿天飛的年代,這些屬性和方法又有了自己的屬性,來告訴框架如何為自己提供服務。比如Spring和EJB3,POJO就用配置信息來告訴框架無侵入的提供服務。整個進化的過程非常自然。

    ????因為這些信息本來就是程序的一部分,所以應該仍然放在Code里頭,Spring把它割裂到XML明顯影響了代碼的閱讀。

    2.Anotation/XML?PK Interface,Spring 無侵入性的基礎
    ???切爾斯基的Blog講了Annotation/XML?對Interface的PK。這次PK,也可以認為是Spring 對 EJB2.1在框架無侵入性上的一次PK。
    ?? 在EJB2.1時代,POJO必須通過接口來向框架聲明一些東西,這就造成了框架的侵入性,強迫POJO實現一堆接口。而Spring,把這些元信息搬到了XML配置文件。
     在Spring里隨便就可以舉個例子。比如一個POJO,在Spring為它進行依賴注入A和B后,需要根據A和B來裝配一個內部屬性C,這樣就需要再跑一個init()函數。Spring提供兩種方式,一種侵入性的,實現InitializingBean接口的afterPropertiesSet()函數供Spring調用。???而另一種是無侵入性的,在Bean的xml節點里面自行定義init函數的名字。

    3.Annotation目前的弱點
     一是Hibernate、Struts、三姑媽、四姨婆的annotation如果一股腦兒的全堆在可憐的POJO上很沒人道,如果三姑六婆都搶Transation這個Anontation就更慘了。
    ??? 二是annoation的表達能力有限,不如XML的強。

    4.JSR250 - Common Annotations for the Java
    ??? Final Draft已經發布,八卦回來一看,也只是多定義了幾個Common Annotation而已。
    ?? 1.Generated? 自動生成的代碼要用此聲明,而且必須說明工具的名稱,如@Generated(“com.sun.xml.rpc.AProcessor”)

    ???2.Resource/Resources 就是EJB3里面用的資源引用。

    ?? 3.PostConstruct / PreDestroy 聲明那些如題的函數。
    ??
    ?? 還有一些安全方面的annotation,不關心。



    反射、Proxy和元數據是Java最強的三個特征,再加上CGLib (Code Generation Library)和ASM,使得Java雖然沒有Ruby,Python般后生可畏,一樣能做出強悍的框架。
    ???Proxy可以看作是微型的AOP,明白提供了在繼承和委托之外的第三個代碼封裝途徑,只要有足夠的想象力,可以做得非常好玩,Spring的源碼里用Proxy就用得很隨便,看得我非常眼紅??上roxy必須基于接口。因此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);







    凡是有該標志的文章,都是該blog博主Caoer(草兒)原創,凡是索引、收藏
    、轉載請注明來處和原文作者。非常感謝。

    posted on 2006-09-07 14:59 草兒 閱讀(1938) 評論(0)  編輯  收藏 所屬分類: Java編程經驗談
    主站蜘蛛池模板: 久久99毛片免费观看不卡| 在线观看永久免费视频网站| 久久亚洲最大成人网4438| 精品免费久久久久久成人影院| 成年免费大片黄在线观看com| 亚洲AV无码码潮喷在线观看| 久久久久免费看黄A片APP | 一级特黄a大片免费| 亚洲成色在线影院| 日韩毛片免费在线观看| 视频免费在线观看| 亚洲国产成人综合精品| 亚洲av无码潮喷在线观看| 日本一道综合久久aⅴ免费| 黄色片免费在线观看| 亚洲乱色熟女一区二区三区蜜臀| 在线亚洲精品福利网址导航| 三年片在线观看免费大全| a毛片在线看片免费| 亚洲av乱码中文一区二区三区| 亚洲AV无码不卡在线播放| 免费a级毛片大学生免费观看| 成人免费的性色视频| A级毛片高清免费视频在线播放| 亚洲精品av无码喷奶水糖心| 一区二区三区亚洲| 丝袜熟女国偷自产中文字幕亚洲| 午夜视频免费观看| av无码国产在线看免费网站| 野花香高清在线观看视频播放免费| 亚洲av成人无码网站…| 亚洲av片不卡无码久久| 亚洲国产综合91精品麻豆| 综合亚洲伊人午夜网 | 亚洲色图在线播放| 激情97综合亚洲色婷婷五| 日韩一区二区三区免费体验| 免费福利视频导航| 久久午夜夜伦鲁鲁片无码免费| 四虎精品成人免费视频| 国产精品亚洲va在线观看|