Spring DM入门

本文介绍Spring Dynamic Modules (SpringDM)如何使Spring应用程序在OSGi容器中部署并利用其服务。通过具体示例展示了如何将Spring Bean作为OSGi服务发布,并在其他模块中引用这些服务。
摘要由CSDN通过智能技术生成

Spring Dynamic Modules (即Spring动态模型,简称Spring DM)允许开发者构建Spring应用程序,这种应用程序能够在OSGi容器中进行部署,并可有效利用OSGi框架所提供的服务。这种应用程序具有以下几方面的优点:

      1、更好的分离应用逻辑与模块。
      2、同时部署同一个模块的不同版本的能力。
      3、动态发现和使用系统内其他模块提供的服务的能力。
      4、在运行着的系统中动态地安装、更新和卸载模块的能力。
      5、使用 Spring 框架在模块内部和模块之间进行实例化、配置、整合组件的能力。
      6、让企业应用开发者使用简单、熟悉的编程模型开发OSGi平台的功能。

 

Spring DM很关键的一个jar文件是spring-osgi-extender-*.*.*.jar,它主要负责为Bundle实例化Spring应用程序上下文。extender可以通过两种方式来识别需要处理的Bundle,一是MANIFEST.MF文件里包含了Spring-Context 头条目的Bundle,二是extender将把META-INF/spring下面的所有XML文件视为有效Spring 配置文件。缺省情况下,Spring使用META-INF/spring目录下所有的xml文件来创建Application Context。缺省设置可以在Spring-Context的manifest header中重写,Header的值是由逗号分隔的资源路径及指令列表表示。

 

Spring-Context头条目的配置范例如下:

      Spring-Context: config/applicationContext.xml, config/beans-security.xml 
      Spring-Context: *;create-asynchronously=false
      Spring-Context: config/osgi-*.xml;wait-for-dependencies:=false
      Spring-Context: *;timeout:=60 
      Spring-Context: *;publish-context:=false

 

 

Header值中的指令主要有以下这些:

      create-asynchronously (true|false):控制是否异步地(默认)或同步地创建应用程序上下文。
      wait-for-dependencies  (true|false):控制在上下文创建之前是否要等待(默认)或不等待所有强制依赖的服务变成 satisfied。
      timeout (300):等待强制依赖服务变成 satisfied 的时间(以秒为单位),超时之后放弃等待且上下文创建会失败。如果 wait-for-dependencies:=false 被指定,那么这个设置会被忽略。默认值是 5 分钟(300 秒)。 
      publish-context  (true|false):控制是否应用程序上下文对象是否发布其自身到 OSGi 服务注册表中。默认是发布。

 

一、将Bean输出为OSGi服务

     1、接口及其实现类源码

public interface PersonManager {
	public void savePerson(String username, String password);
}

 

public class PersonManagerImpl implements PersonManager {
	public PersonManagerImpl(){
		System.out.println("instance PersonManagerImpl");
	}
	
	public void savePerson(String username, String password) {
		System.out.println("save person: " + username + ", " + password);
	}
}

 

     2、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-2.5.xsd
    http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd">
 	
 	<!-- 
 		bundle:为每一个服务的导入者生成一个新的服务实例。当服务导入者停止时,服务实例会被回收。
 	 -->
	<bean id="personManager" scope="bundle" class="p3.service.impl.PersonManagerImpl"/>
	
	<!-- 
		自动将受管Bean暴露成OSGi服务,并注册到OSGi容器中。不需要借助BundleActivator对象。
	 -->
	<osgi:service id="personManagerService" ref="personManager" interface="p3.service.PersonManager"/>
	
</beans>

      被Service元素定义的Bean的类型是org.osgi.framework.ServiceRegistration,它是在OSGi服务注册表中注册输出Bean而产生的ServiceRegistration对象。

      指定服务接口(或者服务接口集):
            使用interface属性来指定一个全限定接口名
            使用嵌套的interfaces元素可以指定多个服务接口
                  <osgi:service id="personManagerService" ref="personManager">
                        <osgi:interfaces>
                              <value>p3.service.PersonManager</value>
                        </osgi:interfaces>
                  </osgi:service>

 

     3、MANIFEST.MF文件内容

        必须导出接口所在的包(如p3.service)供其它Bundle引入

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: P3 Plug-in
Bundle-SymbolicName: p3
Bundle-Version: 1.0.0
Import-Package: org.osgi.framework;version="1.3.0"
Export-Package: p3.service;version="1.0.0"
Bundle-ClassPath: bin/

 

二、引用由Spring Bean输出的OSGi服务  

     1、接口及其实现类 

public interface HelloPerson {
	public void save(String username, String password);
}

 

public class HelloPersonImpl implements p4.service.HelloPerson {
	private PersonManager personManager;
	
	public PersonManager getPersonManager() {
		return personManager;
	}

	public void setPersonManager(PersonManager personManager) {
		this.personManager = personManager;
	}

	public void save(String username, String password) {
		personManager.savePerson(username, password);
	}
}

 

     2、服务消费类

/**
 * 如果一个Bean对象需要访问BundleContext,则可以让该Bean对象实现BundleContextAware接口
 */
public class Activator implements BundleContextAware {
	private BundleContext bundleContext;
	private HelloPerson helloPerson;
	
	public void start() throws Exception {
		System.out.println("start Activator: " + bundleContext.getBundle().getSymbolicName());
		helloPerson.save("cjm", "123");
	}
	
	public void stop() throws Exception {
		System.out.println("stop Activator");
	}

	public void setBundleContext(BundleContext bundleContext) {
		this.bundleContext = bundleContext;
	}
	
	public void setHelloPerson(HelloPerson helloPerson) {
		this.helloPerson = helloPerson;
	}
}

 

     3、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-2.5.xsd
    http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd">
 	
 	<!-- 
 		reference元素:用于定义一个本地bean代理某个OSGi服务(即引用其它Bundle导出的服务)
 			id:本地bean的名字
 			interface:目标服务所注册的接口的全路径名
 	 -->
 	<osgi:reference id="personManagerOSGI" interface="p3.service.PersonManager" />

	<bean id="helloPerson" scope="bundle" class="p4.service.impl.HelloPersonImpl">
		<property name="personManager" ref="personManagerOSGI"/>
	</bean>
	
	<bean id="activator" class="p4.Activator" init-method="start" destroy-method="stop">
    	<property name="helloPerson" ref="helloPerson"></property>
  	</bean>
</beans>

 

     4、MANIFEST.MF文件内容

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: P4 Plug-in
Bundle-SymbolicName: p4
Bundle-Version: 1.0.0
Import-Package: org.osgi.framework;version="1.3.0",
 p3.service;version="1.0.0"
Require-Bundle: org.springframework.bundle.osgi.core

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值