既有SSH框架的改造方案
From Tuscany中文社区
目录 |
[编辑] Spring与Tuscany Runtime的通讯
[编辑] 开发对象
见下图中com.sitechasia.webx.sca包中的三个类:
图中:WebXScaHandler继承了NamespaceHanlderSupport,它处理我们定义的扩展命命名空间。 图中:ScaLocatorParser实现了BeanDefinitionParser,它处理每一个我们扩展定义的标签。 图中:SCAServiceLocator实现了InitializingBean和FactoryBean两个接口,当ApplicationContext启动的时候,第一个被实例化的SCAServiceLocator将会初始化Tuscany,即SCADomain。
[编辑] Spring扩展标记
描述文件:
|--classpath
|--META-INF
|--spring.schemas
|--spring.handlers
|--webx.xsd
描述文件内容如下
|
spring.handlers |
|
|
http\://www.sitechasia.com/webx=com.sitechasia.webx.sca.WebXScaHandler |
由指定的类负责处理扩展标签使用的命名空间 |
|
spring.schemas |
|
|
http\://www.sitechasia.com/webx/webx.xsd=webx.xsd |
扩展标签的内容定义文件 |
|
webx.xsd |
|
<xsd:schema xmlns="http://www.sitechasia.com/webx"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
attributeFormDefault="unqualified" elementFormDefault="qualified"
targetNamespace="http://www.sitechasia.com/webx">
<xsd:element name="scaLocator">
<xsd:complexType>
<xsd:attribute name="type" use="required">
<xsd:simpleType>
<xsd:restriction base="xsd:string" />
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="name" use="required">
<xsd:simpleType>
<xsd:restriction base="xsd:string" />
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="id" use="required">
<xsd:simpleType>
<xsd:restriction base="xsd:string" />
</xsd:simpleType>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:schema>
|
扩展标签内容包括:scaLocator及其属性:type(java接口名称)
name(tuscany构件名称) id(等同于spring bean的id) |
[编辑] 为什么使用spring扩展标记
Spring提供了扩展其基本(核心)标记的方法,即按照图1中的方式继承及实现spring所提供的基类和接口。 本文所使用的扩展标记相当于以下的标准的bean用法
<bean id=”[符合相关setter的命名]” class=”com.sitechasia.webx.sca.SCAServiceLocator”> <property name=”type” value=”[服务类接口]”/> <property name=”name” value=”[Tuscany构件名称]”/> </bean>
该Bean需要在原来的每个Service Bean变为Tuscany构件后,继续满足原来的spring的IoC关系。
为了能够隐蔽一些不需要开发者知道的信息,如*SCAServiceLocator这个类的名称,我们使用了一个spring的扩展标记,该标记提高了具体实现的可扩展性,并进一步降低了开发者的代码量。
[编辑] Tuscany Runtime生命周期
Tuscany Runtime或称容器是在Spring的ApplicationContext启动时由第一个SCAServiceLocator启动的,Tuscany容器被作为一个静态static成员由SCAServiceLocator保管。而所有对Tuscany容器的访问都通过该静态实例完成。
Tuscany容器生命周期如下:
第一次被使用时完成初始化 初始化之后一直存在 在JVM退出之前由JVM负责销毁。
[编辑] 线程安全问题
新系统中,Tuscany Runtime即SCADomain实例作为一个静态成员由SCAServiceLocator保管。涉及线程安全的地方有两处,一是该实例的初始化,该过程在SCAServiceLocator第一次被实例化的时候完成,对于统一个ApplicationContext,bean是一次实例化的,所以没有线程冲突,而对于多个ApplicationContext并行启动的情况,可能它们都使用了SCAServiceLocator,这种情况下,SCADomain的初始化过程有一个同步锁锁定。
第二:任何使用(依赖)Tuscany服务(构件)的bean,都通过这个“全局”的SCADomain获得Tuscany构件,该获得过程是一个涉及线程安全的问题。但是由于这个获得服务的方法(getService)不是静态的,所以实际上并没有线程冲突。
而每个既已获得的构件,缺省情况时多例的,而通过配置,Tuscany可以返回单例的构件实例。
[编辑] Struct Action管理
仍然由Spring管理Struct Action实例,但是原来Action与Service Bean的依赖关系在新的系统中由SCAServiceLocator实现。原Struts配置文件不需要做任何修改。
[编辑] Acegi
SSH框架一般通过Acegi技术实现系统的安全与认证模型。而Acegi是一个通过Spring管理的架构。在新系统中,安全与认证仍然由Acegi实现,并且,Acegi仍然由Spring管理,唯一的区别是原来的UserDetailService被改为SCA服务,原来的依赖UserDetailService Bean的对象,改为依赖一个同名的SCAServiceLocator。
[编辑] Service Bean变为SCA构件
利用tuscany-implementation-spring提供的支持。新系统可以将通过Tuscany扩展的ApplicationContext加载一个spring的定义文件。然后,通过Tuscany所提供的扩展标记来以SCA构件的形势访问某个Bean。 在新系统中,只有Service Bean才应当被映射为SCA Service(其实就是一个构件)。 SCA构件定义
文件资源
java.net.URL
|--META-INF
|--sca-contribution.xml
|--*.composite
|
*.composite |
composite文件内容是SCA的定义 |
<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
targetNamespace="http://webxsample"
name="webxsample">
<component name="BookServiceComponent">
<implementation.spring location="modules/book/spring-conf/serviceContext.xml"/>
</component>
<component name="SecutiryComponent">
<implementation.java class="com.sitechasia.webx.book.utils.Security"/>
</component>
</composite>
|
这里列出的是:composite(组件)及其所在的命名空间; component及其名称; 第一个component是一个spring实现; 第二个component是一个普通的java类实现。 |
|
sca-contribution.xml |
该文件标记了需要发布的composite |
<contribution xmlns="http://www.osoa.org/xmlns/sca/1.0"
targetNamespace="http://webxsample"
xmlns:webx="http://webxsample">
<deployable composite="webx:webxsample"/>
</contribution>
|
Tuscany启动时,将会处理一个URL下面的全部可用资源文件。 而这里的描述指出,tuscany之需要发布webx:webxsample,这个Qname应当与某个composite文件中的命名空间一致 |
[编辑] SCA构件图示
下图描绘了在新的WebX系统中,SCA所扮演的角色。
图中有两个SCA构件:第一个是服务于Acegi的UserDetailService,(它是一个java类实现),其客户是spring的其它bean;另一个构件是spring实现,它将原有的一个ApplicationContext中的某些spring bean发布为SCA服务(构件),同样地,其客户也是spring中的其它bean,如Struct Action。注意:图中了两部分spring的内容是不同的,它们分别管理者前端和后端的bean。
[编辑] sca资源文件的加载
Tuscany自动加载指定URL下面的全部sca资源,由于java.net.URL不支持classpath,所以加载是必须预先计算出绝对路径。该路经下应有一个META-INF/sca-contribution.xml。
[编辑] 新系统依赖的Tuscany类库
新系统依赖的Tuscany模块(JAR包)如下:
tuscany-assembly
tuscany-assembly-xml
tuscany-assembly-xsd
tuscany-binding-sca
tuscany-binding-sca-xml
tuscany-contribution
tuscany-contribution-impl
tuscany-contribution-java
tuscany-contribution-namespace
tuscany-core
tuscany-core-databinding
tuscany-core-spi
tuscany-databinding
tuscany-definitions
tuscany-definitions-xml
tuscany-domain
tuscany-domain-api
tuscany-host-embedded
tuscany-host-http
tuscany-host-webapp
tuscany-implementation-java
tuscany-implementation-java-runtime
tuscany-implementation-java-xml
tuscany-implementation-spring
tuscany-interface
tuscany-interface-java
tuscany-interface-java-xml
tuscany-node
tuscany-node-api
tuscany-policy
tuscany-policy-xml
tuscany-sca-api
[编辑] 新系统依赖的其它JAR包
geronimo-commonj_1.1_spec-1.0
axiom-api-1.2.5
[编辑] 对基于SSH所开发系统的修改
根据以上设计,使用原有WebX框架实现的系统需要做以下一些修改。需要注意的是,改设计并不会修改WebX框架本身的任何部分,仅需对基于WebX所开发的系统做极小量的修改:
- 修改web.xml,将下面的指定部分从文件中删除
<context-param> <param-name>contextConfigLocation</param-name> <param-value>您的Spring配置文件路径</param-value> </context-param>
如果按照WebX中的例子使用了acegi作为系统的安全认证部分,则将以上删除部分替换为“你的Acegi的Spring配置文件路径”。
- 在classpath下增加tuscany目录,并在该目录下增加相应的.composite和应用于服务层的总sping配置文件。总的Spring配置文件用于引入已有的服务层的Spring配置,原有Serivce层Spring配置文件不需要做任何变化。
- 在管理Action的Spring配置文件中增加多个新的SCAServiceLocator的配置来替代原有的Action对Servic的依赖。
- 在管理Action的Spring配置文件中添加相应的服务于SCAServiceLocator的名字空间,暂定为http://www.sitechasia.com/webx。
[编辑] 参考代码
说明:webX是对SSH框架改造的内部代号

