OSGi与Spring的整合 - 拨云现日
最困难的时期已经过去,配置好环境之后下一步就是写一个测试程序跑一下。由于我主要是为了整合Hibernate,所以测试程序就以此为前提了。
Hibernate整合本身比较简单,但如果想把框架设计得更加灵活、耦合性更低,支持以插件方式添加新的数据库表映射以及数据库操作将会比较麻烦,会涉及到SessionFactory的生成,这些问题后续文章会陆续谈到。我们这里采用的例子是一个典型的基于角色的权限校验系统,简化后我们不再关心持久层,只来讨论与Spring结合是如何配置的问题。
首先建一个用来注册实体类的接口,可以动态监控数据库实体类的注册与销毁。接口相当简单,代码如下:
package wanged.core.persistent.entity; @SuppressWarnings("unchecked") public interface EntityRegister { Class[] register(); // 返回需要注册的实体类的数组 }这个接口单独作为一个Bundle(命名为wanged_core_persistent_entity_register),MANIFEST.MF中只需要导出该接口所在的包供其他Bundle引用即可。
现在需要实现接口了,这个接口会被用来声明一类服务,这样就可以利用OSGi的服务来达到动态添加数据库表映射的目的。
建一个包含实体类的Bundle(命名为wanged_security_entity),其实就是一个插件工程,为简单起见就叫Bundle,下同。新建一个类实现EntityRegister接口,代码如下:
package wanged.security.entity; import java.util.ArrayList; import wanged.core.persistent.entity.EntityRegister; @SuppressWarnings("unchecked") public class SecurityEntityRegisterImpl implements EntityRegister{ public Class[] register() { ArrayList cList = new ArrayList(); cList.add(Role.class); // 用户角色实体类Role cList.add(User.class); // 用户信息实体类User return cList.toArray(new Class[cList.size()]); } }
MANIFEST.MF中需要引入EntityRegister接口所在的包,否则会找不到该接口。另外还需要导出Role和User所在的包,以便其他Bundle调用。现在类建好了,需要声明我们的服务了。Spring和OSGi结合可以省去DS的配置文件,这也是上一篇文章在导入所需Bundle时没有引入DS相关的Bundle的原因。Spring可以在META-INF/spring目录下查找所有的xml文件,并自动解析生成其中定义的Bean。下面我们建一个bean.xml的文件来声明服务,内容如下:
package test.core.persistent; import wanged.core.persistent.entity.EntityRegister; public class TestEntityRegister{ // 由于要注册多个这样的服务,所以参数为数组格式 @SuppressWarnings("unchecked") public void setEntityRegister(EntityRegister[] erArr) { for(EntityRegister er: erArr) { System.out.println("EntityRegister class : " + er.getName()); for(Class c : er.register()) { System.out.println(c.getName()); } } } }
在MANIFEST.MF中引入包wanged.core.persistent.entity。在META-INF中添加spring/bean.xml,并定义该测试类:
- <osgi:reference id="entityRegister"
- interface="wanged.core.persistent.entity.EntityRegister" cardinality="1..n" />
- <bean id="testEntityRegister" class="test.core.persistent.TestEntityRegister">
- <property name="entityRegister" ref="entityRegister" />
- </bean>
注意上面的cardinality设置正是和setEntityRegister()方法的数组参数对应。现在已经全部搞定,所需要的就是运行一下,看是否如期输出类的信息。