osgi實戰項目(osmp)一步一步玩轉osgi之服務發佈和引用(4)

 

今天主要講一下在osgi環境下的服務註冊、和服務引用。java

 

其實osgi只是一個java動態化、模塊化的一系列規範,根據不一樣廠商制定了不一樣的規範,如Felix和Equinox則分別是Apache和Eclipse開源社區給出的標準規範的實現!而osgi的魅力也在於動態化和模塊化,我我的認爲要實現動態化最簡單的就是經過classload動態加載。我我的理解而已,osgi只是在傳統開發的基礎上抽象了一個bundle組件的概念,每個bundle組件都有本身的生命週期,bundle實現動態化是基於bundle classloader實現的。理論性的東西我不想講太多,你們能夠去看一下osgi基礎方面的東西,如bundle生命週期,bundle classloader等內容。而服務的註冊,服務的引用等內容偏偏是bundle生命週期最好的詮釋!spring

 

先說一下osgi環境下的服務註冊,其實這部份內容在第二講的時候已經大概說過一點兒,此次咱們講解一下傳統的osgi服務註冊和使用框架的方式來註冊等。apache

 

 一個bundle被部署到osgi容器裏有幾個最要的階段也能夠稱之爲bundle的生命週期,主要包括 INSTALLED(調用BundleContext.installBundle()後,會建立一個INSTALLED狀態的bundle)、RESOLVED(若是其所依賴的全部bundle都存在,即解析成功,轉到RESOLVED狀態)、STARTING(當開始執行BundleActivator.start(),則處於STARTING狀態)、ACTIVE(當執行BundleActivator.start()成功,則轉到ACTIVE狀態)、STOPPING(當開始執行BundleActivator.stop(),則處於STOPPING狀態)、UNINSTALLED(INSTALLED狀態的bundle能夠被卸載,轉到UNINSTALLED狀態)。框架

能夠看到一個bundle的整個生命週期都離不開BundleActivatorBundleContext 這兩個類。maven

 

BundleContext:Bundle上下文,主要功能是與OSGI容器交互,包括服務的註冊,監聽器的註冊,獲取osgi下全部發布的服務,服務的引用等功能。建議你們好好的看一下這個類。ide

BundleActivator:BundleActivator是osgi提供的一個獲取BundleContext的接口,同時提供bundle啓動和中止的處理方法。模塊化

 

知道這兩個類咱們就能夠實現BundleActivator 在bundle啓動的時候經過BundleContext註冊服務到osgi容器裏以供其它bundle調用了測試


實現一個自定義的BundleActivator :ui

 

public class HelloServiceActivator implements BundleActivator {
	ServiceRegistration serviceRegistration;
	@Override
	public void start(BundleContext context) throws Exception {
		HelloService helloService = new HelloServiceImpl();
		serviceRegistration = context.registerService(HelloService.class.getName(), helloService, null);
	}

	@Override
	public void stop(BundleContext context) throws Exception {
		serviceRegistration.unregister();
	}

}

 

在這個bundle啓動的時候咱們經過實現BundleActivator裏的start方法 實例化一個服務類並經過BundleContext的registerService註冊到osgi容器裏,分別傳入服務名稱,服務實例,服務別名(能夠理解爲這個的tag標籤),經過stop方法註銷到這個服務。插件

 

完成這一步後咱們還在MANIFEST.MF(Bundle元數據描述文件,定義此Bundle依賴的jar包,導入和導出的包等基礎元數據)定義Bundle-Activator爲咱們本身的Activator

Bundle-Activator:com.osmp.demo.HelloServiceActivator

 

 這樣咱們在將此bundle部署到osgi容器的時候在bundle啓動的時候就會將HelloService註冊到osgi容器裏供別的bundle服務調用。再簡單的說一下bundle服務的引用。與發佈基本相同,在啓動的時候經過start方法獲取到bundle上下文,經過BundleContext獲取ServiceReference 服務引用,再經過此類獲取咱們須要的服務引用,代碼以下:

 

