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

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

    • 分享

      Java 8動態(tài)代理的新技巧(1):為什么使用動態(tài)代理?

       月影曉風(fēng) 2015-09-27

      (點擊上方公眾號,可快速關(guān)注)


      來源:ImportNew

      鏈接:http://www./16670.html


      動態(tài)代理(Dynamic proxies)是 Java 1.3 引入的特性,在 J2EE 的遠(yuǎn)程調(diào)用中應(yīng)用非常廣泛。給定一個抽象接口以及這個接口的具體實現(xiàn),就可以通過創(chuàng)建兩個額外的類來實現(xiàn)這個接口的遠(yuǎn)程調(diào)用了(如,跨JVM)。首先,在源JVM上實現(xiàn)相應(yīng)的接口,并將調(diào)用細(xì)節(jié)序列化后通過網(wǎng)絡(luò)傳輸。然后,在目標(biāo)JVM上,獲取到序列化后的調(diào)用的細(xì)節(jié),并分配給具體的的類去調(diào)用。


      沒有動態(tài)代理和反射,開發(fā)者不得不為每個遠(yuǎn)程接口提供兩個類。一個動態(tài)代理是運(yùn)行時產(chǎn)生的類,實現(xiàn)一個或多個接口,接口中每個方法的調(diào)用都會自動轉(zhuǎn)換為 java.runtime.InvocationHandler 提供的方法調(diào)用:



      public interface InvocationHandler {

      Object invoke(Object proxy, Method method, Object[] args) throws Throwable;

      }


      InvocationHandler決定如何處理調(diào)用,如何在運(yùn)行時使用方法的有效信息,包括注解、參數(shù)類型及方法的返回類型。這樣就可以實現(xiàn)一個通用邏輯來定義方法調(diào)用的分發(fā)。一旦你寫好了一個InvocationHandler,就可以調(diào)用代理類的 handler 來完成所有接口中的方法,而不是為每一個接口寫一個單獨的實現(xiàn)。


      遠(yuǎn)程調(diào)用最近幾年里已經(jīng)沒那么受歡迎了,因為開發(fā)者需要明白方法調(diào)用分發(fā)與網(wǎng)絡(luò)請求發(fā)送在語義和失敗模式上的本質(zhì)區(qū)別,但是動態(tài)代理仍保留在語言當(dāng)中。在這篇文章中,我將討論動態(tài)代理其他方面的作用。在下一篇文章中,將討論動態(tài)代理新的實現(xiàn)技術(shù),這些技術(shù)是由于 Java 8 引入 lambda 表達(dá)式和默認(rèn)方法而產(chǎn)生的。


      魔法匹配器


      這些年來,我一直在使用一個“magic”對象,以便能夠?qū)懗龊啙嵉牧魇綔y試。我定義了一個“magic”的接口,然后通過一個動態(tài)代理來實現(xiàn)目標(biāo)行為。比較特別的是,在測試時候用”magic builders”來生成測試值,然后用“magic matchers”來表述斷言屬性測試的結(jié)果。我們這里只關(guān)注匹配器。


      我們有一個Person支撐類,這是一個典型的bean——成員變量是私有的,通過getter和setter方法暴露。


      public class Person {

      private String name;

      private int age;

      // insert getters and setters here

      }


      使用一個簡單Hamcrest類,我們有兩種方式來斷言該類的實例。一種方法是單獨抽取每個值,分開斷言。


      assertThat(person.getName(), containsString('Smith'));

      assertThat(person.getAge(), greaterThan(30));


      另一種方式是使用allOf和hasProperty方法,將對象作為一個整體,通過一組期望值來匹配。


      assertThat(person, allOf(

      hasProperty('name', containsString('Smith')),

      hasProperty('age', greaterThan(30)));


      這樣能很好的工作,但是這種方式對 Hamcrest 描述整體匹配和錯誤匹配并沒有什么幫助。


      Expected: (hasProperty('name', a string containing 'Putey') and hasProperty('age', a value greater than <43>))

      but: hasProperty('age', a value greater than <43>) property 'age' <42> was less than <43>


      hasProperty的匹配在類型一致性的檢測也是非常弱的:我們可以寫成 hasProperty(“age”, containsString(“Smith”)),這樣類型檢測也不會拒絕。


      我們真正想要的是一個流式API,能夠像下面一樣使用:


      assertThat(person, aPerson()

      .withName('Arthur Putey')

      .withAge(greaterThan(43)));


      并且能夠很好且易于理解地報告錯誤的匹配:


      Expected:

      name: a string containing 'Putey'

      age: a value greater than <43>

      but:

      age: <42> was less than <43>


      很容易寫一個上述功能的自定義匹配器,但是不得不很乏味地寫很多次。幸運(yùn)的是,可以通過動態(tài)代理來幫我們解決。首先,我們定義一個流式接口,該接口包含如下方法:


      interface PersonMatcher extends Matcher<Person> {

      PersonMatcher withName(String expected);

      PersonMatcher withName(Matcher<? super String> matching);

      PersonMatcher withAge(int expected);

      PersonMatcher withAge(Matcher<Integer> matching);

      }


      然后,我們使用在一個名為 MagicMatcher 的類上的靜態(tài)方法來獲取動態(tài)代理,該代理實現(xiàn)了這個接口,然后通過方法調(diào)用來獲取調(diào)節(jié)表達(dá)式:


      static PersonMatcher aPerson() {

      return MagicMatcher.proxying(PersonMatcher.class);

      }


      每個方法的調(diào)用都通過代理類的“interpreted”方法來實現(xiàn),該代理從方法(“withAge”)中獲取屬性(“age”),并指定調(diào)用匹配對象上的(“getAge”)方法來獲取屬性值。屬性的名稱以及匹配中對應(yīng)的值將會被存儲,直到代理類的 match 或 describeMismatch 方法被調(diào)用(這就是為什么接口需要繼承 Matcher)。在調(diào)用的時候需要抽取并測試對象的屬性,如果有必要,會創(chuàng)建錯誤匹配報告。


      這種方式是輕量級的,我們可以引入任何新的自定義的接口,并在測試中重用,這樣,是非常有利于編寫自定義Hamcrest匹配器的,因為不再需要編寫接口的實現(xiàn)。所有需要生成的在接口中定義的匹配器行為,都只需要實現(xiàn)一次,我們通過一個合適的 InvocationHandler 來完成邏輯功能的實現(xiàn)。


      下一篇文章中,我將創(chuàng)建一個很小的,但是很有用的庫,我們使用 Java 8 的動態(tài)代理來完成各項功能,并演示一些用于實現(xiàn)各種代理行為的方式,包括接口及”magic”對象的生成。這個庫的源代碼,包括這篇文章中討論的 MagicMatcher 類的實現(xiàn),都可以在 github 上找到。




       

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

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多