前面只是简单介绍了sphinx4如何通过配置文件中的实例名称,利用反射来创建对象。对象的创建本身比较简单,但是对象属性之间的依赖关系就变得很复杂了。一个对象往往会引用到很多其他属性,而属性的类型可以是基本类型,也可以是类类型。


在sphinx4中,一个对象依赖的属性是通过<property>和<propertyList>这两个标签来实现的。我们主要介绍一下<property>,<propertyList>用法类似,不再介绍。下面我们还是以HelloWord这个例子为切入点进行分析:


首先我们看一下 helloworld.config.xml配置文件中recognizer的相关配置信息:


<component name="recognizer" type="edu.cmu.sphinx.recognizer.Recognizer">

       <property name="decoder" value="decoder"/>

       <propertylist name="monitors">

               <item>accuracyTracker </item>

               <item>speedTracker </item>

               <item>memoryTracker </item>

       </propertylist>

</component>


这个组件的名称是“recognizer”,对应具体的java类的名称是“edu.cmu.sphinx.recognizer.Recognizer”,解析的时候保存在RawPropertyData的className成员变量中,sphinx4就是利用它,然后通过反射的方式来创建Recognizer对象的。


下面重点分析一下recognizer的属性<property>


在recognizer中,有一个属性它的name为decoder,value为decoder:


<property name="decoder" value="decoder"/>


虽然这两个值都是decoder,但是他们有着本质的区别。name="decoder" 和Recognizer这个类中的成员变量是对应的,我们看下Recognizer中的定义:


public class Recognizer implements Configurable, ResultProducer {


/** The property for the decoder to be used by this recognizer. */

// Decoder成员变量,作为recognizer的一个属性

@S4Component(type = Decoder.class)

public final static String PROP_DECODER = "decoder";


/** The property for the set of monitors for this recognizer */

@S4ComponentList(type = Monitor.class)

public final static String PROP_MONITORS = "monitors";


       //省略其他代码。。。

}

name="decoder"对应 public final static String PROP_DECODER = "decoder",这个两个必须相同,否则无法通过注解的方式对它进行赋值。


value="decoder"表示的是在这个xml配置文件中,查找叫着decode的组件,如下:


<component name="decoder" type="edu.cmu.sphinx.decoder.Decoder">

       <property name="searchManager" value="searchManager"/>

</component>



我们看到在Recognizer中,成员变量PROP_DECODER有一个注解:


@S4Component(type = Decoder.class)

publicfinalstatic String PROP_DECODER = "decoder";


这个注解S4Component的type设置为 Decoder.class,这样Recognizer引用到的成员变量decoder,实际上对应的是edu.cmu.sphinx.decoder.Decoder这个类,但是这个在配置文件中只是一个字符串,还必须通过反射来实际创建这个对象。


那么在Recognizer中是如何得到这个Decoder对象呢?


我们知道,受配置文件管理的对象都实现了Configurable接口,Recognizer 也不例外,同时必须实现其中的抽象方法newProperties:


public void newProperties(PropertySheet ps) throws PropertyException {

        // ×××

        decoder = (Decoder) ps.getComponent(PROP_DECODER);


       // 属性监听器

       monitors = ps.getComponentList(PROP_MONITORS, Monitor.class);


       // 类的实例名称

       name = ps.getInstanceName();

}


这个方法在属性发生变化的时候会自动回调,同时把新的属性对象通过PropertySheet传递进来,在这个方法中有这么一句:


decoder = (Decoder) ps.getComponent(PROP_DECODER);


即通过属性名称PROP_DECODER在PropertySheet属性对象中,查找name为decoder这个属性对应的value,这个value就是Decoder的实例对象,因为getComponent返回的是Configurable类型,所以进行了强制转换。


当然属性的类型不止这一种,还有int,String等,相应的查找方法就是getInt,getString,大家可以在PropertySheet这个类中进行详细查看。


今天先暂时介绍这些,总结一下:

sphinx4中,受配置文件管理的对象都实现了Configurable这个接口,在回调函数newProperties中,通过PropertySheet把它引用到的其他成员给传递进来,我们可以通过PropertySheet的getComponent,getInt等方法来获取这些成员的值。