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
容器。我本人希望能借此文章拋磚引玉,各位達人請多多指點,有錯誤的地方還請大家指正。
下一章節我們來講服務的屬性和引用?
代碼第一部分下載
代碼第二部分下載
代碼第三部分下載