使用Java 8.0进行类型安全的依赖注入
所以有時我真的很想念舊學校的依賴注入。 當Spring仍然“輕量級”時,我們很高興地用“ 一天學習 ” Spring bean xml配置在application.xml文件中配置了所有bean。 缺點當然是類型安全性的損失。 我可以想到很多測試用例,它們的唯一目的是引導Spring配置文件,并只是看看ApplicationContext是否由于接線錯誤和所包含的bean xml配置文件的正確解析而啟動而不會引起麻煩。
我可能是少數,但我從未喜歡過Spring Schema配置。 在我看來,配置有點像配置。
需要注意的是,您必須為所有這些注釋導入庫。 我喜歡注釋,但是將所有DI信息放在一個中央位置是一個很好的情況,這樣您就可以實際看到您的應用程序是如何掛在一起的。 最后,有時您需要創建無法注釋的托管對象。
Java Spring配置通過編譯時安全性使事情變得更好,但是我不得不重新考慮我執行大量接線的方式,因為當我丟失了一些懶惰的評估時,我不得不小心地進行接線。當ApplicationContext啟動時,作為Java代碼的Spring上下文將立即評估。
因此,基于Java的DI很好,但是如何使用Java 8.0進行改進呢?
套用Lambda Hammer
正確,所以這是開始在Java 8.0中應用新錘子的文章的一部分: Lambdas 。
首先,Lambda提供了一種安全的方式來推遲執行直到需要時。
因此,讓我們首先創建一個稱為“ ObjectDefinition”的包裝對象,該對象的工作是定義如何創建對象并使用各種值進行連接。 它通過實例化要創建的類和對象來工作(在這種情況下,我們有一個名為“ MyObject ”的類)。 我們還為它提供了映射到特定值的java.util.function.BiConsumer接口的列表。 該列表將用于執行在對象上設置值的實際任務。
然后,ObjectDefintion使用正反射實例化對象,然后運行BiConsumer接口列表,傳遞具體對象的實例和映射的值。
假設我們為ObjectDefinition提供了流暢的DSL,我們可以通過添加set()方法來定義對象,該方法采用BiConsumer和要設置的值并填充BiConsumer列表,如下所示:
MyObject result = new ObjectDefinition() .type(MyObject.class).set((myObject, value)-> myObject.setA(value), "hello world").set((myObject, value)-> myObject.setB(value), "hallo welt").create();create()方法僅實例化MyObject實例,然后遍歷BiConsumers列表,并通過映射值調用它們。
(好金田)
現在,Java 8.0中的另一個有趣的功能是方法引用,該功能是編譯器將方法包裝在功能接口中的功能,條件是該方法可以映射到該功能接口的簽名。
方法引用允許您映射到對象的任意實例,前提是該方法的第一個參數是該實例值,且后續參數與其參數列表匹配。
這使我們可以將BiConsumer映射到setter,其中第一個參數是目標實例,第二個參數是傳遞給setter的值:
MyObject result = new ObjectDefinition().type(MyObject.class).set(MyObject::setA, "hello world").set(MyObject::setB, "hallo welt").create();方法引用提供了一個有趣的功能,因為它提供了一種以完全類型安全的方式將引用傳遞給方法的方法。 所有示例都需要設置正確的類型和值,并且setter方法需要與該類型相對應。
現在是集裝箱時間
因此,現在我們有了一個不錯的用于構建對象的小DSL,但是如何將其粘貼到容器中并允許ObjectDefinition注入對其他值的引用呢?
好吧,假設我們有這個容器,它方便地提供了一個build()方法,該方法提供了一個添加新ObjectDefinition的鉤子。
現在,我們有了一個容器,可以用來在該容器中注入不同的對象:
Container container = create((builder) -> {builder.define(MyObject.class).set(MyObject::setA, "hello world");});String myString = container.get(MyObject.class);我們的Container對象具有define()方法,該方法創建ObjectDefinition的實例,然后該實例用于定義如何創建對象。
但是依賴項呢?
如果不能注入依賴項,則依賴注入是沒有樂趣的,但是由于有了容器,我們現在可以引用容器中的其他對象。
為此,我們將inject()方法添加到我們的ObjectDefinition類型中,然后可以使用該類型來引用容器中的另一個對象:
Container container = create((builder) -> {builder.define(String.class).args("hello world");builder.define(MyObject.class).inject(MyObject::setA,String.class);});MyObject myString = container.get(MyObject.class);在此示例中,我們映射了另一個String類型的對象(這里的args()方法是可以將值映射到對象的構造函數的方法)。 然后,我們調用inject()方法注入此String。
生命周期。
我們可以使用Lambda和方法引用的相同方法來管理容器中對象的生命周期。
假設我們要在設置所有值之后運行初始化方法,我們只需添加一個新的Functional接口,然后在設置所有值之后調用該接口。
在這里,我們使用java.util.function.Consumer接口,其中參數是我們要調用初始化代碼的實例。
Container container = create((builder) -> {builder.define(MyObject.class).set(MyObject::setA,"hello world").initWith(MyObject::start);});MyObject myString = container.get(MyObject.class);在此示例中,我們向MyObject類添加了一個start()方法。 然后將其作為消費者通過initWith()方法傳遞給ObjectDefinition。
另一個依賴注入容器
因此,所有這些技術(和更多)被包括在YADI集裝箱,它表示Y等甲諾特爾d ependancy 我 njection?ontainer。
- 可以在Github上找到該代碼,網址為https://github.com/jexenberger/yadi 。 并根據Apache許可獲得許可。
翻譯自: https://www.javacodegeeks.com/2014/06/type-safe-dependency-injection-using-java-8-0.html
總結
以上是生活随笔為你收集整理的使用Java 8.0进行类型安全的依赖注入的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 淘宝备案开店流程(淘宝备案开店)
- 下一篇: java ee maven_针对新手的J