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

    任意一个JAVA程序都是从main()开始启动的,OFBIZ也不例外。OFBIZ的main()位于framework/start/src/org/ofbiz/base/start/Start.java:

    public final class Start {
    
        private static final Start instance = new Start();
    
        public static void main(String[] args) throws StartupException {
            ... ...
            
            instance.init(args, command == Command.COMMAND);
            try {
                if (command == Command.STATUS) {
                    System.out.println("Current Status : " + instance.status());
                } else if (command == Command.SHUTDOWN) {
                    System.out.println("Shutting down server : " + instance.shutdown());
                } else {
                    // general start
                    instance.start();
                }
            } catch (Exception e) {
                e.printStackTrace();
                System.exit(99);
            }
        }
        
        void init(String[] args, boolean fullInit) throws StartupException {
            ... ...
    
            // initialize the startup loaders
            initStartLoaders();
        }
    
        private void initStartLoaders() throws StartupException {
            ClassLoader classloader = Thread.currentThread().getContextClassLoader();
            synchronized (this.loaders) {
                // initialize the loaders
                for (Map<String, String> loaderMap : config.loaders) {
                    if (this.serverState.get() == ServerState.STOPPING) {
                        return;
                    }
                    try {
                        String loaderClassName = loaderMap.get("class");
                        Class<?> loaderClass = classloader.loadClass(loaderClassName);
                        StartupLoader loader = (StartupLoader) loaderClass.newInstance();
                        loader.load(config, loaderArgs.toArray(new String[loaderArgs.size()]));
                        loaders.add(loader);
                    } catch (ClassNotFoundException e) {
                        throw (StartupException) new StartupException(e.getMessage()).initCause(e);
                    } catch (InstantiationException e) {
                        throw (StartupException) new StartupException(e.getMessage()).initCause(e);
                    } catch (IllegalAccessException e) {
                        throw (StartupException) new StartupException(e.getMessage()).initCause(e);
                    }
                }
                this.loaders.trimToSize();
            }
            return;
        }
    
        void start() throws Exception {
            if (!startStartLoaders()) {
                if (this.serverState.get() == ServerState.STOPPING) {
                    return;
                } else {
                    throw new Exception("Error during start.");
                }
            }
            if (config.shutdownAfterLoad) {
                stopServer();
            }
        }
        
        boolean startStartLoaders() {
            synchronized (this.loaders) {
                // start the loaders
                for (StartupLoader loader : this.loaders) {
                    if (this.serverState.get() == ServerState.STOPPING) {
                        return false;
                    }
                    try {
                        loader.start();
                    } catch (StartupException e) {
                        e.printStackTrace();
                        return false;
                    }
                }
            }
            return this.serverState.compareAndSet(ServerState.STARTING, ServerState.RUNNING);
        }
    }

    OFBIZ的main()过程可以简单理解为两个步骤:init()和start()。init()初始化StartupLoader,通过initStartLoaders()实现。start()启动StartupLoader,通过startStartLoaders()实现。
    StartupLoader是一个接口,实现载入器的整个生命周期。

    /**
     * An object that loads server startup classes.
     * <p>
     * When OFBiz starts, the main thread will create the <code>StartupLoader</code> instance and
     * then call the loader's <code>load</code> method. If the method returns without
     * throwing an exception the loader will be added to a list of initialized loaders.
     * After all instances have been created and initialized, the main thread will call the
     * <code>start</code> method of each loader in the list. When OFBiz shuts down, a
     * separate shutdown thread will call the <code>unload</code> method of each loader.
     * Implementations should anticipate asynchronous calls to the methods by different
     * threads.
     * </p>
     * 
     */
    public interface StartupLoader {
    
        /**
         * Load a startup class.
         *
         * @param config Startup config.
         * @param args Command-line arguments.
         * @throws StartupException If an error was encountered. Throwing this exception
         * will halt loader loading, so it should be thrown only when OFBiz can't
         * operate without it.
         */
        public void load(Config config, String args[]) throws StartupException;
    
        /**
         * Start the startup class. This method must not block - implementations
         * that require thread blocking must create a separate thread and then return.
         * 
         * @throws StartupException If an error was encountered.
         */
        public void start() throws StartupException;
    
        /**
         * Stop the startup class. This method must not block.
         *
         * @throws StartupException If an error was encountered.
         */
        public void unload() throws StartupException;
    }

    initStartLoaders()从config.loaders获取可用的载入器信息,然后创建StartupLoader实例,调用load()方法。

    private void initStartLoaders() throws StartupException {
        ClassLoader classloader = Thread.currentThread().getContextClassLoader();
        synchronized (this.loaders) {
            // initialize the loaders
            for (Map<String, String> loaderMap : config.loaders) {
                if (this.serverState.get() == ServerState.STOPPING) {
                    return;
                }
                try {
                    String loaderClassName = loaderMap.get("class");
                    Class<?> loaderClass = classloader.loadClass(loaderClassName);
                    StartupLoader loader = (StartupLoader) loaderClass.newInstance();
                    loader.load(config, loaderArgs.toArray(new String[loaderArgs.size()]));
                    loaders.add(loader);
                } catch (ClassNotFoundException e) {
                    throw (StartupException) new StartupException(e.getMessage()).initCause(e);
                } catch (InstantiationException e) {
                    throw (StartupException) new StartupException(e.getMessage()).initCause(e);
                } catch (IllegalAccessException e) {
                    throw (StartupException) new StartupException(e.getMessage()).initCause(e);
                }
            }
            this.loaders.trimToSize();
        }
        return;
    }


    config.loaders来源于配置文件framework/start/src/org/ofbiz/base/start/start.properties。

    # --- StartupLoader implementations to load (in order)
    ofbiz.start.loader1=org.ofbiz.base.container.ContainerLoader
    ofbiz.start.loader1.loaders=main,rmi


    config是framework/start/src/org/ofbiz/base/start/Config.java的一个实例。Config类调用readConfig()过程读取start.properties中的配置信息。

    public class Config {
    
        public List<Map<String, String>> loaders;
    
        public static Config getInstance(String[] args) throws IOException {
            String firstArg = args.length > 0 ? args[0] : "";
            // Needed when portoffset is used with these commands, start.properties fits for all of them
            if ("start-batch".equalsIgnoreCase(firstArg) 
                    || "start-debug".equalsIgnoreCase(firstArg) 
                    || "stop".equalsIgnoreCase(firstArg) 
                    || "-shutdown".equalsIgnoreCase(firstArg)
                    || "-status".equalsIgnoreCase(firstArg)) {
                firstArg = "start";
            }
            String configFileName = getConfigFileName(firstArg);
            Config result = new Config();
            result.readConfig(configFileName, args);
            return result;
        }
    
        private static String getConfigFileName(String command) {
            // default command is "start"
            if (command == null || command.trim().length() == 0) {
                command = "start";
            }
            return "org/ofbiz/base/start/" + command + ".properties";
        }
        
        public void readConfig(String config, String[] args) throws IOException {
            ... ...
            
            // loader classes
            loaders = new ArrayList<Map<String, String>>();
            int currentPosition = 1;
            Map<String, String> loader = null;
            while (true) {
                loader = new HashMap<String, String>();
                String loaderClass = props.getProperty("ofbiz.start.loader" + currentPosition);
                if (loaderClass == null || loaderClass.length() == 0) {
                    break;
                } else {
                    loader.put("class", loaderClass);
                    loader.put("profiles", props.getProperty("ofbiz.start.loader" + currentPosition + ".loaders"));
                    loaders.add(loader);
                    currentPosition++;
                }
            }
        }
    }
  • 相关阅读:
    input,textarea限制字数,实时绑定
    rem布局和vw布局的理解
    HTML5+CSS3响应式垂直时间轴,高端,大气
    谈谈前端工程化是个啥?
    js动态添加html标签和属性_手动插入meta、script、div、img等标签
    textarea换行_在textarea中如何换行的实现总汇
    css常用的颜色单位表示法
    CSS3 2D转换
    为什么设置overflow为hidden可以清除浮动带来的影响
    什么是数据交互格式?xml和json优缺点
  • 原文地址:https://www.cnblogs.com/eastson/p/5328080.html
Copyright © 2011-2022 走看看