2. 嵌入式方式
在开始这部分前,有一些必须的Derby架构的东西需要好好的了解下,可以在Derby的官方网站看一下,地址是http://db.apache.org/derby/papers/derby_arch.html
首先,Derby是由monitor和一系列的module组成的,每个module都代表了一个独立的功能,并且基接口通常是在java.sql包中定义的接口,比如JDBC驱动,锁管理等等。而monitor可以把对module的请求映射到module的具体实现上。比如JDBC驱动,monitor会把来自JDK1.3的请求转给JDBC2.0的实现,而JDK1.4的则转给JDBC3.0的实现。
对Derby的结构的描述就大致说这些吧,有兴趣的可以去官网仔细的了解下。下面转入正题,
一个应用程序和使用嵌入式方式的Derby进行连接代码通常来说是这样的:
try {
/* 如果使用的是JDK1.6,那么嵌入式方式是不需要载入驱动的 */
Class.forName("org.apache.derby.jdbc.EmeddedDriver").newInstance();
} catch (Exception e) {
throw new SQLException("初始化数据库连接失败");
}
String url = "jdbc:derby:data;create=true";
conn = DriverManager.getConnection(url, "username", "password");
可以先研究下Class.forName("org.apache.derby.jdbc.EmeddedDriver").newInstance();这句的初始化里都做了什么。
这个在第1部分中网络服务器方式的启动中也是有涉及的,在网络服务器方式下也载入了嵌入式的驱动,这里正好可以一并的来进行了解,
/* 构造函数 */
public EmbeddedDriver() {
EmbeddedDriver.boot();
}
static void boot() {
PrintStream ps = DriverManager.getLogStream();
if (ps == null)
ps = System.err;
/* 交给JDBCBoot去继续执行 */
new JDBCBoot().boot(Attribute.PROTOCOL, ps);
}
下边就是JDBCBoot类的boot()方法了,
public void boot(String protocol, PrintStream logging) {
if (org.apache.derby.jdbc.InternalDriver.activeDriver() == null) {
/* InternalDriver(JDBC)和授权服务 */
addProperty("derby.service.jdbc", "org.apache.derby.jdbc.InternalDriver");
/* AuthenticationService.MODULE = org.apache.derby.iapi.jdbc.AuthenticationService */
addProperty("derby.service.authentication", AuthenticationService.MODULE);
Monitor.startMonitor(bootProperties, logging);
/* 启动网络模块 */
if (Boolean.valueOf(PropertyUtil.getSystemProperty(Property.START_DRDA)).booleanValue()) {
try {
/* NETWORK_SERVER_AUTOSTART_CLASS_NAME = org.apache.derby.iapi.jdbc.DRDAServerStarter */
Monitor.startSystemModule(NETWORK_SERVER_AUTOSTART_CLASS_NAME);
} catch (StandardException se) {
Monitor.logTextMessage(MessageId.CONN_NETWORK_SERVER_START_EXCEPTION, se.getMessage());
}
}
}
}
这里就涉及到了Monitor的启动了,
public class Monitor {
......
public static void startMonitor(Properties bootProperties, PrintStream logging) {
new org.apache.derby.impl.services.monitor.FileMonitor(bootProperties, logging);
}
......
}
public final class FileMonitor extends BaseMonitor implements java.security.PrivilegedExceptionAction {
......
public FileMonitor(java.util.Properties properties, java.io.PrintStream log) {
runWithState(properties, log);
}
......
}
这里初始化了一个FileMonitor的实例,而在FileMonitor的构造函数里会调用它的父类BaseMonitor中的runWithState()方法,这里就要正式进入重点了。
顺带说下,这个方法我用eclipse是调试不过去了,会报出各种各样的无解错误,有些地方我也不清楚是到底实现什么的。
protected final void runWithState(Properties properties, PrintStream log) {
/*
* 这里properties有两个属性:
* "derby.service.jdbc", "org.apache.derby.jdbc.InternalDriver"
* "derby.service.authentication", "org.apache.derby.iapi.jdbc.AuthenticationService"
*/
bootProperties = properties;
logging = log;
/*
* 这里会读取org/apache/derby/info/DBMS.properties这个配置文件,Derby源代码里没有,可以下一个binary版的看一下
* ,就是一些数据库的版本之类的信息
* 然后会初始化derby.system.home属性
*/
if (!initialize(false))
return;
if (!Monitor.setMonitor(this))
return;
Object msgService = MessageService.setFinder(this);
/* 新开一个后台线程引用这个FileMonitor,还有一个Monitor实例和msgService实例,防止GC */
Object[] keepItems = new Object[3];
keepItems[0] = this;
keepItems[1] = new Monitor();
keepItems[2] = msgService;
dontGC = new AntiGC(keepItems);
final Thread dontGCthread = getDaemonThread(dontGC, "antiGC", true);
try {
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
dontGCthread.setContextClassLoader(null);
return null;
}
});
} catch (SecurityException se1) {
}
/* 开启后台线程 */
dontGCthread.start();
if (SanityManager.DEBUG) {
reportOn = Boolean.valueOf(PropertyUtil.getSystemProperty("derby.monitor.verbose")).booleanValue();
}
/* 这里要读取derby.system.home目录下的derby.properties文件,这个可以进一步控制Derby数据库引擎的操作 */
applicationProperties = readApplicationProperties();
/* 获得系统属性 */
Properties systemProperties = null;
if (SanityManager.DEBUG) {
try {
systemProperties = System.getProperties();
} catch (SecurityException se) {
}
}
/* 返回属性中定义的实现类,对于bootProperties中的两个属性,此处返回null */
Vector bootImplementations = getImplementations(bootProperties, false);
Vector systemImplementations = null;
Vector applicationImplementations = null;
if (true || SanityManager.DEBUG) {
// Don't allow external code to override our implementations.
systemImplementations = getImplementations(systemProperties, false);
applicationImplementations = getImplementations(applicationProperties, false);
}
/* 这里要返回org/apache/derby/modules.properties中默认的module实现 */
/* 可以看看这个文件,基本的模块对应的实现都是在这个文件中定义的 */
Vector defaultImplementations = getDefaultImplementations();
int implementationCount = 0;
if (bootImplementations != null)
implementationCount++;
if (true || SanityManager.DEBUG) {
if (systemImplementations != null)
implementationCount++;
if (applicationImplementations != null)
implementationCount++;
}
if (defaultImplementations != null)
implementationCount++;
/* Vector数组,这个implementationSets变量很重要,载入模块对应的实现的时候会在这个Vector数组中找 */
implementationSets = new Vector[implementationCount];
/* 把前面找到的所有模块实现都放进implementationSets中 */
implementationCount = 0;
if (bootImplementations != null)
implementationSets[implementationCount++] = bootImplementations;
if (true || SanityManager.DEBUG) {
if (systemImplementations != null)
implementationSets[implementationCount++] = systemImplementations;
if (applicationImplementations != null)
implementationSets[implementationCount++] = applicationImplementations;
}
if (defaultImplementations != null)
implementationSets[implementationCount++] = defaultImplementations;
if (SanityManager.DEBUG) {
if (applicationProperties != null) {
addDebugFlags(applicationProperties.getProperty(Monitor.DEBUG_FALSE), false);
addDebugFlags(applicationProperties.getProperty(Monitor.DEBUG_TRUE), true);
}
addDebugFlags(PropertyUtil.getSystemProperty(Monitor.DEBUG_FALSE), false);
addDebugFlags(PropertyUtil.getSystemProperty(Monitor.DEBUG_TRUE), true);
}
try {
/* 这里要启动几个总是要启动的module */
systemStreams = (InfoStreams) Monitor
.startSystemModule("org.apache.derby.iapi.services.stream.InfoStreams");
if (SanityManager.DEBUG) {
SanityManager.SET_DEBUG_STREAM(systemStreams.stream().getPrintWriter());
}
contextService = new ContextService();
uuidFactory = (UUIDFactory) Monitor.startSystemModule("org.apache.derby.iapi.services.uuid.UUIDFactory");
timerFactory = (TimerFactory) Monitor
.startSystemModule("org.apache.derby.iapi.services.timer.TimerFactory");
Monitor.startSystemModule(Module.JMX);
} catch (StandardException se) {
reportException(se);
dumpTempWriter(true);
return;
}
dumpTempWriter(false);
if (SanityManager.DEBUG && reportOn) {
dumpProperties("-- Boot Properties --", bootProperties);
dumpProperties("-- System Properties --", systemProperties);
dumpProperties("-- Application Properties --", applicationProperties);
}
determineSupportedServiceProviders();
boolean bootAll = Boolean.valueOf(PropertyUtil.getSystemProperty(Property.BOOT_ALL)).booleanValue();
/* 开启"derby.service."开头的服务,这个也要仔细看一下 */
startServices(bootProperties, bootAll);
startServices(systemProperties, bootAll);
startServices(applicationProperties, bootAll);
if (bootAll)
bootPersistentServices();
}
这个方法的前半部分主要是找各个module的实现类,然后放到implementationSets这个变量中,后半部分就是module的启动了,有两个方法要重点的关注下,一个是#getImplementations(),一个是#startServices()。
首先来看getImplementations()方法,
private Vector getImplementations(Properties moduleList, boolean actualModuleList) {
if (moduleList == null)
return null;
Vector implementations = actualModuleList ? new Vector(moduleList.size()) : new Vector(0, 1);
/* 获得当前的JDK版本信息 */
int theJDKId = JVMInfo.JDK_ID;
/* 如果某个module需要最低的JDK版本,记录每个JDK版本的module数量 */
int[] envModuleCount = new int[theJDKId + 1];
/* 循环处理传进来的Properties中包括的模块 */
nextModule: for (Enumeration e = moduleList.propertyNames(); e.hasMoreElements();) {
/* 键值 */
String key = (String) e.nextElement();
/* module名 */
String tag;
// derby.module.<modulename>=<class name>
// derby.subSubProtocol.<modulename>=<classname>
/* 判断键值是不是以"derby.module."或者"derby.subSubProtocol."开头,如果都不是放弃这次循环 */
if (key.startsWith(Property.MODULE_PREFIX)) {
tag = key.substring(Property.MODULE_PREFIX.length());
} else if (key.startsWith(Property.SUB_SUB_PROTOCOL_PREFIX)) {
tag = key.substring(Property.MODULE_PREFIX.length());
} else {
continue nextModule;
}
/* 判断是否还同时存在名字为"derby.env.jdk."+<module name>的属性 */
/* 这个属性应该是启动这个服务所需要的最低JDK版本 */
String envKey = Property.MODULE_ENV_JDK_PREFIX.concat(tag);
String envJDK = moduleList.getProperty(envKey);
int envJDKId = 0;
/* 这里会根据版本来确定是否继续启动 */
if (envJDK != null) {
envJDKId = Integer.parseInt(envJDK.trim());
if (envJDKId > theJDKId) {
continue nextModule;
}
}
/* 判断是否还同时存在名字为"derby.env.classes."+<module name>的属性 */
/* 这个属性应该是启动这个服务所需要的其他类信息 */
envKey = Property.MODULE_ENV_CLASSES_PREFIX.concat(tag);
String envClasses = moduleList.getProperty(envKey);
if (envClasses != null) {
StringTokenizer st = new StringTokenizer(envClasses, ",");
for (; st.hasMoreTokens();) {
try {
/* 这里会尝试找这个类或者接口 */
Class.forName(st.nextToken().trim());
} catch (ClassNotFoundException cnfe) {
continue nextModule;
} catch (LinkageError le) {
continue nextModule;
}
}
}
/* 获得module的类名 */
String className = moduleList.getProperty(key);
if (SanityManager.DEBUG && reportOn) {
report("Accessing module " + className + " to run initializers at boot time");
}
try {
/* 尝试载入这个类 */
Class possibleModule = Class.forName(className);
/* 判断是否是某些特殊的module:PersistentService和StorageFactory */
if (getPersistentServiceImplementation(possibleModule))
continue;
if (StorageFactory.class.isAssignableFrom(possibleModule)) {
storageFactories.put(tag, className);
continue;
}
if (envJDKId != 0) {
/* 这里在Vector中会把需要JDK版本高的模块排在前面 */
/* 后面在载入模块实现的时候会有用处,比如保证JDK6在启动JDBC服务时会找到JDBC4的实现而不是JDBC3 */
int offset = 0;
for (int eji = theJDKId; eji > envJDKId; eji--) {
offset += envModuleCount[eji];
}
/* 插入Vector中 */
implementations.insertElementAt(possibleModule, offset);
envModuleCount[envJDKId]++;
} else {
/* 插入Vector中 */
implementations.addElement(possibleModule);
}
if (SanityManager.DEBUG) {// DEBUG的先不去关心
Class[] csParams = { new java.util.Properties().getClass() };
try {
possibleModule.getMethod("canSupport", csParams);
if (!ModuleSupportable.class.isAssignableFrom(possibleModule)) {
SanityManager
.THROWASSERT("Module does not implement ModuleSupportable but has canSupport() - "
+ className);
}
} catch (NoSuchMethodException nsme) {/* ok */
}
// ModuleControl
boolean eitherMethod = false;
Class[] bootParams = { Boolean.TYPE, new java.util.Properties().getClass() };
try {
possibleModule.getMethod("boot", bootParams);
eitherMethod = true;
} catch (NoSuchMethodException nsme) {/* ok */
}
Class[] stopParams = {};
try {
possibleModule.getMethod("stop", stopParams);
eitherMethod = true;
} catch (NoSuchMethodException nsme) {/* ok */
}
if (eitherMethod) {
if (!ModuleControl.class.isAssignableFrom(possibleModule)) {
SanityManager.THROWASSERT("Module does not implement ModuleControl but has its methods - "
+ className);
}
}
}
} catch (ClassNotFoundException cnfe) {
report("Class " + className + " " + cnfe.toString() + ", module ignored.");
} catch (LinkageError le) {
report("Class " + className + " " + le.toString() + ", module ignored.");
}
}
if (implementations.isEmpty())
return null;
implementations.trimToSize();
return implementations;
}
通过这个方法,就找到了属性中定义的module实现,为了对属性的内容有个直观的了解,可以看一下modules.properties中的内容。