Describing your iPOJO component

本节描述iPOJO支持的不同的特性。本章目标是回答以下问题:“在我的ipojo组件描述中我能写些什么?”

+Core featues
核心的特性是由iPOJO运行时服务包支持的。你可以直接去使用它,当iPOJO运行时被部署后。

-服务依赖管理
依赖处理器管理OSGi服务的依赖/需求。它允许组件消费服务而无需去管理服务的发现、跟踪和绑定。处理器管理
了所有的交互和注入需求服务在组件中。

*service Requirement
1、什么是服务需求
一个需求表示一个需求的服务。因此,它管理服务的检索和服务的绑定。当一个实例需求一个服务时,处理器就直接注入一个服务对象到字段上,或者调用一个方法当相符的服务出现(或者消失)时。服务需求可以是:
〉简单/聚合:组件能要求一个或者多个服务供应者
〉托管/可选:一个组建可以定义一个可选的依赖
〉过滤:一个组件可以过滤出有效的供应者
〉动态/静态/动态-优先:组件可以指定绑定的策略
〉规范:依赖目标是符合某规范的服务供应者

2、动态与实例生命周期
在OSGi中,服务可以动态地出现和消失。这就暗示依赖可以指向一个动态出现或者消失的供应者。
因此,依赖需要通过跟踪每时每刻的可用服务来管理动态性。在任何时候,一个依赖可能是未解析的(比如,没有更多的供应者来满足需求)。在托管的需求情形下,实例就被成invalid(一个invalid的实例意味着没有从外部访问的能力,例如供应的服务将不再发布。)。如果一个服务,未满足的依赖服务出现时,实例将变成valid 。结果,依赖影响着实例的状态,并且当服务消失时,必须正确地管理OSGi动态性以允许实例完全的卸载。当托管的依赖不能被满足,实例将变成invalidated.

默认情况下,依赖是被动态管理的,尽管,iPOJO支持其他两种服务绑定风格。
〉静态:如果一个绑定的服务消失,实例将变成invalidated,并且不能重新变成validated(绑定中断)。
〉动态-优先:在每一次的注入中,最佳的供应者是被注入的,或者提供一个存储相应OSGi等级策略的数组。

*Service Requirement Injection Mechanisms
处理器可以管理2种类型的注入:
〉字段注入:一个字段包含了服务对象,当字段被使用时,一个合理的服务对象被注入。这种注入类型完全掩藏了动态性。
〉方法调用:当一个服务出现或者消失时,组件中的一个方法将被调用。每一个依赖,bind和unbind方法被调用,哟关于通知组件的事件。


此外,这两种注入类型可以合并起来,一个组件可以定义一个需求,同时包含字段和"binding"

*Field injection
假设一个Hello 服务,它提供了一个方法getMessage,返回一个"Hello Message"。下面的组件实现可以通过附加这个服务到字段上,然后通过字段使用服务。
public class HelloConsumer{
private Hello m_hello;
public doSomething(){
System.out.println(m_hello.getMessage());
}
}

本组件的metadata如下:
<component classname="...HelloConsumer">
<requires field="m_hello"/>
</component>

metadata包含来一个“requires”的元素(表示服务依赖)。这个元素有一个field属性。属性的值是HelloConsumer类中字段的名字m_hello。

*方法调用
第二种依赖机制是使用方法。通过此方法,动态性可以被开发者直接管理。每一个依赖可以被定义2个方法:
〉bind方法,当服务出现时调用
〉unbind方法,当服务消失时调用

此外,回调可以在组件的超类中(这种情况下,方法必须是public)。这些方法can hava one of these four signatures。
〉无参数:这个方法仅仅是通知(method())
〉服务对象:对象是服务对象(method(Service svc))
〉OSGi服务参考对象:服务参考对象出现或者消失(method(ServiceReference ref))
〉服务对象和服务参考对象(method(Service svc,ServiceReference ref))
〉服务对象和服务属性Map(method(Service svc,Map properties))
〉服务对象和服务属性Dictionary(method(Service svc,Dictionary properties))

下面的组件实现演示了使用该机制的实现样例。
public class HelloConsumer{
private Hello m_hello;

public void bindHello(Hello h){m_hello = h;}
public void unbindHello(){m_hello=h;}
public doSomething(){System.out.println(m_hello.getMessage());}
}

与组件对应的metadata内容如下:
<component classname="...HelloConsumer">
<requires>
<callback type="bind" method="bindHello">
<callback type="unbind" method="unbindHello">
</requires>
...
</component>

