sphinx4 如何通过反射创建对象

前一篇我们介绍了XML文件的解析过程,解析后的数据保存在rawPropertyMap这个Map中,数据解析完后,那么是sphinx4是如何进行创建对象的呢?


回顾我们的HelloWorld Demo,是通过ConfigurationManager的lookup方法来得到某个组件的:


Recognizer recognizer = (Recognizer) cm.lookup("recognizer");


下面我们看下lookup这个方法:


public Configurable lookup(String instanceName) throws InternalConfigurationException {


       // apply all new properties to the model

       instanceName = getStrippedComponentName(instanceName);


       PropertySheet ps = getPropertySheet(instanceName);

       if (ps == null)

               return    null;


       if (showCreations)

               getRootLogger().config("Creating: " + instanceName);


       return ps.getOwner();

}


这个方法的参数是一个String,也就是之前解析得到的对象实例名称,返回类型是一个Configurable

Configurable是一个接口,它有一个抽象方法public    void newProperties(PropertySheet ps):


public    interface Configurable {


   public void newProperties(PropertySheet ps) throws PropertyException;


}


当配置属性发生变化的时候,会回调newProperties这个方法,显然所有用到的组件都实现了Configurable接口,这样在调用lookup方法的时候才能进行强制转换。


继续回到lookup方法中来,我们看下getStrippedComponentName方法:


public String getStrippedComponentName(String propertyName) {


   assert propertyName != null;


   while (propertyName.startsWith("$"))

           propertyName =     globalProperties.get(ConfigurationManagerUtils.stripGlobalSymbol(propertyName)).toString();


       return propertyName;

}

这个方法很简单,因为在xml文件中属性经常会引用到之前定义过的变量,引用的时候使用的是${}这种形式,这个方法就是对这种形式进行解析而已。


再看看getPropertySheet这个方法:


public PropertySheet getPropertySheet(String instanceName) {


       if (!symbolTable.containsKey(instanceName)) {

                   // 如果不在symbol table中,构造

                   RawPropertyData rpd = rawPropertyMap.get(instanceName);

           if (rpd != null) {

                       String className = rpd.getClassName();

                       try {

                           // 根据className 获取到它对应的Class

                           Class<?> cls = Class.forName(className);

       

                           // now load the property-sheet by using the class annotation

                           PropertySheet propertySheet = new PropertySheet(cls.asSubclass(Configurable.class), instanceName, this, rpd);

       

                           symbolTable.put(instanceName, propertySheet);

       

                       } catch (ClassNotFoundException e) {

                           System.err.println("class not found !" + e);

                       } catch (ClassCastException e) {

                           System.err.println("can not cast class !" + e);

                       } catch (ExceptionInInitializerError e) {

                           System.err.println("couldn't load class !" + e);

                       }

                   }

               }

       

           return    symbolTable.get(instanceName);

   }

这个方法首先从存放解析数据的rawPropertyMap中,通过实例名称查找对应的属性数据

RawPropertyData。然后通过RawPropertyData中的className得到它的Class,再根据Class,instanceName,rawPropertyMap等参数创建一个PropertySheet,同时把创建好的PropertySheet保存到symbolTable进行缓存,最终返回symbolTable中的PropertySheet对象。


lookup最后会调用PropertySheet的getOwner方法返回一个Configurable对象,我们分析一下getOwner方法:


public synchronized Configurable getOwner() {


       try {

       

           if (!isInstanciated()) {

                       // ensure that all mandatory properties are set before instantiating the component

                       Collection<String> undefProps = getUndefinedMandatoryProps();

                   if (!undefProps.isEmpty()) {

                               throw new InternalConfigurationException(getInstanceName(),

                                   undefProps.toString(), "not all mandatory properties are defined");

                       }

       

                   owner = ownerClass.newInstance();

                   owner.newProperties(this);

                   }

               } catch (IllegalAccessException e) {

                       throw new InternalConfigurationException(e, getInstanceName(), null, "Can't access class " + ownerClass);

               } catch (InstantiationException e) {

                       throw new InternalConfigurationException(e, getInstanceName(), null, "Can't instantiate class " + ownerClass);

               }

       

       return owner;

   }


此方法最重要的就是这两句:


owner = ownerClass.newInstance();

根据Class,通过反射来创建对象


owner.newProperties(this);

因为属性发生了变化,回调newProperties方法。



以上就是sphinx4创建对象的整个流程,本质上就是通过反射来实现的,只是加了一些自己的封装而已。




你可能感兴趣的:(java,语音识别,sphinx4)