起因
在传统项目中,项目所需的类库都被部署在运行时环境的lib目录,如果要更新一个类库Jar,则需要替换所有运行时环境的lib目录
如果项目中仅有部分程序需要用到新版本的特性,而新版本又有较大改动,则不得不修改所有用到该类库的代码
解决
JIOPi引入标准模块库机制,允许将模块程序分版本放入模块库,当模块库更新时,所有使用点将自动更新类库程序
类似OSGi的模块隔离加载机制,允许在一个系统中同时运行一个模块(同名类)的多个版本
参考阅读:使用JIOPi模块库实现类库自动升级
使用JIOPi的标准模块库,可以实现类库的统一部署和自动升级,但是要在代码中引入JIOPi的API程序
并且在IoC流行的今天,这种做法无疑会失去很多IoC的优点
JIOPi只希望扩充特性,但并不想改变甚至弱化现有编程风格
JIOPi可以完全嵌入在Spring内,既不改变现有编程风格,又可让Spring支持类库的统一部署和自动升级
特别说明
模块库http://jiopi.vip7.es163.net/ibean/resourcepools/jiopi-ibean.xml
的jiopi.ibean.helloworld.i模块已经将版本更新为0.1.0.2,以支持Spring装配的演示
如果你已经运行过之前的jiopi.ibean.helloworld.i模块并关闭了容器的自动升级功能,则需要打开自动升级以下载最新版本的模块程序
前提
为了使用Spring IoC,你的模块程序必须将访问API独立打包为一个Jar,并且在将模块程序部署在JIOPi模块库时,仅部署实现类相关的Jar,而不部署API的Jar包,而在项目的lib内部署 API的Jar包
这个过程有点像发布一个远程模块,你需要在项目内部署远程模块的访问API,而实现类则是部署在另一台服务器
与远程模块不同的是,JIOPi的模块库最终还是在本地执行,而不是远程服务器,所以,你可以使用Spring对获取到的模块对象进行二次装配(即接口并不提供set方法,而其实实现类是实现了set方法的),这是远程模块无法实现的
下面我们就来看看如何使用Spring IoC来运行iBean的HelloWorld程序
JIOPi风格的代码参见: http://www.iteye.com/topic/655312
安装Spring 3
本演示使用了Spring 3的类库,以使用变参函数让代码更易读
需要以下文件:
commons-logging-1.1.1.jar
org.springframework.asm-3.0.1.RELEASE-A.jar
org.springframework.beans-3.0.1.RELEASE-A.jar
org.springframework.context-3.0.1.RELEASE-A.jar
org.springframework.core-3.0.1.RELEASE-A.jar
org.springframework.expression-3.0.1.RELEASE-A.jar
其他Jar
iBeanWithJIOPi-0.1.0.1.jar 当然你还需要JIOPi的实现容器
blueprint-helloworld-0.1.jar HelloWorld的接口Jar
以上jar和演示程序可以从iBean的项目SVN中获取
http://ibean.googlecode.com/svn/trunk/ibean-show/
HelloWorld的源码在:
http://ibean.googlecode.com/svn/trunk/ibean-example/
配置Spring Bean
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="jiopi" singleton="false" class="org.jiopi.framework.CentralConsole" factory-method="accessControlPanel"/> <bean id="helloworld" singleton="false" class="org.jiopi.framework.CentralConsole" factory-method="accessControlPanel"> <constructor-arg type="java.lang.String"><value>jiopi.ibean.helloworld.i</value></constructor-arg> <constructor-arg type="java.lang.String"><null/></constructor-arg> <constructor-arg type="java.lang.String"><value>org.jiopi.ibean.example.module.helloworld.HelloWorldImpl</value></constructor-arg> <constructor-arg type="java.lang.Class"><value>org.jiopi.ibean.example.blueprint.helloworld.HelloWorld</value></constructor-arg> <constructor-arg type="java.lang.Object[]"><list></list></constructor-arg> <property name="msg"><value>spring msg</value></property> </bean> </beans>
说明:
jiopi配置了一个通用模块加载器,你可以通过Spring代理来获取JIOPi模块库中的类,而避免在代码中引入JIOPi的API
helloworld配置了一个加载好的org.jiopi.ibean.example.module.helloworld.HelloWorldImpl对象
并且可以由Spring对加载好的对象进行二次装配:
<property name="msg"><value>spring msg</value></property>
调用代码
使用Spring后,你只需要从Spring容器内获取对象即可,而无需访问JIOPi的API
//直接获取配置好的Bean,使用Spring二次装配 HelloWorld hw = appContext.getBean("helloworld",HelloWorld.class); hw.helloWorld(); //JIOPi隐含调用,默认构造函数 HelloWorld jiopiHw = (HelloWorld) appContext.getBean("jiopi","jiopi.ibean.helloworld.i",null,"org.jiopi.ibean.example.module.helloworld.HelloWorldImpl", HelloWorld.class,new Object[]{}); jiopiHw.helloWorld(); //JIOPi隐含调用,使用带一个参数的构造函数 HelloWorld jiopiHwMy = (HelloWorld) appContext.getBean("jiopi","jiopi.ibean.helloworld.i",null,"org.jiopi.ibean.example.module.helloworld.HelloWorldImpl", HelloWorld.class,new Object[]{"my msg"}); jiopiHwMy.helloWorld();
总结
将JIOPi嵌入Spring,你既可以享受远程模块带来的优点
实现类无需部署在运行环境
实现类的更新后所有使用环境自动生效
可以存在同一功能的多个版本的远程服务
也可以像使用本地类库那样充分使用Spring的各种特性
而你也并不会因此而改变你的代码风格