注意:bind和unbind方法可以使用其他名称。通过使用本机制,你需要确信动态管理的正确性。


*Field injections and Method invocations
上面谈到的两种机制可以一起使用。在这中情况下,字段将早于方法调用接收到服务对象。因此,如果字段被用于方法中,返回值将是最新的。下面的组件实现使用这个机制。
public class HelloConsumer{
private Hello m_hello;

public void bindHello(){System.out.println("Hello appears");}
public void unbindHello(){System.out.println("Hello disapears");}
public doSometing(){System.out.println(m_hello.getMessage());}
}
metadata文件内容如下:
<component classname="...HelloConsumer">
<requires field="m_hello">
<callback type="bind" method="bindHello">
<callback type="unbind" method="unbindHello">
</requires>
...
</component>

*Injection mechanisms & lazy object creation
iPOJO创建对象仅当需求时。当需要时,iPOJO调用实现类的构造方法。实现类可以使用字段需求,因为值已经注入。然而,方法依赖是在构造完成后被调用的。如果,服务早已经出现,而方法调用延迟与构造调用之后。

Some Examples
*simple Requirement
默认情况下,一个需求是托管的,没有过滤并且简单(非聚合).前面的例子中,已经演示了这种依赖。当服务出现和消失,服务的代替物被隐藏。字段附加到简单的需求点上,永远是一个满足的服务对象。做为一个简单的依赖,bind方法仅被调用一次,当服务出现或者POJO构造方法调用,服务可用。当服务消失,unbind方法被调用。而当其他可用服务有效时,bind方法就会被再次调用。如果其他服务供应者有效,这个调用将即可发生。在这种情况下,实例不是invalidated.

*Aggregate Requirement
当组件需求同一服务的多个供应者时,它定义一个聚合依赖。

+Agreegate Dependency with field injection
public class HelloConsumer {
private Hello m_hellos[];
public doSomething() {
for(int I = 0; I < m_hellos.length; i++) {
System.out.println(m_hellos[i].getMessage());
}
}
}

与组件对应的metadata:
<component classname="...HelloConsumer">
<requires field="m_hellos"/>
...
</component>

为字段希求声明一个聚合字段,你仅需要声明一个数组。iPOJO会创建并注入服务对象数组。iPOJO在字节码分析时发现依赖是聚

合的。

Synchronization

The synchronization is managed by iPOJO. As soon as you are 'touching' a dependency in a method, iPOJO ensure that you will keep these objects until the end of the method. Nested methods will share the same service object set.

字段注入的聚合依赖:list、vector、collection和set

public class HelloConsumer{
private List m_hellos;
public doSomethong(){
for(int i = 0; i< m_hellos.size();i++){
System.out.println((Hello)m_hellos.get(i)).getMessage());
}
}
}


组件metadata:
<component classname="...HelloConsumer">
<requires field="m_hellos" specification="o.a.f.i.Hello"/>
...
</component>

在本情况下,仅使用你需要支持的类型。iPOJO将会自动地理解它是一个聚合依赖。

%服务规范发现
服务规范(比如接口)不能够被发现,当使用这些类型时,字节码没有提供足够的信息。因此,你不得不指名需要服务的接口。(使用"specification"属性)在requirment中。

%iPOJO是如何为你管理同步的
As in the previous case, the synchronization is managed by iPOJO. As soon as you are touching a dependency in a method, iPOJO ensure that you will keep these objects until the end of the method. Nested methods will share the same service object set.


*Aggregate Dependency with method invocation
public class HelloConsumer{
private List m_hellos = new ArrayList();
private void bindHello(Hello h){m_hellos.add(h);}
private void unbindHello(Hello h){m_hellos.remove(h);}
public synchronized doSomething(){
for(int i=0;i<m_hellos.size();i++){
System.out.println(m_hellos.get(i).getMessage());

}
}
}

需求配置如下:

<requires aggregate="true">
<callback type="bind" method="bindHello">
<callback type="unbind" method="unbindHello">
</requires>


在这个情况下,iPOJO不能够监测到依赖是否为聚合,因此,你需要增加"aggregate"属性。bindHello和unbindHello将会在Hello服务出现或者消失时分别被调用。

Synchronization

To avoid the list modification during the loop, you need synchronized the block. Indeed, as the field is not an iPOJO requirement, iPOJO will not manage the synchronization.


