任意一个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++;
}
}
}
}

OFBIZ:启动之StartupLoader的更多相关文章

  1. 【转】Ofbiz学习经验谈

    不可否认,OFBiz这个开源的系统功能是非常强大的,涉及到的东西太多了,其实对我们现在而言,最有用的只有这么几个:实体引擎.服务引擎.WebTools.用户权限管理.最先要提醒各位的是,在配置一个OF ...

  2. ofbiz安装优化

    一. 1.安装jdk 2.安装数据库 3.安装ant yum install ant 4.编译启动ofbiz cd /ofbiz目录下 ant run-install ./startofbiz.sh ...

  3. OFBiz:添加实体栏位

    如何添加实体栏位?这里演示为PostalAddress添加planet栏位.打开applications/party/entitydef/entitymodel.xml,找到PostalAddress ...

  4. gradle ofbiz 16 开发环境搭建

    原 gradle ofbiz 16 开发环境搭建 2017年02月13日 10:59:19 阅读数:2702 1.安装jdk 2.配置jdk环境变量 3.eclipse 安装svn 插件 4.svn下 ...

  5. ApacheOFBiz的相关介绍以及使用总结(一)

    由于最近一段时间在给一个创业的公司做客户关系管理CRM系统,限于人力要求(其实是没有多少人力),只能看能否有稳定,开源的半成品进行改造,而且最好不需要前端(js)相关开发人员的支援就可以把事情做成,经 ...

  6. OFBIZ:启动之ContainerLoader

    ContainerLoader类实现StartupLoader接口,目的是装入各种Container容器. /** * An OFBiz container. A container can be t ...

  7. ofbiz idea 启动

    1.下载gradle并安装到本地 2.idea引入gradle 3.gradle右键选择refresh,项目会重新编译并加载gradle的task 4.可以再编译一下 5.没问题的话打开,jar ap ...

  8. [OFBiz]开发 三

    1. Debug不要在Eclipse中使用Ant来启动ofbiz, 因为在Eclipse中无法kill掉Ant的进程,而ofbiz又没有提供stop的方法.(有一个hook shutdown的方法,但 ...

  9. OFBiz:配置过程

    OFBiz使用了大量的配置文件,整个过程有点复杂.这里将配置过程大略整理了一下,方便后面查阅. 第一层:org.ofbiz.base.start.Start启动类.该类载入org/ofbiz/base ...

随机推荐

  1. 关于DButils的简单介绍

    android中的orm框架,一行代码就可以进行增删改查:支持事务,默认关闭:可通过注解自定义表名,列名,外键,唯一性约束,NOT NULL约束,CHECK约束等(需要混淆的时候请注解表名和列名)等等 ...

  2. Winform开发框架之系统登录实现

    在业务系统的操作过程中,有时候,用户需要切换用户进行重新登录,这种情况有时候是因为一个人管理多个用户账号,希望通过不同的账号登录进行管理不同的资料,另一种情况是酒店的换班操作,另一个人接替前面的人进行 ...

  3. 如何利用Cloudera Manager来手动安装parcel包

    1.问题的描述: 当你利用Cloudera Manager部署了CDH的集群后,也许随着你的业务需求,你需要对你的就去哪做一些优化,或者扩展之类的,这个时候你可能需要下载安装一些组件.例如,我最近在阅 ...

  4. 初用Ubuntu常见问题及解决方案之一

    1.我的Vaio Fit15e的无线网卡是BCM43142,装了Ubuntu后为了装驱动折腾了好久,因为这款网卡在Broadcom官网都找不到驱动,google了一大圈,一个最简单的命令可以解决这个问 ...

  5. Python操作文件文档

    需要帮老师将44G的图书分类一下,人工当然累死了.所以用Python大法处理一下. 思路是读取文件目录下的书名,然后去百度百科查分类,如果还没有就去豆瓣,当当查.哪一个先找到其余的就不用找了.如果没有 ...

  6. UVA 247 电话圈 (floyd传递闭包 + dfs输出连通分量的点)

    题意:输出所有的环: 思路:数据比较小,用三层循环的floyd传递闭包(即两条路通为1,不通为0,如果在一个环中,环中的所有点能互相连通),输出路径用dfs,递归还没有出现过的点(vis),输出并递归 ...

  7. import和from import陷阱二

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 #from os import path import os.path path='/home/vamei/doc/file.txt' ...

  8. hadoop删除节点。

    hadoop节点摘除操作: 1.确定exclude文件的位置. <property> <name>dfs.hosts.exclude</name> <valu ...

  9. mysql常用&实用语句

    Mysql是最流行的关系型数据库管理系统,也是目前最常用的数据库之一,掌握其常用的操作语句是必不可少的. 下面是自己总结的mysqp常用&实用的sql语句: 1.mysql -u root - ...

  10. PAT (Basic Level) Practise:1028. 人口普查

    [题目链接] 某城镇进行人口普查,得到了全体居民的生日.现请你写个程序,找出镇上最年长和最年轻的人. 这里确保每个输入的日期都是合法的,但不一定是合理的——假设已知镇上没有超过200岁的老人,而今天是 ...