2008-07-22

基于Spring-OSGi应用开发杂谈

关键字: spring osgi

      在Spring大行其道的今天,网络上随便找一款Java Web应用很难说它的身上没有Spring的影子,前些日子说到OSGi在系统模块化封装、系统热插拔等方面有其独特的优势,那么如果在Spring的Ioc和AOP的支撑下,如果可以将Spring与OSGi结合在一起那会怎么样呢:
1). 能够更好的分离应用逻辑与模块
2). 具备同时部署一个模块的多个版本的功能
3). 具备动态查找,使用其他系统模块功能的能力
4). 在运行时动态部署,升级和卸载模块的能力
5). 在Spring框架下,实现模块之间实例化、配置、集成和装饰组件的能力
6). 在简单的编程模式下快速开发OSGi应用

 

基于对OSGi在软件开发中的优势考虑,Spring的设计开发团队为了能够支持OSGi的开发,在其架构中内置了Spring-OSGi模块,Spring’OSGi的目标是使得写基于Spring的应用程序尽可能的容易,这些应用可以部署到OSGi的执行环境中,并可有效利用OSGi框架所提供的服务。通过在易用、强大的Spring框架上构建应用程序,Spring对OSGi的支持也使得开发这样的基于OSGi的应用更加简单、更加高效。Spring’s OSGi的目标并不是提供一个通用的模型以支持任意的基于OSGi的应用程序开发,但是某些OSGi的开发者肯定能够发现Spring模型吸引人之处,并采纳它。目前已经存在的OSGi的bundles以及它们所export的任何服务都可以轻松的集成到使用SpringOSGi支撑的应用中,就象是Spring已经存在的配置项。

 

Spring OSGi定位于OSGi R4及以上版本,JDK1.3及以上版本。这个规范假设读者已经具有一定的Spring及OSGi的知识。参见介绍白皮书“OSGi for Spring developers”以及“Spring for OSGi developers”。

OSGi中的开发单元(以及模块单元)是bundle。OSGi中所说的bundle有三种稳定状态:installed,resolved,active。而在一个Bundle处于Active状态中时,说明该Bundle已经处于可用状态。

 

为了能够能够简明扼要的说明Spring-OSGi的结合使用,因此我们建立一个小小的test工程:
1). 在Eclipse中利用m2eclipse插件建立一个Maven工程(内容如下):

 

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.danlley.osgi.spring.test</groupId>
  <artifactId>osgi_spring_test</artifactId>
  <name/>
  <version>0.0.1-SNAPSHOT</version>
  <description/>
</project>

 

 

 

 2). 利用PDE Tools将工程转化为一个Plug-in Projects。转化成功后会在系统中增加一个目录和两个文件,一个是build.properties,一个是在新增加的目录META-INF下的MANIFEST.MF文件。


 a. MANIFEST.MF文件内容:
  ----------------------------------------
  Manifest-Version: 1.0
  Bundle-ManifestVersion: 2
  Bundle-Name: osgi_spring_test
  Bundle-SymbolicName: osgi_spring_test
  Bundle-Version: 1.0.0
  ----------------------------------------


 b. build.properties文件内容:
  ----------------------------------------
  source.. = src/main/java/,\
      src/test/java/,\
      src/main/resources/,\
      src/test/resources/
  bin.includes = META-INF/,\
          .
  ----------------------------------------


 c. 编写示例代码:

 MyFirstSpringServiceImpl

package org.danlley.osgi.impl;

import org.danlley.osgi.service.MyFirstSpringService;

public class MyFirstSpringServiceImpl implements MyFirstSpringService {
	public MyFirstSpringServiceImpl() {
		System.out.println("MyFirstSpringService>> constructor initialized!");
		sayHelloToEveryBody();
	}

	public void sayHelloToEveryBody() {
		System.out.println("method sayHelloToEveryBody() has been called.");
		System.out.println("sayHelloToEveryBody>> Hello Everyone!");
	}
}

 

 

 MyFirstSpringService

 

package org.danlley.osgi.service;

public interface MyFirstSpringService {
	public void sayHelloToEveryBody();
}

 

 

d. 在META-INF目录下建立Spring目录增加文件:

