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
的值來指定的,請看下面代碼:
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.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.....}) ,這種描述方式可以一次性定義多個服務,當然了,服務實現也還只是一個而已。
下面代碼展示了如果定義多個服務:
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
:
????????????
??TestService1?service1? = ?(TestService1)?context.locateService( " TestService1 " );?
??????????????service1.print( " print?it " );?
? TestService2?service2? = ?(TestService2)?context.locateService( " TestService2 " );?
??????????????service2.invoke();?
如果我們在定義服務的時候,出現了服務定義和服務實現不一致,那就會出現異常。
注意:這里的異常并不是
SCA
標準中所提到的,因為
SCA
只給出了規范,很多廠商的實現都不太一樣,對于上述問題的處理可能也不一樣。在以后的章節文章中,還會出現一些這種情況,在
SCA
標準沒有明確指明的情況下,我都是以個人的實現來處理的,待
SCA
完善后再進行標準處理。對于上面情況,我在實現這個簡單的
SCA
容器時,將這個情況看成是異常:
public ? class ?TestServiceImpl2? implements ?TestService1??{?
??
??????? public ? void ?print(String?printString)?{?
??????????????System.out.println( " example2?print? " ? + ?printString?);?
???????}?
??
}?
?以下調用方式會出現異常:
??????????????service3.invoke();?
4
.通過配置文件來生命服務以及實現
SCA 中可以根據配置文件來對服務進行描述。
描述服務接口的是一個后綴名為
componentType
的
XML
文件,下面我們給出一個簡單的例子:
< 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
文件中給出的服務接口的實現類,如下:
< 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.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
容器。我本人希望能借此文章拋磚引玉,各位達人請多多指點,有錯誤的地方還請大家指正。