偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

OSGi服務(wù):非常適合SOA的架構(gòu)

開發(fā) 后端
本文介紹OSGi服務(wù)。OSGi架構(gòu)非常適合我們實(shí)現(xiàn)面向服務(wù)的應(yīng)用(SOA)。OSGi具有隱藏真實(shí)的服務(wù)實(shí)現(xiàn)類的能力,所以它為面向服務(wù)的應(yīng)用提供了良好的類與接口的組合。

本文是《你好,OSGi》系列的第四部分。下面講述OSGi服務(wù)。對OSGi不是很了解的讀者可以先閱讀OSGi是什么一文。

OSGi服務(wù)

前面我們提到,OSGi架構(gòu)非常適合我們實(shí)現(xiàn)面向服務(wù)的應(yīng)用(SOA)。它可以讓Bundles導(dǎo)出服務(wù),而其它的Bundles可以在不必了解源Bundles任何信息的情況下消費(fèi)這些導(dǎo)出的服務(wù)。由于OSGi具有隱藏真實(shí)的服務(wù)實(shí)現(xiàn)類的能力,所以它為面向服務(wù)的應(yīng)用提供了良好的類與接口的組合。

在OSGi框架中,源Bundle在OSGi容器中注冊POJO對象,該對象不必實(shí)現(xiàn)任何接口,也不用繼承任何超類,但它可以注冊在一個或多個接口下,并對外提供服務(wù)。目標(biāo)Bundle可以向OSGi容器請求注冊在某一接口下的服務(wù),一旦它發(fā)現(xiàn)該服務(wù),目標(biāo)Bundle就會將該服務(wù)綁定到這個接口,并能調(diào)用該接口中的方法。下面我們舉個例子,以便我們能更好理解與OSGi相關(guān)的這些概念。

5.1. 導(dǎo)出服務(wù)

在本小節(jié)中,我們將更新HelloService Bundle,以便它能把HelloServiceImpl類的對象導(dǎo)出為服務(wù),具體步驟如下:

1) 修改com.javaworld.sample.HelloService Bundle中的MANIFEST.MF文件,讓它導(dǎo)入org.osgi.framework包(譯者注,這一步我們已經(jīng)完成);

2) 新建Java類com.javaworld.sample.impl.HelloServiceActivator.java,其源代碼如清單7所示;

源代碼清單7. HelloServiceActivator.java

  1. public class HelloServiceActivator implements BundleActivator {  
  2. ServiceRegistrationhelloServiceRegistration;  
  3. public void start(BundleContext context)throws Exception {  
  4. HelloService helloService = newHelloServiceImpl();  
  5. helloServiceRegistration=context.registerService(HelloService.class.getName(), helloService, null);  
  6. }  
  7. public void stop(BundleContext context)throws Exception {  
  8. helloServiceRegistration.unregister();  
  9. }  
  10. }  
  11.  

請注意,在源Bundle中,我們應(yīng)使用BundleContext.registerService()方法導(dǎo)出服務(wù),這個方法帶三個參數(shù):

a) 該方法***個參數(shù)為您要注冊的服務(wù)的接口名稱。如果您想把您的服務(wù)注冊到多個接口下,您需要新建一個String數(shù)組存放這些接口名,然后把這個數(shù)組作為***個參數(shù)傳給registerService()方法。在示例代碼中,我們想把我們的服務(wù)導(dǎo)出到HelloServer接口名下;

b) 第二個參數(shù)是您要注冊的服務(wù)的實(shí)際Java對象。在示例代碼中,我們導(dǎo)出HelloServiceImpl類的對象,并將其作為服務(wù);

c) 第三個參數(shù)為服務(wù)的屬性,它是一個Dictionary對象。如果多個Bundle導(dǎo)出服務(wù)的接口名相同,目標(biāo)Bundle就可以使用這些屬性對源Bundle進(jìn)行過濾,找到它感興趣的服務(wù)。

3) ***,請修改HelloServiceBundle中的MANIFEST.MF文件,將Bundle-Activator屬性頭的值改為com.javaworld.sample.service.impl.HelloServiceActivator。

現(xiàn)在HelloService Bundle就可以導(dǎo)出HelloServiceImpl對象了。當(dāng)OSGi容器啟動HelloServiceBundle時,它會將控制權(quán)交給HelloServiceActivator.java類,HelloServiceActivator將HelloServiceImpl對象注冊為服務(wù)。下面,我們開始創(chuàng)建該服務(wù)的消費(fèi)者。

