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);
        }
    }
  • 相关阅读:
    MD5加密Java实现
    一直以来有个问题我没有解决,现在知道了
    从最近一次Struts 2 的漏洞看Web安全
    Android与Struts2、Hibernate打造社交平台
    Android与服务器端交互
    大二生活总结
    throttle_classes 60秒访问10次限制
    restframework流程
    django-admin有用的设置
    django-ckeditor设置
  • 原文地址:https://www.cnblogs.com/eastson/p/5328112.html
Copyright © 2011-2022 走看看