Tuscany SCA V1.0中的扩展机制和启动过程中的扩展点[11月29日更新]
2007年9月24日Tuscany SCA 发布了V1.0版本的实现 。本文讲述的内容使用的就是基于这个版本的,代码下载地址http://incubator.apache.org/tuscany/sca-java-10-incubating.html
一、Tuscany SCA 运行时的组成
Tuscany SCA V1.0 与前面的几个版本相比,在结构上发生了很大的变化。这种变化是意料之中的,但变化之快却是始料不及的。前面几个版本结构比较僵化、组织复杂,对变化的适应性差。如果SCA规范稍有变动,在结构上很难快速的适应,代码的变化就更不用说了。
Tuscany SCA V1.0版本将Tucany SCA 运行时(Runtime)分成两部分,核心部分和扩展部分。核心部分的实质是利用IoC (Inversion of Control)或者DI (Dependency Injection)原理将分开的逻辑和实现,通过扩展机制实现联系和匹配;在扩展部分的结构上使用多级扩展。这种机制带来更加灵活的扩展能力和动态特性。关于Ioc或者DI可以参看相关的文章。
通过扩展点将功能结构分解分散,减少了核心部分的对象和操作,使核心部分结构更加清晰,紧凑。这让我想起了章鱼:一个小小的头和长长的八只爪。我想不久,Tuscany SCA在结构上还会做进一步的改进。
二、"芝麻开门"——Tuscany SCA V1.0 的启动点
Tuscany SCA V1.0的启动是从SCADomain开始的,从上向下,由外到内逐步细化。SCADomain是一个抽象类,对应规范中的Domain组件。SCADomain通过其实现类获得Domain组件的实例。SCADomain 有几个实现类,关系如下图:
当执行SCADomain.createInstance("someComposite") 时,SCA 的启动开始!
三、启动环境的准备
DefaultSCADomain是SCADomain的一个实现类。SCADomain.createInstance()通过DefaultSCADomain构造一个SCADomain类型的实例。这个DefaultSCADomain实例,包含了一个运行时(Runtime)对象——ReallySmallRuntime。
ReallySmallRuntime 主要作用就是实现扩展机制,做了大量的扩展点匹配的工作。
四、扩展机制
扩展机制包含两个部分:扩展类型和扩展点。扩展类型和扩展点的关系是接口和实现类的关系。
扩展类型声明的方法在扩展点中被实现;扩展点是一个接口,而扩展点是实现了这个接口的类。
在程序中,通过什么方法调用即避免在代码中不出现扩展点(实现类),还可以通过扩展类型(接口)使用这些扩展点(实现类)呢?来看看下面的代码:
WorkSchedulerworkScheduler=registry.getExtensionPoint(WorkScheduler.class);
解释一下上面两行代码:
1、ExtensionPointRegistry是一个扩展点注册接口。在ExtensionPointRegistry 中声明的方法通过DefaultExtensionPointRegistry实现,通过ExtensionPointRegistry 接口来使用。
2、通过DefaultExtensionPointRegistry的实例registry来获取扩展类型为WorkScheduler.class 的扩展点,并返回一个扩展类型的实例。
ExtensionPointRegistry在这里起到了匹配、实例化、类型转换、存储的作用。
首先,通过ServiceConfigurationUtil.getServiceClassNames()方法匹配扩展点,方法如下。
List<String>classNames=newArrayList<String>();
for(URLurl:Collections.list(classLoader.getResources("META-INF/services/"+name))){
InputStreamis=url.openStream();
BufferedReaderreader=null;
try{
reader=newBufferedReader(newInputStreamReader(is));
while(true){
Stringline=reader.readLine();
if(line==null)
break;
line=line.trim();
if(!line.startsWith("#")&&!"".equals(line)){
classNames.add(line.trim());
}
}
}finally{
if(reader!=null)
reader.close();
if(is!=null){
try{
is.close();
}catch(IOExceptionioe){}
}
}
}
returnclassNames;
}
其中,String name参数是 WorkScheduler.class.getName()的值,即包含全部包在内的全路径名。
WorkScheduler.class.getName() = "org.apache.tuscany.sca.work.WorkScheduler";
在("META-INF/services/"路径下,会有一个以"org.apache.tuscany.sca.work.WorkScheduler"为名称的文件,文件内容为:
#ormorecontributorlicenseagreements.SeetheNOTICEfile
#distributedwiththisworkforadditionalinformation
#regardingcopyrightownership.TheASFlicensesthisfile
#toyouundertheApacheLicense,Version2.0(the
#"License");youmaynotusethisfileexceptincompliance
#withtheLicense.YoumayobtainacopyoftheLicenseat
#
#http://www.apache.org/licenses/LICENSE-2.0
#
#Unlessrequiredbyapplicablelaworagreedtoinwriting,
#softwaredistributedundertheLicenseisdistributedonan
#"ASIS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY
#KIND,eitherexpressorimplied.SeetheLicenseforthe
#specificlanguagegoverningpermissionsandlimitations
#undertheLicense.
org.apache.tuscany.sca.core.work.Jsr237WorkScheduler
所以,ServiceConfigurationUtil.getServiceClassNames()返回的List类型的classNames里面有一个值,为:org.apache.tuscany.sca.core.work.Jsr237WorkScheduler
然后,实例化、存储、类型转换:
if(!classNames.isEmpty()){
Class<?>extensionPointClass=Class.forName(classNames.iterator().next(),true,classLoader);
Constructorconstructor=extensionPointClass.getConstructor();
ObjectextensionPoint=constructor.newInstance();
}
这样,通过ServiceConfigurationUtil.getServiceClassNames()查找与扩展类型匹配的扩展点,利用ExtensionPointRegistry.getExtensionPoint()方法实现实例化、类型转换、存储,实现了扩展机制。
五、启动过程中的扩展类型分级一览
除了上面列举的一些扩展类型之外,还有两个扩展类型需要特别说明。一个是XMLInputFactory扩展类型;另一个是ModuleActivator扩展类型,这个扩展类型不在上面的表中。
[2007年11月29日新增以下内容]
上面所列举的扩展类型,在其"META-INF/services"目录中都有对应的匹配文件,这个文件就是扩展类型类的全路径名称, 即包括完整的(package)包名的类名,但是不包括扩展名(不包括.Class).
但是XMLInputFactory这个扩展类型,你却无法在Tuscany的代码中找到任何的匹配文件。
这是因为在Tuscany引用的一个jar中包含了一个XMLInputFactory的匹配文件;
这个jar位于D:/tuscany-sca-1.0-incubating/lib的wstx-asl-3.2.1.jar/META-INF/services中.
这是XMLInputFactory扩展类型与其它扩展类型不同的地方,还有一个扩展类型也与众不同,就是ModuleActivator.
上述扩展类型都几乎只有一个匹配文件,在匹配文件中可能有几个继承了这个扩展类型的扩展点,但是数量还是相对较少.ModuleActivator拥有众多的扩展匹配文件,目前找到的有11个匹配文件.这意味着ModuleActivator提供了非常丰富和灵活的应用,这些扩展点是
org.apache.tuscany.sca.binding.ejb.EJBBindingsActivator
org.apache.tuscany.sca.binding.notification.NotificationBindingModuleActivator
org.apache.tuscany.sca.core.databinding.module.DataBindingModuleActivator
org.apache.tuscany.sca.extension.helper.impl.ImplementationsActivator
org.apache.tuscany.sca.extension.helper.impl.BindingsActivator
test.crud.module.CRUDModuleActivator
org.apache.tuscany.sca.http.jetty.module.JettyRuntimeModuleActivator
org.apache.tuscany.sca.http.tomcat.module.TomcatRuntimeModuleActivator
org.apache.tuscany.sca.host.webapp.WebAppModuleActivator
org.apache.tuscany.sca.implementation.java.module.JavaRuntimeModuleActivator
org.apache.tuscany.sca.implementation.notification.NotificationModuleActivator
org.apache.tuscany.sca.osgi.runtime.OSGiRuntimeModuleActivator
<待续>