5.2. 導(dǎo)入服務(wù)

在本小節(jié)中,我們將修改上面開發(fā)的HelloWorld Bundle,以便讓它成為HelloService服務(wù)的消費(fèi)者。您主要需要修改HelloWorldBundle中的Activator.java代碼,修改后的代碼如源代碼清單8所示:

源代碼清單8. HelloWorld Bundle中的Activator.java

  1. packagecom.javaworld.sample.helloworld;  
  2.  
  3. importorg.osgi.framework.BundleActivator;  
  4. importorg.osgi.framework.BundleContext;  
  5. importorg.osgi.framework.ServiceReference;  
  6. importcom.javaworld.sample.service.HelloService;  
  7.  
  8. publicclass Activator implements BundleActivator {  
  9. ServiceReference helloServiceReference;  
  10. public void start(BundleContext context)throws Exception {  
  11. System.out.println("HelloWorld!!");  
  12. helloServiceReference=context.getServiceReference(HelloService.class.getName());  
  13. HelloService helloService=(HelloService)context.getService(helloServiceReference);  
  14. System.out.println(helloService.sayHello());  
  15.  
  16. }  
  17. public void stop(BundleContext context)throws Exception {  
  18. System.out.println("Goodbye World!!");  
  19. context.ungetService(helloServiceReference);  
  20. }  
  21. }  
  22.  

在上面的代碼中,BundleContext.getServiceReference()方法將為注冊在HelloService接口下的服務(wù)返回一個ServiceReference對象。如果存在多個HelloService服務(wù),該方法會返回排行***的服務(wù)(服務(wù)的排行是通過Constants.SERVICE_RANKING屬性指定的)。您一旦獲得ServiceReference對象,您就可以調(diào)用其BundleContext.getService()方法獲取真實(shí)的服務(wù)對象。

您可以參照運(yùn)行Bundle的方法運(yùn)行上面的示例應(yīng)用,請點(diǎn)擊“RunàRun…”菜單,并確保HelloWorld和HelloService這兩個Bundle被選中。當(dāng)您啟動HelloServiceBundle時,您會在控制臺上看到“InsideHelloServiceImple.sayHello()”,這個消息是由HelloServiceImpl.sayHello()方法打印出來的。

5.3. 創(chuàng)建服務(wù)工廠

在上節(jié)中,我們學(xué)會了如何使用OSGi框架新建一個Java對象,并把它注冊為一個服務(wù),然后讓其它的Bundle去消費(fèi)這個服務(wù)。如果您看一下HelloServiceActivator.start()方法,您會注意到我們在start()方法中新建了HelloServiceImpl類對象,然后將它注冊到HelloService接口名下。這樣注冊后,任何其它的Bundle在請求HelloService服務(wù)時,OSGi容器將返回同一對象。

在大多數(shù)情況下,這樣的實(shí)現(xiàn)方法沒有問題。但是,比如說我們要為每一個Bundle消費(fèi)者返回不同的HelloServiceImpl對象,再比如說,您的服務(wù)對象要提供的服務(wù)為打開一個數(shù)據(jù)庫連接,但并不是馬上就打開它,而是在真正需要的時候才打開這個數(shù)據(jù)庫連接。

對這兩種情況,我們的解決方法是,新建一個類實(shí)現(xiàn)ServiceFactory接口,并把該類的對象注冊為服務(wù),但并不是注冊實(shí)際的服務(wù)對象。一旦您完成這一步,其它Bundle在請求該服務(wù)時,您的ServiceFactory實(shí)現(xiàn)類將接管該請求,ServiceFactory會為每個Bundle新建一個服務(wù)對象,并將真實(shí)服務(wù)的創(chuàng)建時間延遲到有人真正需要該服務(wù)的時候。

下面我們將使用ServiceFactory更新我們上面開發(fā)的com.javaworld.sample.HelloServiceBundle,具體步驟如下:

1) 新建工廠 類HelloServiceFactory.java,源代碼如清單9所示。