public class Activator implements BundleActivator {
ServiceReference helloServiceReference;
	public void start(BundleContext context) throws Exception {
		System.out.println("Hello World!!");
		helloServiceReference=context.getServiceReference(HelloService.class.getName());
		HelloService helloService=(HelloService)context.getService(helloServiceReference);
		System.out.println(helloService.sayHello());
	}
	public void stop(BundleContext context) throws Exception {
		System.out.println("Goodbye World!!");
		context.ungetService(helloServiceReference);
	}
}

 

 以上部分寫到一大半的時候,想找兩個例子,結果發現 http://longdick.iteye.com/blog/457310 這篇文章講的很好,你們能夠看一下,我也就再也不專門講解了。

 

我就說一下在osmp裏是怎麼實現服務的註冊和服務的發現和服務路由的。

 

osmp裏服務的發佈咱們是經過spring-dm來發布的,代碼很簡單,

 spring配置文件裏引入spring-osgi的schema,經過 <osgi:service>標籤來將服務發佈到osgi容器裏,配置文件以下:

 

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:osgi="http://www.springframework.org/schema/osgi"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
		http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi-1.2.xsd">

	<context:component-scan base-package="com.osmp.demo.service">
	</context:component-scan>
	
	
	<bean id="jdbcDao" class="com.osmp.jdbc.support.JdbcDao"></bean>
	
	<bean id="osmp.demo.service" class="com.osmp.demo.service.TestServiceImpl" />
	<osgi:service interface="com.osmp.intf.define.service.BaseDataService"
		ref="osmp.demo.service">
		<osgi:service-properties>
			<entry key="name" value="osmp-demo" />
			<entry key="mark" value="測試DEMO" />
		</osgi:service-properties>
	</osgi:service>

</beans>

 

pom.xml 裏依賴

 

<dependency>
            <groupId>org.springframework.osgi</groupId>
            <artifactId>spring-osgi-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.osgi</groupId>
            <artifactId>org.osgi.core</artifactId>
 </dependency>

 

pom.xml將工程打包爲bundle,須要使用到 maven-bundle-plugin 這個插件:

 

<build>
		<plugins>
			<plugin>
				<groupId>org.apache.felix</groupId>
				<artifactId>maven-bundle-plugin</artifactId>
				<extensions>true</extensions>
				<configuration>
					<instructions>
						<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
						<Export-Package></Export-Package>
						<Import-Package>
							org.springframework.aop,
							org.springframework.aop.framework,
							org.springframework.cglib,
							org.springframework.cglib.proxy,
							org.springframework.cglib.core,
							org.springframework.cglib.reflect,
							org.aopalliance.aop,
							org.aopalliance.intercept,
							*;resolution:=optional
						</Import-Package>
					</instructions>
				</configuration>
			</plugin>
		</plugins>
	</build>

 

 

 PS:

一、配置文件引入spring-osgi  xmlns:osgi="http://www.springframework.org/schema/osgi" http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi-1.2.xsd

二、osgi:service-properties 標籤對應 上面講到的context.registerService()方法的第三個參數。個人理解是給這個服務打上tag標籤,以k/v鍵值對的形式。

三、maven-bundle-plugin打bundle時,我這裏使用的servicemix做爲osgi容器,已經集成了spring,此時須要將spring的包顯示的引入進來。這裏比較坑的是我本來覺得經過*;resolution:=optional能自動的將須要依賴的包給import進來,可是試過屢次發現,只有在代碼裏顯示的import的包纔會被自動的引進去,如配置文件裏依賴的包是不會自動的import進來的,並且只能一級一級的import進來。

四、spring-dm 服務引用經過<osgi:reference>這裏不做詳講。

 

上面的例子能夠查看osmp-demo源碼!!!!

相對來講經過spring-dm的方式來發布服務比上面經過BundleContext的方式前進了一大步,此外還能夠經過blueprint的方式來發布服務,感興趣的本身百度。
相關文章
相關標籤/搜索