*Optional Requirement (non-aggregate)
一个可选的需求不会invalidate实例,尽管供应者无效。因此,它可能会注入一个默认服务的实现,当没有实际的供应者存在的情况下。


+Optional Requirement with field injection
public class HelloConsumer{
private Hello m_hello;
public doSomething(){
System.out.println(m_hello.getMessage());
}
}


与这个组件对应的metadata可能如下:
<component classname="...HelloConsumer">
<requires field="m_hello" optioal="true"/>
</component>


为了声明一个可选的需求,拟需要增加'optional'属性。为了避免空指针异常,iPOJO注入一个Nullable对象到字段中,当服务供应者无效时。nullable对象实现了服务接口,但是没有任何逻辑。因此,它就可以被设定为服务的默认实现。
一个默认实现是这样一个类,它仅用于其他供应者服务无效的情况下。默认实现对象将会被nullabel对象取代。

*Optional Dependency with method invocation
public class HelloConsumer{
private Hello m_hello;
public void bindHello(Hello h){m_hello = h;}
public void unbindHello(){m_hello=null;}
public doSomething(){
if(m_hello != null){
System.out.println(m_hello.getMessage());
}
}
}

For this component, metadata should be:
<component classname="...HelloConsumer">
<requires optional="true">
<callback type="bind" method="bindHello">
<callback type="unbind" method="unbindHello">
</requires>
...
</component>


*Aggregate & Optional Requirement
一个依赖可以同时为聚合和可选
Aggregate & Optional Dependency with field injection

public class HelloConsumer {
private Hello m_hellos[];
public doSomething() {
for(int I = 0; I < m_hellos.length; i++) {
System.out.println(m_hellos[i].getMessage());
}
}
}
组件metadata内容如下:
<component classname="...HelloConsumer">
<requires field="m_hellos" optional="true"/>
...
</component>


为了声明一个可选的、聚合字段的需求,你需要在依赖metadata中写上optional属性。如果没有服务可用,iPOJO注入空的数组。


Aggregate & Optional Requirement with method invocation
public class HelloConsumer {
private List m_hellos<Hello> = new ArrayList<Hello>();
private void bindHello(Hello h) { m_hellos.add(h); }
private void unbindHello(Hello h) { m_hellos.remove(h); }
public synchronized doSomething() {
for(int I = 0; I < m_hellos.size(); i++) {
System.out.println(m_hellos.get(i).getMessage());
}
}
}
public class HelloConsumer { private List m_hellos<Hello> = new ArrayList<Hello>(); private void bindHello(Hello h) { m_hellos.add(h); } private void unbindHello(Hello h) { m_hellos.remove(h); } public synchronized doSomething() { for(int I = 0; I < m_hellos.size(); i++) { System.out.println(m_hellos.get(i).getMessage()); } } }

For this component, metadata could be:
<requires aggregate="true" optional="true">
<callback type="bind" method="bindHello">
<callback type="unbind" method="unbindHello">
</requires>


*Filtered Requirement
一个过滤的依赖应用了LDAP风格的过滤在服务供应上。iPOJO重用了OSGi的LDAP过滤能力。下面的metadata演示了如何使用过滤:
<component classname="...HelloConsumer">
<requires filter="(language=fr)">
<callback type="bind" method="bindHello"/>
<callback type="unbind" method="unbindHello"/s>
</requires>
</component>

为了增加一个filter,在requires中增加一个“filter”属性即可。iPOJO将选择符合过滤条件的供应者。

因此,过滤可以实例用于定制的实例。它有可能在组件的实例描述中去指定/更改/增加组件的过滤。当你想创建相同组件的不通实例时这将是很有用的,即使用不同的fileter。为了做到这一点,你必须使用"id"来区分你的依赖。接着,你可以在实例描述中采用依赖过滤,使用属性"requires.filters"。在这个属性中,你可以指定每个依赖的身份,通过id和新的filter值。

<component
className="org.apache.felix.ipojo.example.FilteredDependency"
name="FOO">
<requires field="m_foo" fiter="(foo.property=FOO)" id="id1">
<callback type="bind" method="bind"/>
<callback type="unbind" method="unbind"/>
</requires>
</component>

<instance name="FOO1" component="FOO"/>

<instance name="FOO2" component="FOO">

<property name="requires.filters">
<property name="id1" value="(foo.property=BAR)"/>
</property>
</instance>

<instance name="FOO3" component="FOO">
<property name="requires.filters">
<property name="id1" value="(foo.property=BAZ)"/>
</property>
</instance>

