如何创建可扩展的Java应用程序
開(kāi)放的擴(kuò)展使許多應(yīng)用程序受益。 這篇文章描述了兩種在Java中實(shí)現(xiàn)這種可擴(kuò)展性的方法。
可擴(kuò)展的應(yīng)用
可擴(kuò)展應(yīng)用程序是可以擴(kuò)展其功能而不必重新編譯它們 ,有時(shí)甚至不必重新啟動(dòng)它們的應(yīng)用程序。 只需將jar添加到類路徑中,或通過(guò)更復(fù)雜的安裝過(guò)程來(lái)實(shí)現(xiàn)。
Eclipse IDE是可擴(kuò)展應(yīng)用程序的一個(gè)示例。 它允許安裝稱為插件的擴(kuò)展,以便可以使用新功能。 例如,您可以安裝源代碼管理(SCM)插件以與您喜歡的SCM一起使用。
再舉一個(gè)例子,設(shè)想一個(gè)實(shí)現(xiàn)了的XACML規(guī)范授權(quán) 。 XACML中的“ X”代表“可擴(kuò)展”,并且規(guī)范定義了許多擴(kuò)展點(diǎn) ,例如屬性和類別ID,結(jié)合了算法,功能和策略信息點(diǎn)。 良好的XACML實(shí)現(xiàn)將允許您通過(guò)提供實(shí)現(xiàn)擴(kuò)展點(diǎn)的模塊來(lái)擴(kuò)展產(chǎn)品。
服務(wù)提供商接口
Oracle用于創(chuàng)建可擴(kuò)展應(yīng)用程序的解決方案是服務(wù)提供商接口 (SPI)。
在這種方法中,擴(kuò)展點(diǎn)由接口定義:
package com.company.application;public interface MyService {// ... }您可以使用ServiceLoader類找到此類擴(kuò)展點(diǎn)的所有擴(kuò)展:
public class Client {public void useService() {Iterator<MyService> services = ServiceLoader.load(MyService.class).iterator();while (services.hasNext()) {MyService service = services.next();// ... use service ...}}此擴(kuò)展點(diǎn)的擴(kuò)展可以是實(shí)現(xiàn)該接口的任何類:
package com.company.application.impl;public class MyServiceImpl implements MyService {// ... }實(shí)現(xiàn)類必須是公共可用的,并且具有公共的無(wú)參數(shù)構(gòu)造函數(shù)。 但是,這對(duì)于ServiceLoader類來(lái)說(shuō)還遠(yuǎn)遠(yuǎn)不夠。
您還必須在META-INF/services創(chuàng)建一個(gè)以擴(kuò)展點(diǎn)接口的標(biāo)準(zhǔn)名稱命名的文件。 在我們的示例中,將是:
META-INF/services/com.company.application.Myservice此文件必須是UTF-8編碼的,否則ServiceLoader將無(wú)法讀取它。 該文件的每一行都應(yīng)包含實(shí)現(xiàn)擴(kuò)展點(diǎn)的一個(gè)擴(kuò)展的全限定名稱,例如:
com.company.application.impl.MyServiceImplOSGi服務(wù)
僅當(dāng)擴(kuò)展點(diǎn)文件位于類路徑上時(shí),上述SPI方法才有效。
在OSGi環(huán)境中,情況并非如此。 幸運(yùn)的是,OSGi對(duì)于擴(kuò)展性問(wèn)題有自己的解決方案: OSGi服務(wù) 。
借助Declarative Services ,OSGi服務(wù)易于實(shí)現(xiàn),尤其是在使用Apache Felix 服務(wù)組件運(yùn)行時(shí) (SCR)的注釋 時(shí) :
@Service @Component public class MyServiceImpl implements MyService {// ... }使用OSGi和SCR,使用服務(wù)也非常容易:
@Component public class Client {@Referenceprivate MyService myService;protected void bindMyService(MyService bound) {myService = bound;}protected void unbindMyService(MyService bound) {if (myService == bound) {myService = null;}}public void useService() {// ... use myService ...}}兩全其美
那么,您應(yīng)該選擇兩個(gè)選項(xiàng)中的哪個(gè)? 當(dāng)然,這取決于您的情況。 在OSGi環(huán)境中,顯然應(yīng)該選擇OSGi服務(wù)。 如果您不在OSGi環(huán)境中,則無(wú)法使用它們,因此只剩下SPI。
但是,如果您正在編寫(xiě)框架或庫(kù),卻又不知道您的代碼是否將在基于OSGi或類路徑的環(huán)境中使用,該怎么辦?
您將希望盡可能多地使用您的庫(kù),因此最好是同時(shí)支持這兩種模型。 如果您要小心,可以這樣做。
請(qǐng)注意,將像OSGI-INF/myServiceComponent.xml這樣的Declarative Services服務(wù)組件文件添加到j(luò)ar中(這是SCR注釋在處理時(shí)最終會(huì)完成的工作)僅在OSGi環(huán)境中有效,但在OSGi外部無(wú)害。
同樣,SPI服務(wù)文件將在傳統(tǒng)的類路徑環(huán)境中工作,但在OSGi中是無(wú)害的。
因此,這兩種方法實(shí)際上是互斥的,并且在任何給定的環(huán)境中,這兩種方法中只有一種會(huì)找到任何東西。 因此,您可以編寫(xiě)使用這兩種方法的代碼。 這有點(diǎn)重復(fù),但是它允許您的代碼在兩種類型的環(huán)境中都能工作,因此您也可以吃蛋糕。
參考: 如何從安全軟件開(kāi)發(fā)博客上的JCG合作伙伴 Remon Sinnema 創(chuàng)建可擴(kuò)展Java應(yīng)用程序 。
翻譯自: https://www.javacodegeeks.com/2012/12/how-to-create-extensible-java-applications.html
總結(jié)
以上是生活随笔為你收集整理的如何创建可扩展的Java应用程序的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 苹果怎么改时间系统时间
- 下一篇: Java – 2012年回顾和未来预测