zoukankan      html  css  js  c++  java
  • OFBIZ:启动之ContainerLoader

    ContainerLoader类实现StartupLoader接口,目的是装入各种Container容器。

    /**
     * An OFBiz container. A container can be thought of as a background process.
     * 
     * <p>
     * When OFBiz starts, the main thread will create the <code>Container</code> instance and
     * then call the container's <code>init</code> method. If the method returns without
     * throwing an exception the container will be added to a list of initialized containers.
     * After all instances have been created and initialized, the main thread will call the
     * <code>start</code> method of each container in the list. When OFBiz shuts down, a
     * separate shutdown thread will call the <code>stop</code> method of each container.
     * Implementations should anticipate asynchronous calls to the methods by different
     * threads.
     * </p>
     * 
     * <p>Containers might be loaded more than once (have more than one instance).<p>
     */
    public interface Container {
    
        /** Initialize the container. This method must not block - implementations
         * should initialize internal structures and then return.
         *
         * @param args Command-line arguments.
         * @param name Unique name of the container's instance.
         * @param configFile Location of the configuration file used to load this container.
         * @throws ContainerException If an error was encountered. Throwing this exception
         * will halt container loading, so it should be thrown only when other containers
         * might depend on this one.
         */
        public void init(String[] args, String name, String configFile) throws ContainerException;
    
        /**
         * Start the container process. This method must not block - implementations
         * that require thread blocking must create a separate thread and then return.
         *
         * @return <code>true</code> if the process started.
         * @throws ContainerException If an error was encountered.
         */
        public boolean start() throws ContainerException;
    
        /**
         * Stop the container process. This method must not block.
         *
         * @throws ContainerException If an error was encountered.
         */
        public void stop() throws ContainerException;
    
        /**
         * Return the container name.
         *
         * @return Name of the container's instance.
         */
        public String getName();
    }


    ContainerLoader会以三种方式寻找Container。第一种方式从配置文件中找,默认的配置文件是framework/base/config/ofbiz-containers.xml。第二种方式找组件Component总定义的容器。第三种方式找hot-deploy容器,这也是一个配置文件hot-deploy-containers.xml。

    ofbiz-containers.xml定义了整个OFBIZ最重要的ComponentContainer容器,该容器载入所有的Component。

    <ofbiz-containers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/ofbiz-containers.xsd">
    
        <!-- load the ofbiz component container (always first) -->
        <container name="component-container" loaders="main,rmi,pos,install" class="org.ofbiz.base.container.ComponentContainer"/>
    
        <container name="component-container-test" loaders="test" class="org.ofbiz.base.container.ComponentContainer">
            <property name="ofbiz.instrumenterClassName" value="org.ofbiz.base.config.CoberturaInstrumenter"/>
            <property name="ofbiz.instrumenterFile" value="runtime/logs/cobertura-components.dat"/>
        </container>
    
        <container name="component-container-limited" loaders="limited" class="org.ofbiz.base.container.ComponentContainer">
            <property name="update-classpath" value="false"/>
        </container>
    
        <container name="component-container" loaders="testlist" class="org.ofbiz.base.container.JustLoadComponentsContainer"/>
    
    </ofbiz-containers>


    ContainerLoader首先载入ofbiz-containers.xml中的容器:

    this.loadedContainers.clear();
    
    // get this loader's configuration file
    // default: framework/base/config/ofbiz-containers.xml
    this.configFile = config.containerConfig;
    
    Collection<ContainerConfig.Container> containers = null;
    try {
        containers = ContainerConfig.getContainers(configFile);
    } catch (ContainerException e) {
        throw new StartupException(e);
    }
    
    for (ContainerConfig.Container containerCfg : containers) {
        if (this.unloading) {
            return;
        }
        boolean matchingLoaderFound = false;
        if (UtilValidate.isEmpty(containerCfg.loaders) && UtilValidate.isEmpty(loaders)) {
            matchingLoaderFound = true;
        } else {
            for (String loader: loaders) {
                if (UtilValidate.isEmpty(containerCfg.loaders) || containerCfg.loaders.contains(loader)) {
                    matchingLoaderFound = true;
                    break;
                }
            }
        }
        if (matchingLoaderFound) {
            Debug.logInfo("Loading container: " + containerCfg.name, module);
            Container tmpContainer = loadContainer(containerCfg, args);
            this.loadedContainers.add(tmpContainer);
            Debug.logInfo("Loaded container: " + containerCfg.name, module);
        }
    }
    
    private Container loadContainer(ContainerConfig.Container containerCfg, String[] args) throws StartupException {
        // load the container class
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        if (loader == null) {
            Debug.logWarning("Unable to get context classloader; using system", module);
            loader = ClassLoader.getSystemClassLoader();
        }
        Class<?> containerClass = null;
        try {
            containerClass = loader.loadClass(containerCfg.className);
        } catch (ClassNotFoundException e) {
            throw new StartupException("Cannot locate container class", e);
        }
        if (containerClass == null) {
            throw new StartupException("Component container class not loaded");
        }
    
        // create a new instance of the container object
        Container containerObj = null;
        try {
            containerObj = (Container) containerClass.newInstance();
        } catch (InstantiationException e) {
            throw new StartupException("Cannot create " + containerCfg.name, e);
        } catch (IllegalAccessException e) {
            throw new StartupException("Cannot create " + containerCfg.name, e);
        } catch (ClassCastException e) {
            throw new StartupException("Cannot create " + containerCfg.name, e);
        }
    
        if (containerObj == null) {
            throw new StartupException("Unable to create instance of component container");
        }
    
        // initialize the container object
        try {
            containerObj.init(args, containerCfg.name, configFile);
        } catch (ContainerException e) {
            throw new StartupException("Cannot init() " + containerCfg.name, e);
        } catch (java.lang.AbstractMethodError e) {
            throw new StartupException("Cannot init() " + containerCfg.name, e);
        }
    
        return containerObj;
    }

    然后载入Component中定义的容器:

    List<ContainerConfig.Container> containersDefinedInComponents = ComponentConfig.getAllContainers();
    for (ContainerConfig.Container containerCfg: containersDefinedInComponents) {
        boolean matchingLoaderFound = false;
        if (UtilValidate.isEmpty(containerCfg.loaders) && UtilValidate.isEmpty(loaders)) {
            matchingLoaderFound = true;
        } else {
            for (String loader: loaders) {
                if (UtilValidate.isEmpty(containerCfg.loaders) || containerCfg.loaders.contains(loader)) {
                    matchingLoaderFound = true;
                    break;
                }
            }
        }
        if (matchingLoaderFound) {
            Debug.logInfo("Loading component's container: " + containerCfg.name, module);
            Container tmpContainer = loadContainer(containerCfg, args);
            this.loadedContainers.add(tmpContainer);
            Debug.logInfo("Loaded component's container: " + containerCfg.name, module);
        }
    }

    第三步载入hot-deploy容器:

    ClassLoader loader = Thread.currentThread().getContextClassLoader();
    Enumeration<URL> resources;
    try {
        resources = loader.getResources("hot-deploy-containers.xml");
        while (resources.hasMoreElements() && !this.unloading) {
            URL xmlUrl = resources.nextElement();
            Debug.logInfo("Loading hot-deploy containers from " + xmlUrl, module);
            Collection<ContainerConfig.Container> hotDeployContainers = ContainerConfig.getContainers(xmlUrl);
            for (ContainerConfig.Container containerCfg : hotDeployContainers) {
                if (this.unloading) {
                    return;
                }
                Container tmpContainer = loadContainer(containerCfg, args);
                this.loadedContainers.add(tmpContainer);
            }
        }
    } catch (Exception e) {
        Debug.logError(e, "Could not load hot-deploy-containers.xml", module);
        throw new StartupException(e);
    }


    最后ContainerLoader启动时,执行所有Container的start()方法。

    public synchronized void start() throws StartupException {
        if (!this.loaded || this.unloading) {
            throw new IllegalStateException("start() called on unloaded containers");
        }
        Debug.logInfo("[Startup] Starting containers...", module);
        // start each container object
        for (Container container: this.loadedContainers) {
            if (this.unloading) {
                return;
            }
            Debug.logInfo("Starting container " + container.getName(), module);
            try {
                container.start();
            } catch (ContainerException e) {
                throw new StartupException("Cannot start() " + container.getClass().getName(), e);
            } catch (java.lang.AbstractMethodError e) {
                throw new StartupException("Cannot start() " + container.getClass().getName(), e);
            }
            Debug.logInfo("Started container " + container.getName(), module);
        }
    }
  • 相关阅读:
    HDU 5791 Two (DP)
    POJ 1088 滑雪 (DPor记忆化搜索)
    LightOJ 1011
    POJ 1787 Charlie's Change (多重背包 带结果组成)
    HDU 5550 Game Rooms (ccpc2015 K)(dp)
    HDU 5542 The Battle of Chibi (ccpc 南阳 C)(DP 树状数组 离散化)
    HDU 5543 Pick The Sticks (01背包)
    HDU 5546 Ancient Go (ccpc2015南阳G)
    NB-IoT的DRX、eDRX、PSM三个模式 (转载,描述的简单易懂)
    MQTT 嵌入式端通讯协议解析(转)
  • 原文地址:https://www.cnblogs.com/eastson/p/5328112.html
Copyright © 2011-2022 走看看