领先一步
VMware 提供培训和认证,以加快您的进度。
了解更多上个月,在最初的 4.0 版本发布近 4 年后,OSGi 联盟正式批准了 OSGi 服务平台 4.2 版本。公告标题重点介绍了Blueprint Container 服务,这是基于 Spring Dynamic Modules(也称为 Spring OSGi)项目推广的编程模型添加到 Compendium 规范中的新内容。为了快速总结 Blueprint,我将直接引用 OSGi 的规范
(Blueprint Container) [...] 定义了一个依赖注入框架,专门用于 OSGi 捆绑包,它理解服务的独特动态特性。它提供了一个 OSGi 捆绑包编程模型,具有最少的实现依赖项,并且 Java 代码中几乎没有意外的复杂性。
熟悉IoC 概念或 Spring 和 Spring DM 配置的用户会发现 Blueprint 规范很容易理解。事实上,由于它源自 Spring DM,许多 Blueprint 的概念、语法和术语都是相同的,在大多数情况下,在两者之间移植现有应用程序只需调整配置文件即可。在功能方面,Blueprint 提供了一个支持构造函数和 setter 注入、工厂方法、生命周期管理和回调、签名消除歧义和类型转换等的控制反转容器。在 OSGi 方面,可以使用导出器和导入器来透明地发布和使用 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 都可以在同一个应用程序中同时适应这两种样式,从而提供更大的灵活性。例如,字段注入或基于注解的配置可以像在传统的 Spring 应用程序中一样轻松地添加到 Blueprint 捆绑包中,从而补充 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*
请注意,模板不包含有关注解或配置的信息——自 1.0.0.M6 以来,Bundlor 了解 Blueprint 捆绑包,它会自动拾取并解析任何相关的配置和类。
# 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 捆绑包列表(通过在 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
您可以在这里找到项目存档(包含说明)here。
通过在 OSGi 平台内采用事实上的标准(如依赖注入),我们相信 Blueprint 对 OSGi 和非 OSGi 开发人员都有益,因为它鼓励 API 解耦和基础设施问题的外部化,大大降低了创建和配置 OSGi 应用程序的入门门槛。
我们对未来的发展和目前正在开发的功能感到非常兴奋!
有关 OSGi 和 Spring DM 的更多更新(和反馈!),请关注本博客和 Twitter(通过标签#osgi、#springdm、#dmserver。本人可在@costinl找到)。