Posted on 2006-08-16 11:58
Dart 阅读(2089)
评论(0) 编辑 收藏 所属分类:
SCA
1.服务属性配置
在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;
}
}
上面代码中,分别是给字段以及一个方法标记了@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容器中,对于上面这种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规范中,对于属性值类型有一定的限制,它规定:属性值只能是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
>
@Service(Service1.
class
)
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
>
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;
}
}
<?
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
>
@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
>
从上面的文件可以看出,设置引用的时候,引用服务的值就是某个服务的name值,如果我们在设置引用的时候,并没有将该引用类型设置为服务,在本人实现的SCA容器中,是无法对引用实例化的。
在实例化引用时,其实就是在实例化一个服务,这就会出现如下面的特殊情况:
引用出现环状 比如A引用B,B应用了C,C又引用了A
如果是这种引用,那在没有任何对服务生命周期管理的情况下,或者说服务都是无状态的(关于服务的生命周期会在以后的章节中讲述),也就是说,没实例化一个服务,那它的引用也会重新实例化。
那如果在环状引用的情况下,不难看出,会出现死循环的情况。而真对这种情况,本人实现的SCA容器会提示环状引用的出现,并且将整个引用环的最后一个节点的引用设置为NULL
3.小结
在SCA中,服务的属性定义和引用和Spirng的Bean管理极其相似,但是也有不同的地方。在SCA中,服务除了作为一个单独的功能节点存在外,它和其他服务之间的引用也是很重要的,这使得服务并不是纯粹意义上的独立,服务和服务之间建立起了一定的联系。服务属性的定义为动态初始化服务实例提供了可能。不管是服务属性还是服务引用,他们都是采用了依赖注入的思想,通过注入来获得更多的灵活性和扩展性。
本人水平有限,如有错误的地方还请达人指点。
代码第一部分下载
代码第二部分下载
代码第三部分下载