领先一步
VMware 提供培训和认证,助您加速进步。
了解更多上个月,在 4.0 版本发布近 4 年后,OSGi 联盟正式 批准了 OSGi 服务平台 4.2 版本。公告的头条是Blueprint Container 服务,这是 Compendium 规范的新增内容,基于 Spring Dynamic Modules(也称为 Spring OSGi)项目推广的编程模型。为了快速总结 Blueprint,我将直接引用 OSGi 规范
(Blueprint Container) [...] 定义了一个依赖注入框架,专门用于 OSGi bundle,该框架能够理解服务独特的动态特性。它提供了一个 OSGi bundle 编程模型,具有最小的实现依赖,并且在 Java 代码中几乎没有意外的复杂性。
熟悉IoC概念或Spring和Spring DM配置的用户,会发现Blueprint规范很容易理解。事实上,由于它源自Spring DM,Blueprint的许多概念、语法和术语都相同,因此在大多数情况下,将现有应用程序迁移到两者之间,只需调整配置文件即可。在功能方面,Blueprint提供了一个控制反转容器,支持构造函数和setter注入、工厂方法、生命周期管理和回调、签名歧义化和类型转换等。在OSGi方面,可以使用导出器(exporters)和导入器(importers)来透明地发布和消耗OSGi服务。
下面是一个Blueprint配置的代码片段,它创建了几个对象,导入了一个服务,将它们连接在一起,然后将目标暴露为一个OSGi服务。
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" default-activation="lazy">
<!-- basic object creation -->
<bean id="object" class="java.lang.Object"/>
<bean id="length" class="java.lang.Integer">
<argument value="4"/>
</bean>
<bean id="buffer" class="java.lang.StringBuffer" depends-on="simple">
<property name="length" ref="length"/>
</bean>
<bean id="current-time" class="java.lang.System" factory-method="currentTimeMillis" scope="prototype"/>
<bean id="list" class="java.util.ArrayList" destroy-method="clear" activation="eager">
<argument ref="length"/>
</bean>
<!-- service import -->
<reference id="ds" class="javax.sql.DataSource" filter="(batch-size=200)"/>
<bean id="consumer" class="org.springframework.jdbc.core.simple.SimpleJdbcTemplate">
<property name="dataSource" ref="ds"/>
</bean>
<!-- service export -->
<service id="publisher" ref="consumer" auto-detect="interfaces"/>
</blueprint>
除了配置之外,Blueprint还提供了一个小的API(通过container和reflect包)用于依赖查找、读取元数据或执行自定义类型转换,这在一定程度上类似于Spring。有关Blueprint和Spring DM之间相似性(及差异)的更多信息,请参阅DM 2.0 M1参考文档中专门的章节。
值得指出的是,虽然Blueprint依赖于OSGi 4.2 API,但Spring DM 2.x不依赖。运行OSGi 4.0和4.1的用户可以安全地使用Spring DM 2.x;只有Blueprint功能将被禁用,其余功能仍然可用。
使用Spring DM的一个关键优势是能够透明地完全访问OSGi中的Spring容器:无论您是计划使用Blueprint、Spring/Spring DM API和配置,Spring DM 2.x 都可以在同一个应用程序中支持这两种风格,从而提供更大的灵活性。例如,字段注入或基于注解的配置可以轻松添加到Blueprint bundle中,就像在传统的Spring应用程序中一样,从而补充了Blueprint的功能。
具体来说,让我们以规范中的一个示例为例,将Blueprint配置与JSR-250(通用注解)以及Spring 3中的一些新功能(如JSR-330(Java依赖注入)支持)结合起来。
public interface Echo {
public String echo(String m);
}
public class EchoImpl implements Echo {
String message;
public void setMessage(String m) {
this.message= m;
}
public String echo(String s) { return message + s; }
}
<blueprint>
<service id="echoService" interface="com.acme.Echo" ref="echo"/>
<bean id="echo" class="com.acme.EchoImpl"
<property name="message" value="Echo: "/>
</bean>
</blueprint>
我将在此示例中使用Maven及其项目布局约定:[caption id="attachment_2939" align="aligncenter" width="326"]
[/caption]
public class EchoImpl implements Echo {
@Inject
private PackageAdmin pkgAdmin;
String message;
public void setMessage(String m) {
this.message = m;
}
public String echo(String s) {
return message + s;
}
@PostConstruct
void startup() {
Bundle bnd = pkgAdmin.getBundle(getClass());
ExportedPackage pkg = pkgAdmin.getExportedPackage(Echo.class.getPackage().getName());
System.out.printf("Echo service bundle [%s] wired to bundles %s\n", bnd.getSymbolicName(),
Arrays.toString(pkg.getImportingBundles()));
}
}
<blueprint>
<service id="echoService" interface="com.acme.Echo" ref="echo" />
<bean id="echo" class="com.acme.internal.EchoImpl">
<property name="message" value="Echo: "/>
</bean>
<reference id="pkgAdmin"
interface="org.osgi.service.packageadmin.PackageAdmin" />
<context:annotation-config/>
</blueprint>
Excluded-Exports: *.internal*
请注意,模板中没有关于注解或配置的信息——由于Bundlor自1.0.0.M6起就支持Blueprint bundle,它会自动拾取并解析任何相关的配置和类。
# mvn package
这样就完成了。现在让我们运行我们的示例。
Manifest-Version: 1.0
Export-Package: com.acme;version="0.0.0"
Bundle-Name: blueprint-atinject
Bundle-ManifestVersion: 2
Bundle-SymbolicName: blueprint-atinject
Import-Package: javax.annotation,javax.inject,org.osgi.framework,org.o
sgi.service.packageadmin
只需将生成的jar部署到OSGi 4.2框架中,并与Spring DM 2.0.0.M1一起,您应该会看到以下输出。
INFO: Blueprint API detected; enabling Blueprint Container functionality
...
INFO: JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
...
Echo service bundle [blueprint-atinject] wired to bundles []
...
INFO: Publishing service under classes [{com.acme.Echo}]
以下是我的OSGi bundle列表(通过在Equinox中调用ss得到的结果)。
0 ACTIVE org.eclipse.osgi_3.5.0.v20090520
1 ACTIVE com.springsource.slf4j.api_1.5.6
Fragments=2
2 RESOLVED com.springsource.slf4j.juli_1.5.6
Master=1
3 ACTIVE com.springsource.slf4j.org.apache.commons.logging_1.5.6
4 ACTIVE com.springsource.org.aopalliance_1.0.0
5 ACTIVE com.springsource.net.sf.cglib_2.1.3
6 ACTIVE org.springframework.asm_3.0.0.RC1
7 ACTIVE org.springframework.expression_3.0.0.RC1
8 ACTIVE org.springframework.core_3.0.0.RC1
9 ACTIVE org.springframework.beans_3.0.0.RC1
10 ACTIVE org.springframework.aop_3.0.0.RC1
11 ACTIVE org.springframework.context_3.0.0.RC1
12 ACTIVE org.springframework.osgi.io_2.0.0.M1
13 ACTIVE org.springframework.osgi.core_2.0.0.M1
14 ACTIVE org.springframework.osgi.extender_2.0.0.M1
15 ACTIVE com.springsource.javax.inject_0.9.0.PFD
16 ACTIVE com.springsource.javax.annotation_1.0.0
17 ACTIVE blueprint-atinject_0.0.0
您可以在此处找到项目存档(含说明)。
通过在OSGi平台中采用事实上的标准(如依赖注入),我们相信Blueprint对OSGi和非OSGi开发者都有益,因为它鼓励API解耦和基础设施关注点的外部化,从而大大降低了创建和配置OSGi应用程序的入门门槛。
我们对未来的道路以及当前正在开发的功能感到非常兴奋!
有关OSGi和Spring DM的更多更新(和反馈!),请关注我们的博客和Twitter(通过标签#osgi、#springdm、#dmserver。您可以通过@costinl联系我)。