1.
SCA
简介
“
2005
年
11
月,
IBM
、
BEA
、
Oracle
、
SAP
等国外著名企业联合发布了
SCA 0.9
规范草稿。
SCA
是一种全新的、跟语言无关的编程模型,这种面向服务构件的编程模型可以大大简化客户的编程,提高应用的灵活性,将会对现有软件开发方式产生颠覆性的影响。”上面段文字是摘自普元
SCA
中文论坛中对
SCA
的描述,大家可以通过上面简短的文字对
SCA
有一个简单的认识。
SCA
全称
Service Component Architecture
(服务组件构架)
,
它是一套遵循
SOA
思想的构架,通过模型描述来构建应用系统。
SCA
并不只是针对于一种语言,它是可以支持多种语言的(
Java,C++,PHP….
),目前
SCA
给出了
Java
以及
C++
的实现规范。
对于
Java
版本的
SCA
,可以通过配置文件以及
J2SE5.0
的
Annotation
功能来描述服务,或者是通过
XML
格式的配置文件来描述服务,并能使得
SCA
容器对其进行管理。
以下文中所提到了
SCA
都是
Java
版本的
SCA
。
SCA
中的服务可以分为本地、远程服务,以及外部服务,服务具有自己的属性、引用,并且通过一些表示,可以确定服务的生命周期。
下面介绍一下如何定义本地服务,以及如何去调用本地服务。
2
.简单的本地服务
SCA
中可以通过
J2SE5.0
的
Annotation
来对服务进行标记,利用
@Service
标签,就可以定义一个服务,一般情况下,服务一般是一个接口类,服务实现是一个具体实现该接口的类,当然,我们也可以把一个具体的类定义为一个服务,服务实现即其本身。
@Service
标记是放在实现类上使用的,当标记上后,
SCA
容器就会认为这个实现类为服务的实现。而服务的描述则是通过
@Service
的值来指定的,请看下面代码:
@Service(TestService.
class
)
public
class
TestServiceImpl
implements
TestService {
public
void
invoke() {
System.out.println(
"
invoke method
"
);
}
public
void
print(String printString) {
System.out.println(
"
print
"
+
printString );
}
}
上面代码的将
TestServiceImpl
上标记了
@Service
,而@Service中的TestService.class值就表明了该服务接口即为TestService接口,而TestServiceImpl就是这个服务的实现。通过上面简单的定义,一个简单的本地服务就算是做好了。
这是最简单的本地服务例子,
@Service
中的服务接口仅仅只有一个,如果我们想要去调用这个服务则需要启动
SCA
容器,然后通过模型上下文去定位服务:
SCA sca
=
new
UxTeamSCA();
sca.start();
TestService service
=
(TestService)CurrentModuleContext.getContext().locateService(
"
TestService
"
);
service.invoke();
service.print(
"
print it
"
);
简单说一下上面代码。
SCA
是
OSOA
组织提供的
SCA
框架标准接口,它初始化后会将当前线程中的模块上下文(
ModuleContext
,也是
SCA
的一个标注接口)赋值,用户可以通过
CurrentModuleContext
类的静态方法去获得这个
ModuleContext
,模块上下文实例就可以去通过服务名定位这个服务。
我们通过
Annotation
标记服务的时候是不能给出服务名的,这种标记方式会将服务接口名默认为服务名。
3
.多个服务接口
在上面我们使用的
@Service
的值只有一个,其实
@Service
可以定义多个服务接口,形式如下:
@Service(interfaces={Interface1.class,Interfaces2.class.....})
,这种描述方式可以一次性定义多个服务,当然了,服务实现也还只是一个而已。
下面代码展示了如果定义多个服务:
@Service(interfaces
=
{TestService1.
class
,TestService2.
class
})
public
class
TestServiceImpl1
implements
TestService1 , TestService2 {
public
void
invoke() {
System.out.println(
"
example2 invoke method
"
);
}
public
void
print(String printString) {
System.out.println(
"
print
"
+
printString );
}
}
这种标记的话,
SCA
容器就会识别出
2
个服务:
TesrService1
和
TestService2
:
ModuleContext context
=
CurrentModuleContext.getContext();
TestService1 service1
=
(TestService1) context.locateService(
"
TestService1
"
);
service1.print(
"
print it
"
);
TestService2 service2
=
(TestService2) context.locateService(
"
TestService2
"
);
service2.invoke();
如果我们在定义服务的时候,出现了服务定义和服务实现不一致,那就会出现异常。
注意:这里的异常并不是
SCA
标准中所提到的,因为
SCA
只给出了规范,很多厂商的实现都不太一样,对于上述问题的处理可能也不一样。在以后的章节文章中,还会出现一些这种情况,在
SCA
标准没有明确指明的情况下,我都是以个人的实现来处理的,待
SCA
完善后再进行标准处理。对于上面情况,我在实现这个简单的
SCA
容器时,将这个情况看成是异常:
@Service(interfaces
=
{TestService1.
class
,TestService2.
class
})
public
class
TestServiceImpl2
implements
TestService1 {
public
void
print(String printString) {
System.out.println(
"
example2 print
"
+
printString );
}
}
以下调用方式会出现异常:
TestService2 service3
=
(TestService2) context.locateService(
"
TestService2
"
);
service3.invoke();
4
.通过配置文件来生命服务以及实现
SCA
中可以根据配置文件来对服务进行描述。
描述服务接口的是一个后缀名为
componentType
的
XML
文件,下面我们给出一个简单的例子:
<?
xml version="1.0" encoding="ASCII"
?>
<
componentType
xmlns
="http://www.osoa.org/xmlns/sca/0.9"
>
<
service
name
="TestService3"
>
<
interface
.java interface
="org.uxteam.sca.example3.TestService3"
/>
</
service
>
<
service
name
="TestService4"
>
<
interface
.java interface
="org.uxteam.sca.example3.TestService4"
/>
</
service
>
</
componentType
>
上面的这个
XML
指明了服务的名称以及服务对应的接口类:
第一个服务为
TestService3
,对应得是一个
Java
接口,接口类得全路径是
org.uxteam.sca.example3.TestService3
第二个服务为
TestService4
,对应的是一个
Java
接口,类路径为
org.uxteam.sca.example3.TestService4
一般情况下,该“组件描述”文件是和实现类放在一个目录下的,文件名同实现类文件名相同,只是后缀名改为
componentType
。
componentType
文件只是描述了服务接口,但是服务实现并没有给出。
其实服务实现的描述是在
.module
文件中给出的。
.module
文件指明在
componentType
文件中给出的服务接口的实现类,如下:
<?
xml version="1.0" encoding="ASCII"
?>
<
module
xmlns
="http://www.osoa.org/xmlns/sca/0.9"
name
="scaexample"
>
<
component
name
="TestService3"
>
<
implementation
.java class
="org.uxteam.sca.example3.TestServiceImpl"
/>
</
component
>
<
component
name
="TestService4"
>
<
implementation
.java class
="org.uxteam.sca.example3.TestServiceImpl"
/>
</
component
>
</
module
>
这个文件中,将服务名和组件名对应了起来,比如第一个组件是
TestService3
,它是一个
Java
实现,并且类路径是
org.uxteam.sca.example3.TestServiceImpl
。同理,第二个组件也如此。
我在实现这个简单的
SCA
容器时规定,
module
文件必须放置在
bin
目录下(当然,其他的
SCA
容器如何规定我就不得而知了)
当
SCA
容器启动得时候,会去解析这几个文件,如果文件无误,那
SCA
就会开始维护配置文件中定义得服务了。我们同样可以去定位、调用这些服务:
SCA sca
=
new
UxTeamSCA();
sca.start();
ModuleContext context
=
CurrentModuleContext.getContext();
TestService3 service
=
(TestService3)context.locateService(
"
TestService3
"
);
service.invoke();
TestService4 service1
=
(TestService4)context.locateService(
"
TestService4
"
);
service1.execute();
5
.结束语
通过上面的介绍希望能让网友们对
SCA
有一个比较清晰简单的认识。而本人实现的
SCA
容器目前来说还很幼稚,我会随着对该
SCA
文章的更新来完善我的
SCA
容器。我本人希望能借此文章抛砖引玉,各位达人请多多指点,有错误的地方还请大家指正。
下一章节我们来讲服务的属性和引用
代码第一部分下载
代码第二部分下载
代码第三部分下载