乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Java下的框架編程(反射,泛型,元數(shù)據(jù),CGLib,代碼動(dòng)態(tài)生成,AOP,動(dòng)態(tài)語(yǔ)言嵌入)

       ShangShujie 2007-04-11
      作者:江南白衣
                                                      
         以Ruby為助力的Ruby on Rails 橫空出世,又刷新了一次人們對(duì)Framework的認(rèn)識(shí):Closures、Maxin、Continuations、Metaprogramming、Reflection,又一堆名詞砸得人悴不及防。
            Java 雖然沒有動(dòng)態(tài)語(yǔ)言般暴起,但仍然天連天,水接水的生出好多框架技術(shù)---反射(reflection),泛型(generics),元數(shù)據(jù)(annotation),proxies(proxy/cglib),代碼動(dòng)態(tài)生成(asm),AOP(aspectJ),動(dòng)態(tài)語(yǔ)言嵌入(groovy/javascript/beanshell)。面對(duì)著這些,我們像一夜暴富的農(nóng)企,有點(diǎn)手足無(wú)措的樣子。

          第一感覺,應(yīng)該出現(xiàn)新的Design Pattern書籍了。
          多年前基于純C++語(yǔ)法寫就的那本經(jīng)典,很多模式都可以被更優(yōu)雅的實(shí)現(xiàn),還有更多的新模式,會(huì)隨著這些技術(shù)的推廣而出現(xiàn)。

          第二感覺,新的框架模式出現(xiàn)了。
          不斷升級(jí)自己的Spring,綜合運(yùn)用了除泛型外的大部分技術(shù),把編程界的想像力MFC/ EJB2.0 Container這樣傳統(tǒng)的template模式/鉤子函數(shù)的思路,向完全無(wú)侵入的標(biāo)準(zhǔn)過(guò)渡。
          當(dāng)你不顧性能狂用反射時(shí),C++下的遺憾感開始越來(lái)越遠(yuǎn)。
          
          第三感覺,自己應(yīng)該重新充電了。
          從C++下編寫框架的經(jīng)歷到盡用“反射,泛型,元數(shù)據(jù),proxy,代碼動(dòng)態(tài)生成,AOP,動(dòng)態(tài)語(yǔ)言嵌入”是一條明顯的分界線,自己應(yīng)該調(diào)度足夠的業(yè)余時(shí)間,沉實(shí)的學(xué)習(xí)一遍。

          這個(gè)系列開始一個(gè)個(gè)介紹上述的積木。

      Java5泛型的用法,T.class的獲取和為擦拭法站臺(tái)

      作者:江南白衣 

         Java 5的泛型語(yǔ)法已經(jīng)有太多書講了,這里不再打字貼書。GP一定有用,不然Java和C#不會(huì)約好了似的同時(shí)開始支持GP。但大家也清楚,GP和Ruby式的動(dòng)態(tài)OO語(yǔ)言屬于不同的意識(shí)形態(tài),如果是一人一票,我想大部分的平民程序員更熱衷動(dòng)態(tài)OO語(yǔ)言的平白自然。但如果不準(zhǔn)備跳槽到支持JSR223的動(dòng)態(tài)語(yǔ)言,那還是看看GP吧。

         胡亂總結(jié)泛型的四點(diǎn)作用:
         第一是泛化,可以拿個(gè)T代表任意類型。 但GP是被C++嚴(yán)苛的靜態(tài)性逼出來(lái)的,落到Java、C#這樣的花語(yǔ)平原里----所有對(duì)象除幾個(gè)原始類型外都派生于Object,再加上Java的反射功能,Java的Collection庫(kù)沒有范型一樣過(guò)得好好的。

         第二是泛型 + 反射,原本因?yàn)镴ava的泛型拿不到T.class而覺得泛型沒用,最近才剛剛學(xué)到通過(guò)反射的API來(lái)獲取T的Class,后述。

         第三是收斂,就是增加了類型安全,減少了強(qiáng)制類型轉(zhuǎn)換的代碼。這點(diǎn)倒是Java Collection歷來(lái)的弱項(xiàng)。

         第四是可以在編譯期搞很多東西,比如MetaProgramming。但除非能完全封閉于框架內(nèi)部,框架的使用者和擴(kuò)展者都不用學(xué)習(xí)這些東西的用法,否則那就是自絕于人民的票房毒藥。C++的MetaProgramming好厲害吧,但對(duì)比一下Python拿Meta Programming生造一個(gè)Class出來(lái)的簡(jiǎn)便語(yǔ)法,就明白什么才是真正的叫好又叫座。

         所以,作為一個(gè)架構(gòu)設(shè)計(jì)師,應(yīng)該使用上述的第2,3項(xiàng)用法,在框架類里配合使用反射和泛型,使得框架的能力更強(qiáng); 同時(shí)采用收斂特性,本著對(duì)人民負(fù)責(zé)的精神,用泛型使框架更加類型安全,更少?gòu)?qiáng)制類型轉(zhuǎn)換。
         
         擦拭法避免了Java的流血分裂 :
          大家經(jīng)常罵Java GP的擦拭法實(shí)現(xiàn),但我覺得多虧于它的中庸特性---如果你用就是范型,不用就是普通Object,避免了Java陣營(yíng)又要經(jīng)歷一場(chǎng)to be or not to be的分裂。 
          最大的例子莫過(guò)Java 5的Collection 框架, 比如有些同學(xué)堅(jiān)持認(rèn)為自己不會(huì)白癡到類型出錯(cuò),而且難以忍受每個(gè)定義的地方都要帶一個(gè)泛型定義List〈Book〉,不用強(qiáng)制類型轉(zhuǎn)換所省下的代碼還不夠N處定義花的(對(duì)了,java里面還沒有tyepdef.....),因此對(duì)范型十分不感冒,這時(shí)就要齊齊感謝這個(gè)搽拭法讓你依然可以對(duì)一個(gè)泛型框架保持非泛型的用法了...

         通過(guò)反射獲得 T.class:
         
          不知為何書上不怎么講這個(gè),是差沙告訴我才知道的,最經(jīng)典的應(yīng)用見Hibernate wiki的Generic Data Access Objects, 代碼如下: 
      abstract public class BaseHibernateEntityDao<T> extends HibernateDaoSupport {
       
      private Class<T> entityClass;
       
      public BaseHibernateEntityDao() {
              entityClass 
      =(Class<T>) ((ParameterizedType) getClass()
                                      .getGenericSuperclass()).getActualTypeArguments()[0];
          }
       
      public T get(Serializable id) {
              T o 
      = (T) getHibernateTemplate().get(entityClass, id);
      }
      }

        精華就是這句了:
      Class<T> entityClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; 

        泛型之后,所有BaseHibernateEntityDao的子類只要定義了泛型,就無(wú)需再重載getEnttityClass(),get()函數(shù)和find()函數(shù),銷益挺明顯的,所以SpringSide的Dao基類毫不猶豫就泛型了。

        不過(guò)擦拭法的大棒仍在,所以子類的泛型語(yǔ)法可不能亂寫,最正確的用法只有:
         
      public class BookDao extends BaseHibernateEntityDao<Book>
       

      Java下的框架編程(3)--關(guān)于反射的碎話

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

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

           不過(guò)Java的反射也就是對(duì)著C++比較自豪而以,因?yàn)镃#,Ruby,Python甚至php都標(biāo)配了反射的功能。而且,人家的反射語(yǔ)法都是內(nèi)嵌在基礎(chǔ)Object類的,拿最弱的php來(lái)看:
      $func_name="helloworld";
      $foo->$func_name;

           而Java,卻搞出了Class,Methed, Field,Constructor這么一大堆類出來(lái)。本來(lái)這是Java設(shè)計(jì)師很嚴(yán)謹(jǐn),很cool的體現(xiàn),問(wèn)題是它居然不提供一種集成的簡(jiǎn)便的寫法......相同的情形還出現(xiàn)在Java的I/O 類庫(kù)里。
          微軟這方面就做得好些,懂得討好開發(fā)人員。

          因?yàn)镴ava的無(wú)情,就搞得大家的項(xiàng)目里要自制BeanUtils了。幸虧Apache Jakarta Commons 已經(jīng)做了一個(gè)比較好的,可以直接使用--以前寫的介紹文章。
          另外Spring也做了一個(gè)。

          閑得沒事做的,還可以emule一本〈Relection in action〉回來(lái)看。

          而C++下面的"反射",見我偶像di文章。另還有一個(gè)比較BT的C++框架叫ACDK的,把自己整得和Java很像,有反射和垃圾收集,甚至和JSDK差不多的線程,Unicode,I/O,網(wǎng)絡(luò),XML API??上У氖?,即使到了C++0x, B大叔還是不準(zhǔn)備在語(yǔ)言級(jí)支持反射。
       

      Java下的框架編程(4)--Annotation vs XML vs Interface 最新一Round

      作者:江南白衣 

      1.因?yàn)閮烧叩挠猛静煌?,所以Annotation與XML應(yīng)該并存

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

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

          因?yàn)檫@些信息本來(lái)就是程序的一部分,所以應(yīng)該仍然放在Code里頭,Spring把它割裂到XML明顯影響了代碼的閱讀。

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

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

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

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

         3.PostConstruct / PreDestroy 聲明那些如題的函數(shù)。
        
         還有一些安全方面的annotation,不關(guān)心
       

      Java下的框架編程(5)--cglib的應(yīng)用

         作者:江南白衣 

         反射、Proxy和元數(shù)據(jù)是Java最強(qiáng)的三個(gè)特征,再加上CGLib (Code Generation Library)和ASM,使得Java雖然沒有Ruby,Python般后生可畏,一樣能做出強(qiáng)悍的框架。
         Proxy可以看作是微型的AOP,明白提供了在繼承和委托之外的第三個(gè)代碼封裝途徑,只要有足夠的想象力,可以做得非常好玩,Spring的源碼里用Proxy就用得很隨便,看得我非常眼紅??上roxy必須基于接口。因此Spring的做法,基于接口的用proxy,否則就用cglib。AOP么,一般小事非compoent一級(jí)的就不麻煩AspectJ出手了。

          cglib的Enhancer說(shuō)起來(lái)神奇,用起來(lái)一頁(yè)紙不到就講完了。
          它的原理就是用Enhancer生成一個(gè)原有類的子類,并且設(shè)置好callback到proxy, 則原有類的每個(gè)方法調(diào)用都會(huì)轉(zhuǎn)為調(diào)用實(shí)現(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);來(lái)執(zhí)行原有函數(shù),在執(zhí)行前后加入自己的東西,改變它的參數(shù)值,也可以瞞天過(guò)海,完全干別的。說(shuō)白了,就是AOP中的around advice。

          AOP沒有出現(xiàn)以前,該領(lǐng)域經(jīng)典的設(shè)計(jì)模式是Decorator,像Java IO Stream的設(shè)計(jì)就是如此.不過(guò),如果為每個(gè)DAO, 每個(gè)方法的寫Decorator函數(shù)會(huì)寫死人的,所以用上cglib的好處是一次過(guò)攔截所有方法。 

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

      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();
             }
             
      //默認(rèn)的攔截方法
            public Object intercept(Object o,Method method,Object[] args,MethodProxy proxy) throws Throwable
            {
                 log.info(
      "調(diào)用日志方法"+method.getName());
                 Object result
      =proxy.invokeSuper(o,args);
                 
      return result;
            }
         }

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

      2.而在Spring的管理下應(yīng)該略加修改的高級(jí)Decorator
         上面的例子用return enhancer.create();創(chuàng)建子類實(shí)例,但在Spring管理下,一些Bean的實(shí)例必須由Spring來(lái)創(chuàng)建和管理,而不由enhancer來(lái)創(chuàng)建的。所以我對(duì)上述用法略加修改,使它真正當(dāng)一個(gè)Proxy的角色,請(qǐng)對(duì)比黑體字的部分


        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();
             }      
             
      //默認(rèn)的攔截方法
            public Object intercept(Object o,Method method,Object[] args,MethodProxy proxy) throws Throwable
            {
                 log.info(
      "調(diào)用日志方法"+method.getName());
                 Object result
      =proxy.invoke(dao, args);
                 
      return result;
            }
        }

      可見,原來(lái)模式里在getDao()時(shí)由enhancer創(chuàng)建dao,而 調(diào)用intercept時(shí)則將enhancer創(chuàng)建的dao以O(shè)bject o參數(shù)傳回。
      而新模式里,dao在getDao()時(shí)從外面?zhèn)魅?,enhancer.create()返回的是一個(gè)proxy. 而調(diào)用intercept時(shí),實(shí)際會(huì)用之前傳入的dao進(jìn)行操作,而忽略O(shè)bject o參數(shù)傳入的proxy.

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

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多