看过#getImplementations()之后,来看一下#startServices()方法,这个方法就是启动服务了,前面看到的JDBC服务就是在这里启动的(addProperty("derby.service.jdbc", "org.apache.derby.jdbc.InternalDriver");)
public void startServices(Properties properties, boolean bootAll) {
if (properties == null)
return;
for (Enumeration e = properties.propertyNames(); e.hasMoreElements();) {
/* 获得服务的键值 */
String key = (String) e.nextElement();
if (key.startsWith(SERVICE)) {// 判断是否以"derby.service."开头
/* 返回服务名 */
String name = key.substring(SERVICE.length());
/* 服务的协议或类型,其实就是类名 */
String protocolOrType = properties.getProperty(key);
try {
/* 如果协议名等于"serviceDirectory" */
if (protocolOrType.equals(Monitor.SERVICE_TYPE_DIRECTORY)) {
if (bootAll)
findProviderAndStartService(name, properties, true);
} else {
/* 开启服务 */
bootService((PersistentService) null, protocolOrType, name, (Properties) null, false);
}
} catch (StandardException se) {
if (!protocolOrType.equals(Monitor.SERVICE_TYPE_DIRECTORY))
reportException(se);
}
}
}
}
这里需要重点留意的是协议名不等于"serviceDirectory"的情况,也就是进入#bootService()方法的分支。
这个方法也是非常长的,我们来研究下,
protected Object bootService(PersistentService provider, String factoryInterface, String serviceName,
Properties properties, boolean create) throws StandardException {
/*
* 以 "derby.service.jdbc", "org.apache.derby.jdbc.InternalDriver" 为例
* provider = null factoryInterface = protocolOrType
* (org.apache.derby.jdbc.InternalDriver) serviceName = name (jdbc)
* properties = null create = false
*/
if (provider != null)
serviceName = provider.getCanonicalServiceName(serviceName);
/* ProtocolKey里存了两个属性factoryInterface和serviceName */
ProtocolKey serviceKey = ProtocolKey.create(factoryInterface, serviceName);
if (SanityManager.DEBUG && reportOn) {
report("Booting service " + serviceKey + " create = " + create);
}
ContextManager previousCM = contextService.getCurrentContextManager();
ContextManager cm = previousCM;
Object instance;
TopService ts = null;
Context sb = null;
try {
synchronized (this) {
if (inShutdown) {
throw StandardException.newException(SQLState.CLOUDSCAPE_SYSTEM_SHUTDOWN);
}
/*
* 这里services这个变量实在BaseMonitor的构造函数中初始化的 services = new
* Vector(0, 1); services.addElement(new TopService(this)); //
*/
for (int i = 1; i < services.size(); i++) {
TopService ts2 = (TopService) services.elementAt(i);
if (ts2.isPotentialService(serviceKey)) {
// if the service already exists then just return null
return null;
}
}
/* 取得Locale */
Locale serviceLocale = null;
if (create) {
properties = new Properties(properties);
serviceLocale = setLocale(properties);
properties.put(Property.SERVICE_PROTOCOL, factoryInterface);
serviceName = provider.createServiceRoot(serviceName, Boolean.valueOf(
properties.getProperty(Property.DELETE_ON_CREATE)).booleanValue());
serviceKey = ProtocolKey.create(factoryInterface, serviceName);
} else if (properties != null) {
String serverLocaleDescription = properties.getProperty(Property.SERVICE_LOCALE);
if (serverLocaleDescription != null)
serviceLocale = staticGetLocaleFromString(serverLocaleDescription);
}
/* TopService代表了对module实例的描述 */
ts = new TopService(this, serviceKey, provider, serviceLocale);
services.addElement(ts);
}
if (SanityManager.DEBUG) {
if (provider != null) {
SanityManager.ASSERT(provider.getCanonicalServiceName(serviceName).equals(serviceName),
"mismatched canonical names " + provider.getCanonicalServiceName(serviceName) + " != "
+ serviceName);
SanityManager.ASSERT(serviceName.equals(serviceKey.getIdentifier()), "mismatched names "
+ serviceName + " != " + serviceKey.getIdentifier());
}
}
if (properties != null) {
properties.put(PersistentService.ROOT, serviceName);
properties.put(PersistentService.TYPE, provider.getType());
}
if (SanityManager.DEBUG && reportOn) {
dumpProperties("Service Properties: " + serviceKey.toString(), properties);
}
if (previousCM == null) {
cm = contextService.newContextManager();
contextService.setCurrentContextManager(cm);
}
sb = new ServiceBootContext(cm);
UpdateServiceProperties usProperties;
Properties serviceProperties;
boolean inRestore = (properties != null ? properties.getProperty(Property.IN_RESTORE_FROM_BACKUP) != null
: false);
if ((provider != null) && (properties != null)) {
usProperties = new UpdateServiceProperties(provider, serviceName, properties, !(create || inRestore));
serviceProperties = usProperties;
} else {
usProperties = null;
serviceProperties = properties;
}
/* 这个方法比较重要,进行module的启动 */
instance = ts.bootModule(create, null, serviceKey, serviceProperties);
if (create || inRestore) {
provider.saveServiceProperties(serviceName, usProperties.getStorageFactory(), BaseMonitor
.removeRuntimeProperties(properties), false);
usProperties.setServiceBooted();
}
if (cm != previousCM)
cm.cleanupOnError(StandardException.closeException());
} catch (Throwable t) {
StandardException se;
if ((t instanceof StandardException)
&& (((StandardException) t).getSeverity() == ExceptionSeverity.DATABASE_SEVERITY))
se = (StandardException) t;
else
se = Monitor.exceptionStartingModule(t);
if (cm != previousCM) {
cm.cleanupOnError(se);
}
if (ts != null) {
ts.shutdown();
synchronized (this) {
services.removeElement(ts);
}
boolean deleteOnError = (properties != null ? properties.getProperty(Property.DELETE_ROOT_ON_ERROR) != null
: false);
if (create || deleteOnError)
provider.removeServiceRoot(serviceName);
}
Throwable nested = se.getCause();
if (nested instanceof ThreadDeath)
throw (ThreadDeath) nested;
throw se;
} finally {
if ((previousCM == cm) && (sb != null))
sb.popMe();
if (previousCM == null)
contextService.resetCurrentContextManager(cm);
}
/* 这个方法把module实例加入到protocolTable这个Hashtable中 */
ts.setTopModule(instance);
Thread.yield();
return instance;
}
这里instance = ts.bootModule(create, null, serviceKey, serviceProperties);这一步比较重要,这步会找到module的实现类,然后返回module的实例。
Object bootModule(boolean create, Object service, ProtocolKey key, Properties properties) throws StandardException {
synchronized (this) {
if (inShutdown)
throw StandardException.newException(SQLState.SHUTDOWN_DATABASE, getKey().getIdentifier());
}
/* 查看是否已经启动了这个module,在protocolTable这个Hashtable中先查找实例 */
Object instance = findModule(key, false, properties);
if (instance != null)// 如果有,直接返回
return instance;
if (monitor.reportOn) {
monitor.report("Booting Module " + key.toString() + " create = " + create);
}
synchronized (this) {
for (int i = 0; i < moduleInstances.size(); i++) {// 在运行中的module中查找
/* module的包装类 */
ModuleInstance module = (ModuleInstance) moduleInstances.elementAt(i);
if (!module.isTypeAndName((PersistentService) null, key.getFactoryInterface(), key.getIdentifier()))
continue;
instance = module.getInstance();
if (!BaseMonitor.canSupport(instance, properties))
continue;
// 把实例加入到protocolTable中
if (!addToProtocol(key, module))
continue;
if (monitor.reportOn) {
monitor.report("Started Module " + key.toString());
monitor.report(" Implementation " + instance.getClass().getName());
}
return instance;
}
}
/* 这步就是载入module实例了,以我们之前的JDBC module为例,会找到与当前JDBC版本对应的Driver */
instance = monitor.loadInstance(key.getFactoryInterface(), properties);
if (instance == null) {
throw Monitor.missingImplementation(key.getFactoryInterface().getName());
}
ModuleInstance module = new ModuleInstance(instance, key.getIdentifier(), service,
topModule == null ? (Object) null : topModule.getInstance());
moduleInstances.addElement(module);
try {
/* 这里会调用module的#boot()方法 */
BaseMonitor.boot(instance, create, properties);
} catch (StandardException se) {
moduleInstances.removeElement(module);
throw se;
}
synchronized (this) {
/* 加入到Hashtable中 */
if (addToProtocol(key, module)) {
if (monitor.reportOn) {
monitor.report("Started Module " + key.toString());
monitor.report(" Implementation " + module.getInstance().getClass().getName());
}
return module.getInstance();
}
}
/* 如果加入失败,那么就不能使用这个module了,要shutdown掉 */
TopService.stop(instance);
moduleInstances.removeElement(module);
return findModule(key, true, properties);
}
这个方法有两处还需要重点的研究下,一个是BaseMonitor的#loadInstance(),它负责找到实例。
protected Object loadInstance(Class factoryInterface, Properties properties) {
Object instance = null;
Vector localImplementations = getImplementations(properties, false);
if (localImplementations != null) {
instance = loadInstance(localImplementations, factoryInterface, properties);
}
/* implementationSets存了前面BaseMonitor的#runWithState()方法中找到的全部实例 */
for (int i = 0; i < implementationSets.length; i++) {
instance = loadInstance(implementationSets[i], factoryInterface, properties);
if (instance != null)
break;
}
return instance;
}
private Object loadInstance(Vector implementations, Class factoryInterface, Properties properties) {
for (int index = 0; true; index++) {
index = findImplementation(implementations, index, factoryInterface);
if (index < 0)
return null;
Object instance = newInstance((Class) implementations.elementAt(index));
if (BaseMonitor.canSupport(instance, properties))
return instance;
}
}
private static int findImplementation(Vector implementations, int startIndex, Class factoryInterface) {
for (int i = startIndex; i < implementations.size(); i++) {
Class factoryClass = (Class) implementations.elementAt(i);
/* 这里用#isAssignableFrom方法来匹配是否是module的实例 */
if (!factoryInterface.isAssignableFrom(factoryClass)) {
continue;
}
return i;
}
return -1;
}
这里第二个需要关注的是BaseMonitor.boot(instance, create, properties);方法,这个方法会调用module实例的#boot()方法,
static void boot(Object module, boolean create, Properties properties) throws StandardException {
if (module instanceof ModuleControl)
((ModuleControl) module).boot(create, properties);
}
在EmbeddedDriver的载入过程中,以最新的JDK1.6为例,对应的是JDBC4.0。JDBC module(org.apache.derby.jdbc.InternalDriver)会找到的实现类是org.apache.derby.jdbc.Driver40(这个是在module.properties中定义的)。这里BaseMonitor#boot()就会调用Driver40的boot()方法了。最后会把InternalDriver的一个内部静态变量activeDriver设定成当前找到的这个Driver40,这个代码还是很容易理解的,这里就不再列出来了。
至此,Derby的启动部分就分析完了。
分享到:
相关推荐
Apache Derby,也被称为Java DB,是一款轻量级、开源的关系型数据库管理系统,完全用Java编写,遵循Apache软件基金会的开放源代码协议。这个名为"db-derby-10.11.1.1-bin.zip"的压缩包包含了Apache Derby 10.11.1.1...
"db-derby-10.11.1.1-src.zip" 是Apache Derby的10.11.1.1版本的源代码包,对于开发者来说,这是一个宝贵的资源,可以深入了解Derby的内部工作原理和实现细节。 Apache Derby的核心特性包括: 1. **完全用Java编写...
### 源代码检查工具SONAR使用经验 #### Sonar概述 Sonar作为一个代码质量管理的开放平台,通过灵活的插件机制集成了多种测试工具、代码分析工具以及持续集成工具。与传统持续集成工具(如Hudson/Jenkins)相比,...
源代码的提供意味着用户可以查看、学习甚至修改系统的内部实现,以适应特定需求或进行二次开发。 Swing是Java的一个图形用户界面(GUI)工具包,它是Java Foundation Classes (JFC)的一部分,用于构建桌面应用。...
在本教程中,读者将了解如何下载、安装并启动Derby数据库服务器,以及如何连接到数据库并执行基本的SQL操作。 2. **MyBatis框架**:MyBatis是一个持久层框架,它允许开发者编写SQL语句,并将这些SQL语句与Java代码...
- **javadoc 子目录**:包含通过源代码注释生成的 API 文档。 - **docs 子目录**:包含 JavaDB 文档。 - **lib 子目录**:包含 JavaDB jar 文件。 3. **在 NetBeans IDE 中注册数据库**: - 在“服务”窗口中,...
用户可以直接运行这个文件启动聊天软件,而无需查看或修改源代码。"src"目录包含了项目的源代码,开发者可以研究这些代码来学习Swing和Derby的结合使用,了解如何创建GUI、处理用户输入、连接数据库以及执行数据库...
- **编辑器(Editor)**:用于编写和编辑源代码。 - **常见概念和操作**: - **项目(Project)**:一组相关文件的集合。 - **工作区(Workspace)**:存放项目的文件夹。 - **导入、导出Java项目**:便于项目...
- **CVS团队源代码管理**: 介绍如何使用CVS进行源代码管理。 - **字符编码设置**: 说明如何修改文件的字符编码。 #### 五、数据库管理 - **功能概述**: 概述MyEclipse Database Explorer的主要功能。 - **透视图...
- **手工和自动编译**:手动或自动编译 Java 源代码。 - **直接粘贴 Java 源码为类文件**:直接粘贴代码生成文件。 - **复制项目中的文件**:复制文件到其他位置。 - **断点和调试器**:设置断点进行调试。 - **快速...
oozie-4.3.1目录下包含了Oozie的源代码、构建脚本、文档和配置文件等。主要目录结构如下: - `src/main`:存放主要的源代码,包括Java类和XML配置文件。 - `src/test`:包含单元测试代码。 - `build.xml`:Ant构建...