1.服務屬性配置
在SCA中,服務可以定義自己的屬性,利用@Property標記即可,@Property標記具有兩個屬性參數:
1) name 屬性的名稱,一個服務中屬性名稱是唯一的,如果重復出現多次,則多出現的屬性會被忽略
2) required 表示屬性是否需要配置,它接受的是bool類型的值
@Property標記需要在我們定義的服務實現類中使用,而且需要標記在字段(Field)或者Setter方法上,這里需要注意的是,所謂的Setter方法就是我們使用的Javabean中定義的Setter方法,在SCA容器中,這種方法也是可以視為屬性。
服務屬性定義后,SCA容器在實例化服務時,會主動去初始化那些標記了@Property的字段以及方法,對于標記的字段,無論是什么樣的訪問關鍵字,甚至是private的,SCA容器也能對其進行賦植,同樣Setter方法也類似。
如果我們在Java實現類中定義屬性,可以像如下代碼中所寫那樣定義:
上面代碼中,分別是給字段以及一個方法標記了@Property,而如果我們將屬性定義寫到componentType文件中,對應上述代碼同等效應的如下所示:
而在目前本人實現的SCA容器中,對于上面這種required值為false,并且沒有給出默認值的屬性,初始化服務實例的時候是不會將屬性設值的,如果要進行屬性設值,那需要修改上面的componentType代碼:
這里需要注意的是,SCA規范中,對于屬性值類型有一定的限制,它規定:屬性值只能是Java的簡單基礎類型:int,short.....或者是對應的一些對象類型:Integer,String....,而對于復雜類型的值,只能是SDO類型或者是JAXB類型的。本人實現的這個容器,目前只對SDO類型做檢測,對于JAXB生成的對應并不在考慮范圍內。
服務的屬性除了可以定義單個值外,還可以將屬性值類型改成數組,或者是從Collection繼承下來的java實現類型,比如ArrayList,HashSet,LinkedList等,這一類數組以及Collection接口定義的屬性,在配置文件中的many值是為true的:
注意,如果我們想要利用List等Collection接口類型去定義many屬性,并且我們可能給出了一個默認值,這就需要我們主動去定義Collection中類型的泛型了,如同上面代碼中所寫的,stringList屬性是一個List類型的,而List放置的是String類型的對象。
就如上一次我們所提到的定義Java服務那樣,服務屬性定義也是可以從標記和配置文件中進行配置,但是如果有沖突的地方是以Java代碼標記的為主。
我們對于上面的屬性定義可以通過module文件定義它們,我本人認為在module文件中定義屬性,在初始化設置值的時候是很重要的,因為很多情況下,module配置文件才是實例化服務的一個參考標準:
2.服務的引用
服務引用其實應該算是服務訪問的一種方式。
服務引用其實是指在服務實現中,通過字段或者是Setter方法去引用另外一個服務。引用是利用@Reference在Java代碼中注釋在字段或者Setter方法上定義的,或者是在componentType文件中加入<reference>元素:
@Reference具有兩個屬性:name和required,他們的作用類似于@Property屬性參數的作用。
如果定義好了@Reference,并且給出的required值為true,那SCA容器在實例化該服務的時候,會將引用服務一同實例化——盡管我們并沒有給這些字段定義值。
同@Property一樣,我們也可以將這些引用字段設為數組或者是Collection接口類型。如果將服務定義的引用體現在module文件中,是如下所寫:
從上面的文件可以看出,設置引用的時候,引用服務的值就是某個服務的name值,如果我們在設置引用的時候,并沒有將該引用類型設置為服務,在本人實現的SCA容器中,是無法對引用實例化的。
在實例化引用時,其實就是在實例化一個服務,這就會出現如下面的特殊情況:
引用出現環狀 比如A引用B,B應用了C,C又引用了A
如果是這種引用,那在沒有任何對服務生命周期管理的情況下,或者說服務都是無狀態的(關于服務的生命周期會在以后的章節中講述),也就是說,沒實例化一個服務,那它的引用也會重新實例化。
那如果在環狀引用的情況下,不難看出,會出現死循環的情況。而真對這種情況,本人實現的SCA容器會提示環狀引用的出現,并且將整個引用環的最后一個節點的引用設置為NULL
3.小結
在SCA中,服務的屬性定義和引用和Spirng的Bean管理極其相似,但是也有不同的地方。在SCA中,服務除了作為一個單獨的功能節點存在外,它和其他服務之間的引用也是很重要的,這使得服務并不是純粹意義上的獨立,服務和服務之間建立起了一定的聯系。服務屬性的定義為動態初始化服務實例提供了可能。不管是服務屬性還是服務引用,他們都是采用了依賴注入的思想,通過注入來獲得更多的靈活性和擴展性。
本人水平有限,如有錯誤的地方還請達人指點。
代碼第一部分下載
代碼第二部分下載
代碼第三部分下載
在SCA中,服務可以定義自己的屬性,利用@Property標記即可,@Property標記具有兩個屬性參數:
1) name 屬性的名稱,一個服務中屬性名稱是唯一的,如果重復出現多次,則多出現的屬性會被忽略
2) required 表示屬性是否需要配置,它接受的是bool類型的值
@Property標記需要在我們定義的服務實現類中使用,而且需要標記在字段(Field)或者Setter方法上,這里需要注意的是,所謂的Setter方法就是我們使用的Javabean中定義的Setter方法,在SCA容器中,這種方法也是可以視為屬性。
服務屬性定義后,SCA容器在實例化服務時,會主動去初始化那些標記了@Property的字段以及方法,對于標記的字段,無論是什么樣的訪問關鍵字,甚至是private的,SCA容器也能對其進行賦植,同樣Setter方法也類似。
如果我們在Java實現類中定義屬性,可以像如下代碼中所寫那樣定義:
@Service(Service1.
class
)
public ? class ?Service1Impl? implements ?Service1?{
????@Property
???? private ? int ?intValue;
?? @Property
???? public ? void ?setIntegerValue(Integer?integerValue){
???????? this .integerValue? = ?integerValue;
????}
}
public ? class ?Service1Impl? implements ?Service1?{
????@Property
???? private ? int ?intValue;
?? @Property
???? public ? void ?setIntegerValue(Integer?integerValue){
???????? this .integerValue? = ?integerValue;
????}
}
上面代碼中,分別是給字段以及一個方法標記了@Property,而如果我們將屬性定義寫到componentType文件中,對應上述代碼同等效應的如下所示:
<?
xml?version="1.0"?encoding="ASCII"
?>
< sca:componentType? xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" ?xmlns:sca ="http://www.osoa.org/xmlns/sca/0.9" >
?? < sca:service? name ="Service2" >
???? < sca:interface? xsi:type ="sca:JavaInterface"??
????????????????????? interface="org.uxteam.sca.example.property.Service2"/>
?? </ sca:service >
?? < sca:property? many ="false" ?name ="intValue" ?required ="false" ?type ="int" ?/ >
?? ? < sca:property? many ="false" ?name ="integerValue" ?required ="false"??
???????????????????? type="java.lang.Integer"?/>
</ sca:componentType >
< sca:componentType? xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" ?xmlns:sca ="http://www.osoa.org/xmlns/sca/0.9" >
?? < sca:service? name ="Service2" >
???? < sca:interface? xsi:type ="sca:JavaInterface"??
????????????????????? interface="org.uxteam.sca.example.property.Service2"/>
?? </ sca:service >
?? < sca:property? many ="false" ?name ="intValue" ?required ="false" ?type ="int" ?/ >
?? ? < sca:property? many ="false" ?name ="integerValue" ?required ="false"??
???????????????????? type="java.lang.Integer"?/>
</ sca:componentType >
而在目前本人實現的SCA容器中,對于上面這種required值為false,并且沒有給出默認值的屬性,初始化服務實例的時候是不會將屬性設值的,如果要進行屬性設值,那需要修改上面的componentType代碼:
<?
xml?version="1.0"?encoding="ASCII"
?>
< sca:componentType? xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" ?xmlns:sca ="http://www.osoa.org/xmlns/sca/0.9" >
?? < sca:service? name ="Service2" >
???? < sca:interface? xsi:type ="sca:JavaInterface"??
???????????????????? interface="org.uxteam.sca.example.property.Service2"/>
?? </ sca:service >
?? < sca:property? many ="false" ?name ="intValue" ?required ="true"??
?????????????????? type="int"?default="100"/>
?? ?? < sca:property? many ="false" ?name ="integerValue" ?required ="true"??
????????????????????? type="java.lang.Integer"?default="1234"/>
</ sca:componentType >
< sca:componentType? xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" ?xmlns:sca ="http://www.osoa.org/xmlns/sca/0.9" >
?? < sca:service? name ="Service2" >
???? < sca:interface? xsi:type ="sca:JavaInterface"??
???????????????????? interface="org.uxteam.sca.example.property.Service2"/>
?? </ sca:service >
?? < sca:property? many ="false" ?name ="intValue" ?required ="true"??
?????????????????? type="int"?default="100"/>
?? ?? < sca:property? many ="false" ?name ="integerValue" ?required ="true"??
????????????????????? type="java.lang.Integer"?default="1234"/>
</ sca:componentType >
這里需要注意的是,SCA規范中,對于屬性值類型有一定的限制,它規定:屬性值只能是Java的簡單基礎類型:int,short.....或者是對應的一些對象類型:Integer,String....,而對于復雜類型的值,只能是SDO類型或者是JAXB類型的。本人實現的這個容器,目前只對SDO類型做檢測,對于JAXB生成的對應并不在考慮范圍內。
服務的屬性除了可以定義單個值外,還可以將屬性值類型改成數組,或者是從Collection繼承下來的java實現類型,比如ArrayList,HashSet,LinkedList等,這一類數組以及Collection接口定義的屬性,在配置文件中的many值是為true的:
<?
xml?version="1.0"?encoding="ASCII"
?>
< sca:componentType? xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" ?xmlns:sca ="http://www.osoa.org/xmlns/sca/0.9" >
?? < sca:service? name ="Service2" >
???? < sca:interface? xsi:type ="sca:JavaInterface"??
?????????????????????? interface="org.uxteam.sca.example.property.Service2"/>
?? </ sca:service >
?? < sca:property? many ="true" ?name ="boolValues" ?required ="true"??
?????????????????? type="boolean"?default="false"/>
?? < sca:property? many ="true" ?name ="stringList" ?required ="true"??
?????????????????? type="java.lang.String"?default="firstString"/>
</ sca:componentType >
< sca:componentType? xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" ?xmlns:sca ="http://www.osoa.org/xmlns/sca/0.9" >
?? < sca:service? name ="Service2" >
???? < sca:interface? xsi:type ="sca:JavaInterface"??
?????????????????????? interface="org.uxteam.sca.example.property.Service2"/>
?? </ sca:service >
?? < sca:property? many ="true" ?name ="boolValues" ?required ="true"??
?????????????????? type="boolean"?default="false"/>
?? < sca:property? many ="true" ?name ="stringList" ?required ="true"??
?????????????????? type="java.lang.String"?default="firstString"/>
</ sca:componentType >
@Service(Service1.
class
)
public ? class ?Service1Impl? implements ?Service1?{
????@Property
???? private ? boolean []?boolValues;
????@Property
???? private ?List < String > ?stringList;
???? private ?Integer?integerValue;
}
public ? class ?Service1Impl? implements ?Service1?{
????@Property
???? private ? boolean []?boolValues;
????@Property
???? private ?List < String > ?stringList;
???? private ?Integer?integerValue;
}
注意,如果我們想要利用List等Collection接口類型去定義many屬性,并且我們可能給出了一個默認值,這就需要我們主動去定義Collection中類型的泛型了,如同上面代碼中所寫的,stringList屬性是一個List類型的,而List放置的是String類型的對象。
就如上一次我們所提到的定義Java服務那樣,服務屬性定義也是可以從標記和配置文件中進行配置,但是如果有沖突的地方是以Java代碼標記的為主。
我們對于上面的屬性定義可以通過module文件定義它們,我本人認為在module文件中定義屬性,在初始化設置值的時候是很重要的,因為很多情況下,module配置文件才是實例化服務的一個參考標準:
<?
xml?version="1.0"?encoding="ASCII"
?>
< sca:module? xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" ?xmlns:sca ="http://www.osoa.org/xmlns/sca/0.9" ?name ="test.module" >
?? < sca:component? name ="Service1" >
???? < sca:implementation? xsi:type ="sca:JavaImplementation" ?class ="org.uxteam.sca.example.property.Service1Impl" />
?? </ sca:component >
?? < sca:component? name ="Service2" >
???? < sca:implementation? xsi:type ="sca:JavaImplementation" ?class ="org.uxteam.sca.example.property.Service2" />
???? < sca:properties >
?????? < intValue > 100 </ intValue >
?????? < floatValue > 0.01 </ floatValue >
?????? < doubleValue > 0.01 </ doubleValue >
?????? < longValue > 1000000 </ longValue >
?????? < boolValues > false </ boolValues >
?????? < stringList > firstString </ stringList >
?????? < integerValue > 1234 </ integerValue >
???? </ sca:properties >
?? </ sca:component >
</ sca:module >
< sca:module? xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" ?xmlns:sca ="http://www.osoa.org/xmlns/sca/0.9" ?name ="test.module" >
?? < sca:component? name ="Service1" >
???? < sca:implementation? xsi:type ="sca:JavaImplementation" ?class ="org.uxteam.sca.example.property.Service1Impl" />
?? </ sca:component >
?? < sca:component? name ="Service2" >
???? < sca:implementation? xsi:type ="sca:JavaImplementation" ?class ="org.uxteam.sca.example.property.Service2" />
???? < sca:properties >
?????? < intValue > 100 </ intValue >
?????? < floatValue > 0.01 </ floatValue >
?????? < doubleValue > 0.01 </ doubleValue >
?????? < longValue > 1000000 </ longValue >
?????? < boolValues > false </ boolValues >
?????? < stringList > firstString </ stringList >
?????? < integerValue > 1234 </ integerValue >
???? </ sca:properties >
?? </ sca:component >
</ sca:module >
2.服務的引用
服務引用其實應該算是服務訪問的一種方式。
服務引用其實是指在服務實現中,通過字段或者是Setter方法去引用另外一個服務。引用是利用@Reference在Java代碼中注釋在字段或者Setter方法上定義的,或者是在componentType文件中加入<reference>元素:
@Service(TestService.
class
)
public ? class ?TestServiceimpl? implements ?TestService?{
????@Reference(required = true )
???? private ?TestService1?a;
????
???? private ?TestService1?testService2;
????
???? public ? void ?print()?{
????????System.out.println( " TestService?Print " );
????????testService2.print();
????}
????@Reference(required = true )
???? public ? void ?setTestService2(TestService1?testService2)?{
???????? this .testService2? = ?testService2;
????}
}
public ? class ?TestServiceimpl? implements ?TestService?{
????@Reference(required = true )
???? private ?TestService1?a;
????
???? private ?TestService1?testService2;
????
???? public ? void ?print()?{
????????System.out.println( " TestService?Print " );
????????testService2.print();
????}
????@Reference(required = true )
???? public ? void ?setTestService2(TestService1?testService2)?{
???????? this .testService2? = ?testService2;
????}
}
<?
xml?version="1.0"?encoding="ASCII"
?>
< sca:componentType? xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" ?xmlns:sca ="http://www.osoa.org/xmlns/sca/0.9" >
?? < sca:service? name ="TestService" >
???? < sca:interface? xsi:type ="sca:JavaInterface" ?interface ="org.uxteam.sca.example.reference.TestService" />
?? </ sca:service >
?? < sca:reference? name ="a" ? >
???? < sca:interface? xsi:type ="sca:JavaInterface" ?interface ="org.uxteam.sca.example.reference.TestService1" />
?? </ sca:reference >
?? < sca:reference? name ="testService2" ? >
???? < sca:interface? xsi:type ="sca:JavaInterface" ?interface ="org.uxteam.sca.example.reference.TestService1" />
?? </ sca:reference >
</ sca:componentType >
< sca:componentType? xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" ?xmlns:sca ="http://www.osoa.org/xmlns/sca/0.9" >
?? < sca:service? name ="TestService" >
???? < sca:interface? xsi:type ="sca:JavaInterface" ?interface ="org.uxteam.sca.example.reference.TestService" />
?? </ sca:service >
?? < sca:reference? name ="a" ? >
???? < sca:interface? xsi:type ="sca:JavaInterface" ?interface ="org.uxteam.sca.example.reference.TestService1" />
?? </ sca:reference >
?? < sca:reference? name ="testService2" ? >
???? < sca:interface? xsi:type ="sca:JavaInterface" ?interface ="org.uxteam.sca.example.reference.TestService1" />
?? </ sca:reference >
</ sca:componentType >
@Reference具有兩個屬性:name和required,他們的作用類似于@Property屬性參數的作用。
如果定義好了@Reference,并且給出的required值為true,那SCA容器在實例化該服務的時候,會將引用服務一同實例化——盡管我們并沒有給這些字段定義值。
同@Property一樣,我們也可以將這些引用字段設為數組或者是Collection接口類型。如果將服務定義的引用體現在module文件中,是如下所寫:
<?
xml?version="1.0"?encoding="ASCII"
?>
< sca:module? xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" ?xmlns:sca ="http://www.osoa.org/xmlns/sca/0.9" ?name ="t" >
?? ?? < sca:component? name ="TestService1" >
???? < sca:implementation? xsi:type ="sca:JavaImplementation" ?class ="org.uxteam.sca.example.reference.TestService1Impl" />
?? </ sca:component >
?? < sca:component? name ="TestService" >
???? < sca:implementation? xsi:type ="sca:JavaImplementation" ?class ="org.uxteam.sca.example.reference.TestServiceimpl" />
???? < sca:references >
?????? < a > TestService1 </ a >
?????? < testService2 > TestService1 </ testService2 >
???? </ sca:references >
?? </ sca:component >
</ sca:module >
< sca:module? xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" ?xmlns:sca ="http://www.osoa.org/xmlns/sca/0.9" ?name ="t" >
?? ?? < sca:component? name ="TestService1" >
???? < sca:implementation? xsi:type ="sca:JavaImplementation" ?class ="org.uxteam.sca.example.reference.TestService1Impl" />
?? </ sca:component >
?? < sca:component? name ="TestService" >
???? < sca:implementation? xsi:type ="sca:JavaImplementation" ?class ="org.uxteam.sca.example.reference.TestServiceimpl" />
???? < sca:references >
?????? < a > TestService1 </ a >
?????? < testService2 > TestService1 </ testService2 >
???? </ sca:references >
?? </ sca:component >
</ sca:module >
從上面的文件可以看出,設置引用的時候,引用服務的值就是某個服務的name值,如果我們在設置引用的時候,并沒有將該引用類型設置為服務,在本人實現的SCA容器中,是無法對引用實例化的。
在實例化引用時,其實就是在實例化一個服務,這就會出現如下面的特殊情況:
引用出現環狀 比如A引用B,B應用了C,C又引用了A
如果是這種引用,那在沒有任何對服務生命周期管理的情況下,或者說服務都是無狀態的(關于服務的生命周期會在以后的章節中講述),也就是說,沒實例化一個服務,那它的引用也會重新實例化。
那如果在環狀引用的情況下,不難看出,會出現死循環的情況。而真對這種情況,本人實現的SCA容器會提示環狀引用的出現,并且將整個引用環的最后一個節點的引用設置為NULL
3.小結
在SCA中,服務的屬性定義和引用和Spirng的Bean管理極其相似,但是也有不同的地方。在SCA中,服務除了作為一個單獨的功能節點存在外,它和其他服務之間的引用也是很重要的,這使得服務并不是純粹意義上的獨立,服務和服務之間建立起了一定的聯系。服務屬性的定義為動態初始化服務實例提供了可能。不管是服務屬性還是服務引用,他們都是采用了依賴注入的思想,通過注入來獲得更多的靈活性和擴展性。
本人水平有限,如有錯誤的地方還請達人指點。
代碼第一部分下載
代碼第二部分下載
代碼第三部分下載