FOO组件类型定义一个"id1"id的服务依赖。这个依赖没有默认的filter。第一个实例是FOO组件的实例化,没有修改服务的依赖。第二个增加了一个过滤到服务声明上,目标供应者具有foo.property=BAR。最后一个增加了另外一个filter用于声明服务依赖。通过使用服务过滤自定义,它可以用于创建复杂的应用,在这里你可通过过滤后的实例避免绑定的问题。


*Targeting a specific provider
一个服务依赖可以选择特定的供应者。To achieve this,add a 'from' 属性在你的requirement描述中,如下:
<component classname="...HelloConsumer">
<requires from="MyHelloProvider">
<callback type="bind" method="bindHello"/>
<callback type="unbind" method="unbindHello"/>
</requires>
</component>

iPOJO把from属性影射为特定的过滤。|(instance.name=MyHelloProvider)(service.pid=MyHelloProvider).因此服务依赖仅当满足该过滤条件才能满足。

因此,from属性可以自定义实例化实例。它可以被specialize/change/add 一个component的“from”属性。它是有用处的,当你想去创建同一组件的不同实例时,只需使用不同的"from"条件。为了能完成之,你必须使用"id"属性表明你依赖的身份。然后,你可以采用“from”依赖在实例配置中,通过使用"requires.from"。在本属性中,你可以指定每一个依赖的身份和"from"值。

<component
className="org.apache.felix.ipojo.example.FilteredDependency"
name="FOO">
<requires field="m_foo" id="id1">
<callback type="bind" method="bind"/>
<callback type="unbind" method="unbind"/>
</requires>
</component>

<instance name="FOO1" component="FOO"/>

<instance name="FOO2" component="FOO">
<property name="requires.from">
<property name="id1" value="myprovider"/>
</property>
</instance>

<instance name="FOO3" component="FOO">
<property name="requires.from">
<property name="id1" value="myotherprovider"/>
</property>
</instance>

FOO组件类型定义服务的依赖,使用"id1"id。依赖默认使用from属性。第一个实例是一个FOO组件实例,没有修改任何依赖特性。第二个增加了from属性,来定义依赖目标的特性为myprovider。最后一个增加了另一个"from"条件来定义依赖属性。


*Binding Policies
在iPOJO中,有3种绑定策略受到支持:
〉Dynamic policy(default)
〉Static policy
〉Dynamic-priority


*Note about nullable object & default-implementation
实例的实现可以使用可选依赖,而无需检查。的确,当一个实例使用字段注入定义了一个可选的依赖,iPOJO会创建一个on the fly的实现了接口Nullable类(like mock)。因此,iPOJO不能返回一个服务给实例,做为可选依赖,它返回一个nullable对象。


A nullable object returns:

* Null when the method returns an object
* 0 when the method returns an int, log, byte, short, char, float or a double
* False when the method return a boolean

You can check if the returned object is a nullable object with the test: "myservice instanceof Nullable".

你可以禁止Nullabel模式(默认就是)。在本例中,iPOJO将注入null而非Nullabel对象。因此,你可以测试字段是否为null,就能知道服务是否可用。禁止Nullabel模式,你需要在服务依赖描述中增加“nullable=false”属性即可。


<component classname="...LogExample">
<requires field="m_log" optional="true" nullable="false"/>
...
</component>

可是,你可以为可选服务指定一个默认实现。在本例中,如果供应者没有发现,iPOJO将创建一个默认实现并注入。
default-implementation属性描你的实现类名称。给定的类当然是要实现需求的接口。

例如,下面的组件使用了一个Log服务依赖的默认实现:
<component classname="...LogExample">
<requires field="m_log" optional="true"
default-implementation=
"org.apache.felix.ipojo.example.default.MyLogService"/>
...
</component>

如果一个Log服务不可用,iPOJO创建“org.apache.felix.ipojo.example.default.MyLogService”对象。这个对象将取代Nullable对象。例如,默认实现可以在System.err流中打印消息。而nullable对象则不能。

*Note about Callbacks
依赖管理着2种回调:bind 和unbind.一个“bind”类型的回调,将在每次服务供应者满足时,并且绑定是必须的。
根据数据的依赖意味着:
〉简单依赖
〉聚合依赖


An unbind callback is called each time that a used service provider goes away. For a simple dependency this method is called each time that the used service provider goes away. For a multiple dependency this method is called each time that a service provider goes away.

The method can receive in argument the service object or the service reference (in order to obtain service properties). The bind methods are delayed since a POJO object is created.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值