OFBiz業(yè)務(wù)方法里面,當(dāng)執(zhí)行一個service的時候,通常采用如下的方式:

    LocalDispatcher dispatcher = dctx.getDispatcher();
    Map<String, Object> result = dispatcher.runSync(getServiceName(), getContext());

LocalDispatcher是本地調(diào)度器,實現(xiàn)服務(wù)的同步異步調(diào)度和定時任務(wù)的調(diào)度。與服務(wù)調(diào)度相關(guān)的類圖如下:



LocalDispatcher是一個接口,實例化的都是GenericDispatcher類,ContextFilter實現(xiàn)了Servlet Filter,會初始化一個GenericDispatcher,并將其存放在ServletContext中,以備整個應(yīng)用使用。
在請求處理過程中,如果遇到service的event,那么EventHandler會使用LocalDispatcher執(zhí)行service。
實際上GenericDispatcher只是一個Proxy,自己并不處理相關(guān)的調(diào)度工作,真正最苦最累的調(diào)度工作是由ServiceDispatcher完成的。下面具體研究一下Dispatcher同步和異步調(diào)用方法的實現(xiàn)代碼:

1.同步調(diào)用

通過dispatcher調(diào)用runSync方法,也即是調(diào)用GenericDispatcher的runSync方法:
    
        /**
         * @see org.ofbiz.service.LocalDispatcher#runSync(java.lang.String, java.util.Map)
         */
        public Map<String, Object> runSync(String serviceName, Map<String, ? extends Object> context)
        throws ServiceValidationException, GenericServiceException
        {
            ModelService service = ctx.getModelService(serviceName);
            return dispatcher.runSync(this.name, service, context);
        }

dispatcher實際是ServiceDispatcher對象。ServiceDispatcher的runSync方法有三百多行,比較復(fù)雜,
但最終調(diào)用service的是GenericEngine。

    GenericEngine engine = this.getGenericEngine(modelService.engineName);
    ……
    
    Map<String, Object> invokeResult = engine.runSync(localName, modelService, context);
  
GenericEngine是其工廠類GenericEngineFactory獲取的,這個Factory類非常簡單:

public class GenericEngineFactory {

    protected ServiceDispatcher dispatcher = null;
    protected Map<String, GenericEngine> engines = null;

    public GenericEngineFactory(ServiceDispatcher dispatcher) {
        this.dispatcher = dispatcher;
        engines = FastMap.newInstance();
    }

    /**
     * Gets the GenericEngine instance that corresponds to given the name
     *@param engineName Name of the engine
     *@return GenericEngine that corresponds to the engineName
     */
    public GenericEngine getGenericEngine(String engineName) throws GenericServiceException {
        Element rootElement = null;

        try {
            rootElement = ServiceConfigUtil.getXmlRootElement();
        } catch (GenericConfigException e) {
            throw new GenericServiceException("Error getting Service Engine XML root element", e);
        }
        Element engineElement = UtilXml.firstChildElement(rootElement, "engine", "name", engineName);

        if (engineElement == null) {
            throw new GenericServiceException("Cannot find a service engine definition for the engine name [" + engineName + "] in the serviceengine.xml file");
        }

        String className = engineElement.getAttribute("class");

        GenericEngine engine = engines.get(engineName);

        if (engine == null) {
            synchronized (GenericEngineFactory.class) {
                engine = engines.get(engineName);
                if (engine == null) {
                    try {
                        ClassLoader loader = Thread.currentThread().getContextClassLoader();
                        Class<?> c = loader.loadClass(className);
                        Constructor cn = c.getConstructor(ServiceDispatcher.class);
                        engine = (GenericEngine) cn.newInstance(dispatcher);
                    } catch (Exception e) {
                        throw new GenericServiceException(e.getMessage(), e);
                    }
                    if (engine != null) {
                        engines.put(engineName, engine);
                    }
                }
            }
        }

        return engine;
    }
}

從配置文件serviceengine.xml文件中獲取相應(yīng)的engine子類,如java的是org.ofbiz.service.engine.StandardJavaEngine
bsh的是org.ofbiz.service.engine.BeanShellEngine。

Java的StandardJavaEnignerunSync方法采用的是反射來執(zhí)行相應(yīng)的方法,如下:

        Class<?> c = cl.loadClass(this.getLocation(modelService));
            Method m = c.getMethod(modelService.invoke, DispatchContext.class, Map.class);
            result = m.invoke(null, dctx, context);
            
不同的Engine實現(xiàn)的方式不一樣。

2. 異步調(diào)用

異步調(diào)用怎么實現(xiàn)的呢?實現(xiàn)異步的原理就是啟動一個線程來執(zhí)行相應(yīng)的業(yè)務(wù)邏輯,原方法直接返回,從而實現(xiàn)異步。具體實現(xiàn)的時候可以根據(jù)實際情況而定,比如將業(yè)務(wù)邏輯封裝成一個任務(wù),將此任務(wù)放到一個任務(wù)鏈中,線程池采用先進(jìn)先出的方式來選擇任務(wù)進(jìn)行執(zhí)行。OFBiz中怎么實現(xiàn)呢?具體查看GenericAsyncEngine的runAsync方法發(fā)現(xiàn)是通過一個生成一個Job來實現(xiàn)的:

        job = new GenericServiceJob(dctx, jobId, name, modelService.name, context, requester);
        try {
            dispatcher.getJobManager().runJob(job);
        } catch (JobManagerException jse) {
            throw new GenericServiceException("Cannot run job.", jse);
        }
對于Job的執(zhí)行,感興趣的可以看我的另一篇文章OFBiz中Job的運行機制