看过#getImplementations()之后,来看一下#startServices()方法,这个方法就是启动服务了,前面看到的JDBC服务就是在这里启动的(addProperty("derby.service.jdbc", "org.apache.derby.jdbc.InternalDriver");)
这里需要重点留意的是协议名不等于"serviceDirectory"的情况,也就是进入#bootService()方法的分支。
这个方法也是非常长的,我们来研究下,
这里instance = ts.bootModule(create, null, serviceKey, serviceProperties);这一步比较重要,这步会找到module的实现类,然后返回module的实例。
这个方法有两处还需要重点的研究下,一个是BaseMonitor的#loadInstance(),它负责找到实例。
这里第二个需要关注的是BaseMonitor.boot(instance, create, properties);方法,这个方法会调用module实例的#boot()方法,
在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的启动部分就分析完了。
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的启动部分就分析完了。