fooservice.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
	<bean name="mySpringService" class="org.danlley.osgi.impl.MyFirstSpringServiceImpl" />
</beans>

 

 

fooservice-osgi.xml

<?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: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/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd">
	<osgi:service id="mySpringServiceOsgi" ref="mySpringService"
		interface="org.danlley.osgi.service.MyFirstSpringService" />
</beans>

 

e. 修改POM文件:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.danlley.osgi.spring.test</groupId>
  <artifactId>osgi_spring_test</artifactId>
  <name/>
  <version>0.0.1-SNAPSHOT</version>
  <description/>
	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>2.5.1</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>2.5.1</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>2.5.1</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-beans</artifactId>
			<version>2.5.1</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>2.0</version>
				<configuration>
					<source>1.5</source>
					<target>1.5</target>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-jar-plugin</artifactId>
				<configuration>
					<archive>
						<manifestFile>
							META-INF/MANIFEST.MF
						</manifestFile>
					</archive>
				</configuration>
			</plugin>
		</plugins>
	</build>
	<pluginRepositories>
		<pluginRepository>
			<id>maven-repo</id>
			<name>maven repo</name>
			<url>http://repo1.maven.org/maven2/</url>
		</pluginRepository>
		<pluginRepository>
			<id>agilejava</id>
			<url>http://agilejava.com/maven/</url>
		</pluginRepository>
	</pluginRepositories>
	<repositories>
		<repository>
			<id>eclipse-repository</id>
			<name>Eclipse Repository</name>
			<url>http://repo1.maven.org/eclipse/</url>
		</repository>
		<repository>
			<id>safehaus-repository</id>
			<name>Safehaus Repository</name>
			<url>http://m2.safehaus.org</url>
		</repository>
		<repository>
			<id>spring-ext</id>
			<name>Spring External Dependencies Repository</name>
			<url>
				http://springframework.svn.sourceforge.net/svnroot/springframework/repos/repo-ext/
			</url>
		</repository>
		<repository>
			<id>spring-release</id>
			<name>Spring Portfolio Release Repository</name>
			<url>
				http://s3.amazonaws.com/maven.springframework.org/release
			</url>
		</repository>
		<repository>
			<id>spring-external</id>
			<name>Spring Portfolio Release Repository</name>
			<url>
				http://s3.amazonaws.com/maven.springframework.org/external
			</url>
		</repository>
		<repository>
			<id>spring-milestone</id>
			<name>Spring Portfolio Milestone Repository</name>
			<url>
				http://s3.amazonaws.com/maven.springframework.org/milestone
			</url>
		</repository>
		<repository>
			<id>i21-s3-osgi-repo</id>
			<name>i21 osgi artifacts repo</name>
			<snapshots>
				<enabled>true</enabled>
			</snapshots>
			<url>
				http://s3.amazonaws.com/maven.springframework.org/osgi
			</url>
		</repository>
	</repositories>
</project>

 

 

 f. 配置一些支持OSGi运行环境的一些Bundle
  -----------------------------------------------------------------------------------------
  Framework is launched.

  id State       Bundle
  0 ACTIVE      org.eclipse.osgi_3.3.2.R33x_v20080105
  6 ACTIVE      org.eclipse.osgi.services_3.1.200.v20070605
  30 ACTIVE      org.apache.commons.logging_1.0.4.v200706111724
  34 ACTIVE      org.apache.commons.logging_1.0.4
  35 ACTIVE      org.springframework.bundle.spring_2.5.2.v200803070100
  36 ACTIVE      org.springframework.osgi.backport.util.concurrent_3.0.0
  37 ACTIVE      org.eclipse.equinox.ds_1.0.0.qualifier
  38 ACTIVE      org.springframework.bundle.osgi.core_1.0.1.v200803070100
  39 ACTIVE      org.springframework.bundle.osgi.io_1.0.1.v200803070100
  40 ACTIVE      osgi_spring_test_1.0.0
  41 ACTIVE      org.springframework.bundle.osgi.extender_1.0.1.v200803070100
  42 ACTIVE      org.springframework.binding_1.0.3.1
  -----------------------------------------------------------------------------------------
  配置后MANIFEST.MF文件内容如下:
  ------------------------------------------------------------
  Manifest-Version: 1.0
  Bundle-ManifestVersion: 2
  Bundle-Name: osgi_spring_test
  Bundle-SymbolicName: osgi_spring_test
  Bundle-Version: 1.0.0
  Require-Bundle: org.eclipse.osgi,
   org.springframework.bundle.osgi.core,
   org.springframework.bundle.osgi.io,
   org.springframework.bundle.osgi.extender,
   org.springframework.bundle.spring,
   org.springframework.osgi.backport.util.concurrent,
   org.apache.commons.logging,
   org.springframework.binding,
   org.eclipse.equinox.ds,
   org.eclipse.osgi.services
  ------------------------------------------------------------

 