源代碼清單9 . HelloServiceFactory.java

  1. public class HelloServiceFactory implements ServiceFactory{  
  2. private int usageCounter = 0;  
  3. public Object getService(Bundle bundle,ServiceRegistration registration) {  
  4. System.out.println("Create objectof HelloService for " + bundle.getSymbolicName());  
  5. usageCounter++;  
  6. System.out.println("Number ofbundles using service " + usageCounter);  
  7. HelloService helloService = newHelloServiceImpl();  
  8. return helloService;  
  9. }  
  10. public void ungetService(Bundle bundle,ServiceRegistration registration, Object service) {  
  11. System.out.println("Release objectof HelloService for " + bundle.getSymbolicName());  
  12. usageCounter--;  
  13. System.out.println("Number ofbundles using service " + usageCounter);  
  14. }  
  15. }  
  16.  

從上面的代碼中,我們可以看到,ServiceFactory接口定義了兩個方法:

a) getService()方法:當(dāng)某個Bundle***次使用BundleContext.getService(ServiceReference)方法請求一個服務(wù)對象時,OSGi框架會調(diào)用該方法。在源代碼清單9中,我們用這個方法為每個Bundle新建并返回不同的HelloServiceImpl對象,如果這個對象不是null,OSGi框架會緩存這個對象。如果同一個Bundle再次調(diào)用BundleContext.getService(ServiceReference)方法,OSGi將返回同一個服務(wù)對象。

b) ungetService()方法:當(dāng)Bundle釋放服務(wù)時,OSGi容器可以調(diào)用該方法銷毀服務(wù)對象。在源代碼清單9中,我們使用usageCounter變量來跟蹤服務(wù)的使用數(shù)目,并打印出該服務(wù)的客戶端數(shù)量。

2) 修改HelloService Bundle中的HelloServiceActivator.java的start()方法,讓它注冊到ServiceFactory接口名下,而不是注冊到HelloService接口。詳細(xì)代碼如清單10所示:

源代碼清單10. 修改后的HelloServiceBundle中的HelloServiceActivator.java

  1. package com.javaworld.sample.service.impl;  
  2. importorg.osgi.framework.BundleActivator;  
  3. importorg.osgi.framework.BundleContext;  
  4. importorg.osgi.framework.ServiceRegistration;  
  5.  
  6. importcom.javaworld.sample.helloservice.HelloServiceFactory;  
  7. importcom.javaworld.sample.service.HelloService;  
  8.  
  9. publicclass HelloServiceActivator implements BundleActivator {  
  10. ServiceRegistrationhelloServiceRegistration;  
  11. public void start(BundleContext context)throws Exception {  
  12. HelloServiceFactory helloServiceFactory= new HelloServiceFactory();  
  13. helloServiceRegistration=context.registerService(HelloService.class.getName(), helloServiceFactory,null);  
  14. }  
  15. public void stop(BundleContext context)throws Exception {  
  16. helloServiceRegistration.unregister();  
  17. }  
  18. }  
  19.  

現(xiàn)在,您可以試運(yùn)行示例代碼。您會注意到,當(dāng)HelloWorld Bundle啟動時,服務(wù)計(jì)數(shù)器變?yōu)?;當(dāng)HelloWorldBundle停止時,服務(wù)計(jì)數(shù)器的數(shù)目將變?yōu)?。

5.4. 跟蹤服務(wù)

在“OSGi服務(wù)”小節(jié),您學(xué)會了如何使用服務(wù)的接口名搜索服務(wù)。但如果有多個Bundle使用同一接口名注冊服務(wù),那會發(fā)生什么呢?這時,OSGi容器將返回排行***的服務(wù),即,返回注冊時那個SERVICE_RANKING屬性值***的服務(wù)。如果有多個服務(wù)的排行值相等,那么OSGi容器將返回PID值最小的那個服務(wù)。

但是,如果您的服務(wù)消費(fèi)者需要了解某一接口下的服務(wù)對象何時注冊、何時取消注冊,這時,您應(yīng)使用ServiceTracker類。下面,我們看看如何使用服務(wù)跟蹤器來修改我們的示例代碼,具體步驟如下。

1) 修改HelloWorldBundle的MANIFEST.MF文件,讓它導(dǎo)入org.osgi.util.tracker包;

2) 新建類HelloServiceTracker.java,其源代碼參見清單11。