3. 运行结果:


 -----------------------------------------------------------------------------------------
 osgi> Jul 22, 2008 10:54:39 AM org.springframework.osgi.extender.internal.ContextLoaderListener start
 INFO: Starting org.springframework.osgi.extender bundle v.[1.0.1.v200803070100]
 Jul 22, 2008 10:54:40 AM org.springframework.osgi.extender.internal.ContextLoaderListener addAnnotationBPP
 INFO: Disabled automatic Spring-DM annotation processing; [ org.springframework.osgi.extender.annotation.auto.processing=null]
 Jul 22, 2008 10:54:40 AM org.springframework.context.support.AbstractApplicationContext prepareRefresh
 INFO: Refreshing org.springframework.osgi.context.support.OsgiBundleXmlApplicationContext@482923 : display name [OsgiBundleXmlApplicationContext(bundle=osgi_spring_test, config=osgibundle:/META-INF/spring/*.xml)]; startup date [Tue Jul 22 10:54:40 CST 2008]; root of context hierarchy
 Jul 22, 2008 10:54:40 AM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
 INFO: Loading XML bean definitions from URL [bundleentry://40/META-INF/spring/fooservice-osgi.xml]
 Jul 22, 2008 10:54:41 AM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
 INFO: Loading XML bean definitions from URL [bundleentry://40/META-INF/spring/fooservice.xml]
 Jul 22, 2008 10:54:41 AM org.springframework.context.support.AbstractApplicationContext obtainFreshBeanFactory
 INFO: Bean factory for application context [org.springframework.osgi.context.support.OsgiBundleXmlApplicationContext@482923]: org.springframework.beans.factory.support.DefaultListableBeanFactory@18ce14a
 Jul 22, 2008 10:54:41 AM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
 INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@18ce14a : defining beans [mySpringServiceOsgi,mySpringService]; root of factory hierarchy
 MyFirstSpringService>> constructor initialized!<-----------------关键信息开始
 method sayHelloToEveryBody() has been called.
 sayHelloToEveryBody>> Hello Everyone!<-----------------关键信息结束
 Jul 22, 2008 10:54:41 AM org.springframework.osgi.service.exporter.support.OsgiServiceFactoryBean registerService
 INFO: Publishing service under classes [{org.danlley.osgi.service.MyFirstSpringService}]
 Jul 22, 2008 10:54:41 AM org.springframework.osgi.context.support.AbstractOsgiBundleApplicationContext publishContextAsOsgiServiceIfNecessary
 INFO: Publishing application context with properties (org.springframework.context.service.name=osgi_spring_test)
 -----------------------------------------------------------------------------------------


下面,我们对刚才运行的Spring-osgi示例进行分析和说明,缺省情况下,Spring将使用在META-INF/spring文件夹中的所有以“.xml”为扩展名的文档,作为application context的配置定义。当然,这个缺省设置是可以在manifest header中重写的,关于这个话题不是我们这里的重点,不过我会在以后的文章中涉及到这个议题。

接下来编写测试用例:

 

package org.danlley.osgi.impl;

import junit.framework.TestCase;

import org.danlley.osgi.service.MyFirstSpringService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

public class MyFirstSpringServiceImplTest extends TestCase {
	private ApplicationContext ac;

	public void setUp() {
		ac = new FileSystemXmlApplicationContext(
				"META-INF/spring/fooservice.xml");
	}

	public void testSayHelloToEveryBody() {
		MyFirstSpringService _service=(MyFirstSpringService)ac.getBean("mySpringService");
		System.out.println("++++++++++++++++++++++++++++++++++++");
		_service.sayHelloToEveryBody();
		System.out.println("++++++++++++++++++++++++++++++++++++");
	}

}

 

运行测试用例,运行结果如下:

 

-----------------------------------------------------------------------------------
2008-7-22 15:13:47 org.springframework.context.support.AbstractApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.FileSystemXmlApplicationContext@108786b : display name [org.springframework.context.support.FileSystemXmlApplicationContext@108786b]; startup date [Tue Jul 22 15:13:47 CST 2008]; root of context hierarchy
2008-7-22 15:13:47 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from file [D:\workspace\osgi_spring_test\META-INF\spring\fooservice.xml]
2008-7-22 15:13:47 org.springframework.context.support.AbstractApplicationContext obtainFreshBeanFactory
信息: Bean factory for application context [org.springframework.context.support.FileSystemXmlApplicationContext@108786b]: org.springframework.beans.factory.support.DefaultListableBeanFactory@37fb1e
2008-7-22 15:13:47 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
信息: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@37fb1e : defining beans [mySpringService,mySecondService]; root of factory hierarchy
MyFirstSpringService>> constructor initialized!
method sayHelloToEveryBody() has been called.
sayHelloToEveryBody>> Hello Everyone!
second service was called! <-----------------关键信息结束
++++++++++++++++++++++++++++++++++++
method sayHelloToEveryBody() has been called.
sayHelloToEveryBody>> Hello Everyone!
++++++++++++++++++++++++++++++++++++<-----------------关键信息结束
-----------------------------------------------------------------------------------

 

 

4. 实例扩展: 

由于我们在这里使用的是硬加载的方式,因此不失一般性,在增加一个Bean。代码如下:

MySecondSpringServiceImpl

package org.danlley.osgi.impl;

import org.danlley.osgi.service.MyFirstSpringService;
import org.danlley.osgi.service.MySecondSpringService;

public class MySecondSpringServiceImpl implements MySecondSpringService {
	MyFirstSpringService mySpringService;

	public MySecondSpringServiceImpl() {
		System.out.println("second service was called! ");
	}

	public void helloWatcher() {
		if (mySpringService == null) {
			System.out.println("initialization failed");
		} else {
			System.out.println("-------------------------------------");
			mySpringService.sayHelloToEveryBody();
			System.out.println("-------------------------------------");
		}
	}

	public MyFirstSpringService getMySpringService() {
		return mySpringService;
	}

	public void setMySpringService(MyFirstSpringService mySpringService) {
		this.mySpringService = mySpringService;
	}
}

 

MySecondSpringService

package org.danlley.osgi.service;

public interface MySecondSpringService {
	public void helloWatcher();
}

 

 

 修改相应配置文件,内容如下:

 fooservice.xml

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
	<bean name="mySpringService" class="org.danlley.osgi.impl.MyFirstSpringServiceImpl" />
	<bean name="mySecondService" class="org.danlley.osgi.impl.MySecondSpringServiceImpl" >
		<property name="mySpringService">
			<ref bean="mySpringService"/>
		</property>
	</bean>
</beans>

 

 

fooservice-osgi.xml

 

<?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: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/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd">
	<osgi:service id="mySpringServiceOsgi" ref="mySpringService"
		interface="org.danlley.osgi.service.MyFirstSpringService" />
	<osgi:service id="mySecondServiceOsgi" ref="mySecondService"
		interface="org.danlley.osgi.service.MySecondSpringService" />
</beans>

 

为MySecondSpringService编写测试用例:

package org.danlley.osgi.impl;

import junit.framework.TestCase;

import org.danlley.osgi.service.MySecondSpringService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

public class MySecondSpringServiceImplTest extends TestCase {
	private ApplicationContext ac;

	public void setUp() {
		ac = new FileSystemXmlApplicationContext(
				"META-INF/spring/fooservice.xml");
	}
	public void testHelloWatcher() {
		try {
			MySecondSpringService _service=(MySecondSpringService)ac.getBean("mySecondService");
			System.out.println("++++++++++++++++++++++++++++++++++++");
			_service.helloWatcher();
			System.out.println("++++++++++++++++++++++++++++++++++++");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

 

 

 

运行结果如下:
 -----------------------------------------------------------------------------------------
 2008-7-22 15:16:31 org.springframework.context.support.AbstractApplicationContext prepareRefresh
 信息: Refreshing org.springframework.context.support.FileSystemXmlApplicationContext@1add2dd : display name [org.springframework.context.support.FileSystemXmlApplicationContext@1add2dd]; startup date [Tue Jul 22 15:16:31 CST 2008]; root of context hierarchy
 2008-7-22 15:16:31 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
 信息: Loading XML bean definitions from file [D:\workspace\osgi_spring_test\META-INF\spring\fooservice.xml]
 2008-7-22 15:16:31 org.springframework.context.support.AbstractApplicationContext obtainFreshBeanFactory
 信息: Bean factory for application context [org.springframework.context.support.FileSystemXmlApplicationContext@1add2dd]: org.springframework.beans.factory.support.DefaultListableBeanFactory@1543c88
 2008-7-22 15:16:31 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
 信息: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1543c88 : defining beans [mySpringService,mySecondService]; root of factory hierarchy
 MyFirstSpringService>> constructor initialized!
 method sayHelloToEveryBody() has been called.
 sayHelloToEveryBody>> Hello Everyone!
 second service was called!
 ++++++++++++++++++++++++++++++++++++
 -------------------------------------
 method sayHelloToEveryBody() has been called.
 sayHelloToEveryBody>> Hello Everyone!
 -------------------------------------
 ++++++++++++++++++++++++++++++++++++
 -----------------------------------------------------------------------------------------

 

 

 5. 客户端Bundle调用

从上面的验证可以看出,我们配置的Spring是没有问题的,那么是不是当前的Bundle已经可以被其他的Bundle使用了呢,让我们继续做一些小手术。


1). 发布包路径,发布成功后的MANIFEST.MF配置文件内容如下

 ---------------------------------------------------------------
 Manifest-Version: 1.0
 Bundle-ManifestVersion: 2
 Bundle-Name: osgi_spring_test
 Bundle-SymbolicName: osgi_spring_test
 Bundle-Version: 1.0.0
 Require-Bundle: org.eclipse.osgi,
  org.springframework.bundle.osgi.core,
  org.springframework.bundle.osgi.io,
  org.springframework.bundle.osgi.extender,
  org.springframework.bundle.spring,
  org.springframework.osgi.backport.util.concurrent,
  org.apache.commons.logging,
  org.springframework.binding,
  org.eclipse.equinox.ds,
  org.eclipse.osgi.services
 Export-Package: org.danlley.osgi.service
 ---------------------------------------------------------------

 

2). 建立一个客户端Bundle,大体跟上面建立工程的过程类似,这里就不再详述。

 

3). 在新建工程中增加类如下:

Activator

package org.danlley.osgi.spring.client;

import org.danlley.osgi.service.MyFirstSpringService;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;

public class Activator implements BundleActivator {

	public void start(final BundleContext context) throws Exception {
		System.out.println("开始启动bundle。。。。");
		Thread t = new Thread(new Runnable() {
			boolean registered = false;
			ServiceReference ref = null;
			int safety = 0;

			public void run() {
				while (!registered && safety < 10) {
					System.out.println("Trying to get the reference to FooService");
					ref = context.getServiceReference(MyFirstSpringService.class.getName());
					if (ref != null) {
						break;
					}
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
					}
					safety++;
				}
				if (ref == null) {
					System.out.println("Service " + MyFirstSpringService.class.getName() + " is not registered");
				} else {
					System.out.println("Found service");
					MyFirstSpringService service = (MyFirstSpringService) context.getService(ref);
					System.out.println("Retrieved service: " + service.getClass().getName());
					System.out.println("||||||||||||||||||||||||||||||||||||||||||||||");
					service.sayHelloToEveryBody();
					System.out.println("||||||||||||||||||||||||||||||||||||||||||||||");
				}
			}
		});
		t.start();
	}

	public void stop(BundleContext context) throws Exception {
		System.out.println("Stopping service");
	}
}

 

如果前面没有发布包路径,在这里可能会有些小麻烦。

 


4). 修改客户端工程的MANIFEST.MF配置文件
 ---------------------------------------------------------------------------------
 Manifest-Version: 1.0
 Bundle-ManifestVersion: 2
 Bundle-Name: osgi_spring_client
 Bundle-SymbolicName: osgi_spring_client
 Bundle-Version: 1.0.0
 Require-Bundle: org.eclipse.osgi,
  org.springframework.bundle.osgi.core,
  org.springframework.bundle.osgi.io,
  org.springframework.bundle.osgi.extender,
  org.springframework.bundle.spring,
  org.springframework.osgi.backport.util.concurrent,
  org.apache.commons.logging,
  org.springframework.binding,
  org.eclipse.equinox.ds,
  org.eclipse.osgi.services,
  osgi_spring_test
 Bundle-Activator: org.danlley.osgi.spring.client.Activator
 ---------------------------------------------------------------------------------

5). 运行客户端工程, 结果如下:
------------------------------------------------------------------------------------------------------------
osgi> Jul 22, 2008 4:11:20 PM org.springframework.osgi.extender.internal.ContextLoaderListener start
INFO: Starting org.springframework.osgi.extender bundle v.[1.0.1.v200803070100]
Jul 22, 2008 4:11:20 PM org.springframework.osgi.extender.internal.ContextLoaderListener addAnnotationBPP
INFO: Disabled automatic Spring-DM annotation processing; [ org.springframework.osgi.extender.annotation.auto.processing=null]
Jul 22, 2008 4:11:20 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.osgi.context.support.OsgiBundleXmlApplicationContext@122cdb6 : display name [OsgiBundleXmlApplicationContext(bundle=osgi_spring_test, config=osgibundle:/META-INF/spring/*.xml)]; startup date [Tue Jul 22 16:11:20 CST 2008]; root of context hierarchy
开始启动bundle。。。。
Trying to get the reference to FooService
Jul 22, 2008 4:11:20 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from URL [bundleentry://43/META-INF/spring/fooservice-osgi.xml]
Jul 22, 2008 4:11:20 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from URL [bundleentry://43/META-INF/spring/fooservice.xml]
Jul 22, 2008 4:11:20 PM org.springframework.context.support.AbstractApplicationContext obtainFreshBeanFactory
INFO: Bean factory for application context [org.springframework.osgi.context.support.OsgiBundleXmlApplicationContext@122cdb6]: org.springframework.beans.factory.support.DefaultListableBeanFactory@18941f7
Jul 22, 2008 4:11:20 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@18941f7 : defining beans [mySpringServiceOsgi,mySecondServiceOsgi,mySpringService,mySecondService]; root of factory hierarchy
MyFirstSpringService>> constructor initialized!
method sayHelloToEveryBody() has been called.
sayHelloToEveryBody>> Hello Everyone!
Jul 22, 2008 4:11:20 PM org.springframework.osgi.service.exporter.support.OsgiServiceFactoryBean registerService
INFO: Publishing service under classes [{org.danlley.osgi.service.MyFirstSpringService}]
second service was called!
Jul 22, 2008 4:11:20 PM org.springframework.osgi.service.exporter.support.OsgiServiceFactoryBean registerService
INFO: Publishing service under classes [{org.danlley.osgi.service.MySecondSpringService}]
Jul 22, 2008 4:11:20 PM org.springframework.osgi.context.support.AbstractOsgiBundleApplicationContext publishContextAsOsgiServiceIfNecessary
INFO: Publishing application context with properties (org.springframework.context.service.name=osgi_spring_test)
Trying to get the reference to FooService
Found service
Retrieved service: org.danlley.osgi.impl.MyFirstSpringServiceImpl
||||||||||||||||||||||||||||||||||||||||||||||<-------------------------------- 调用开始
method sayHelloToEveryBody() has been called.
sayHelloToEveryBody>> Hello Everyone!
||||||||||||||||||||||||||||||||||||||||||||||<-------------------------------- 调用结束
------------------------------------------------------------------------------------------------------------

跟我们预期的结果一样,成功运行并调用了我们在osgi_spring_test_1.0.0中定义的Spring应用。

 

 

 

结束!

 

参考资料:http://www.springframework.org/

 

 

 

 

 QQ群:9896150 【Java终结者】

 

 

 

 

 

评论
发表评论

您还没有登录,请登录后发表评论