源代碼清單11.HelloServiceTracker.java

  1. public class HelloServiceTracker extends ServiceTracker {  
  2.  
  3.     public HelloServiceTracker(BundleContext context) {  
  4.  
  5.         super(context, HelloService.class.getName(),null);  
  6.  
  7.     }  
  8.  
  9.     public Object addingService(ServiceReference reference) {  
  10.  
  11.         System.out.println("Inside HelloServiceTracker.addingService " + reference.getBundle());  
  12.  
  13.         return super.addingService(reference);  
  14.  
  15.     }  
  16.  
  17.     public void removedService(ServiceReference reference, Object service) {  
  18.  
  19.         System.out.println("Inside HelloServiceTracker.removedService " + reference.getBundle());  
  20.  
  21.         super.removedService(reference, service);  
  22.  
  23.     }  
  24.  
  25. }  
  26.  

在上面的HelloSerivceTracker類的構(gòu)造函數(shù)中,您可以看到,我們把HelloService接口名傳入其父類中,這相當(dāng)于說,HelloServiceTracker應(yīng)跟蹤注冊到HelloService接口名下的所有服務(wù),HelloServiceTracker繼承自ServiceTracker類,實(shí)現(xiàn)了下面兩個方法:

a) addingService()方法:當(dāng)Bundle使用接口名注冊服務(wù)時,該方法將會被調(diào)用;

b)removedService()方法:當(dāng)Bundle取消注冊某個接口名下的服務(wù)時,該方法將會被調(diào)用。

3) 用HelloServiceTracker類更新我們的Activator.java類,以便讓它來管理服務(wù),而不是直接去查找它們,源代碼請參見清單12。

源代碼清單12. 使用了HelloServiceTracker的Activator.java

  1. public class Activator implements BundleActivator {  
  2.  
  3.     HelloServiceTracker helloServiceTracker;  
  4.  
  5.     public void start(BundleContext context) throws Exception {  
  6.  
  7.         System.out.println("Hello World!!");  
  8.  
  9.         helloServiceTracker= new HelloServiceTracker(context);  
  10.  
  11.         helloServiceTracker.open();  
  12.  
  13.         HelloService helloService = (HelloService)helloServiceTracker.getService();  
  14.  
  15.         System.out.println(helloService.sayHello());  
  16.  
  17.    
  18.  
  19.     }  
  20.  
  21.     public void stop(BundleContext context) throws Exception {  
  22.  
  23.         System.out.println("Goodbye World!!");  
  24.  
  25.         helloServiceTracker.close();  
  26.  
  27.     }  
  28.  
  29. }  
  30.  

我們看到,在初始的start()方法中,我們首先新建一個HelloServiceTracker對象,然后要求這個對象跟蹤HelloService接口下的服務(wù)。這時,我們可以調(diào)用getService()方法獲得HelloService對象。

如果您試運(yùn)行上面的示例代碼,您會注意到,在啟動或停止HelloSerivceBundle時,OSGi容器都會調(diào)用HelloServiceTracker對象的addingService()方法或removedService()方法。

【編輯推薦】

  1. OSGi依賴性管理:Bundle訪問域
  2. OSGi Bundle之Hello World
  3. OSGi是什么:Java語言的動態(tài)模塊系統(tǒng)
  4. OSGi 4.2將于8月發(fā)布 新版特性預(yù)覽
  5. Spring Tool Suite開始支持OSGi
責(zé)任編輯:yangsai 來源: Carl的博客
相關(guān)推薦

2012-06-07 10:31:12

SOA架構(gòu)設(shè)計(jì)原則

2009-09-29 14:20:05

OSGiContactDAO

2009-11-10 10:15:16

SOA面向服務(wù)

2009-11-23 12:39:26

2009-06-22 13:41:58

FaceletsJSF組件

2021-06-03 18:42:26

Redis集群故障

2019-03-18 05:02:30

高并發(fā)京東架構(gòu)

2010-01-08 09:13:28

2010-05-31 10:43:52

李彥宏

2009-09-28 13:32:39

OSGi入門

2009-06-18 15:24:08

Spring OSGi

2025-02-10 02:20:00

微服務(wù)SOA架構(gòu)

2009-06-01 11:20:21

OSGi服務(wù)規(guī)范非贏利機(jī)構(gòu)

2018-12-11 14:20:14

Python技巧編程語言

2009-06-11 09:20:15

GlassFish是什OSGi

2022-05-13 07:22:39

攜程微服務(wù)SOA

2009-09-15 13:33:38

SOA架構(gòu)

2012-03-14 11:33:31

ibmdw

2009-06-01 10:28:03

SpringOSGi整合

2012-11-01 14:35:53

SOAWeb安全Web服務(wù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號