`
zddava
  • 浏览: 243036 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Derby源代码分析 -- 服务器启动(三)

阅读更多
看过#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的启动部分就分析完了。
分享到:
评论

相关推荐

    db-derby-10.11.1.1-bin.zip

    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

    "db-derby-10.11.1.1-src.zip" 是Apache Derby的10.11.1.1版本的源代码包,对于开发者来说,这是一个宝贵的资源,可以深入了解Derby的内部工作原理和实现细节。 Apache Derby的核心特性包括: 1. **完全用Java编写...

    源代码检查工具SONAR使用经验

    ### 源代码检查工具SONAR使用经验 #### Sonar概述 Sonar作为一个代码质量管理的开放平台,通过灵活的插件机制集成了多种测试工具、代码分析工具以及持续集成工具。与传统持续集成工具(如Hudson/Jenkins)相比,...

    销售信息管理系统v0.3带源代码.zip

    源代码的提供意味着用户可以查看、学习甚至修改系统的内部实现,以适应特定需求或进行二次开发。 Swing是Java的一个图形用户界面(GUI)工具包,它是Java Foundation Classes (JFC)的一部分,用于构建桌面应用。...

    derby+myBatis 入门

    在本教程中,读者将了解如何下载、安装并启动Derby数据库服务器,以及如何连接到数据库并执行基本的SQL操作。 2. **MyBatis框架**:MyBatis是一个持久层框架,它允许开发者编写SQL语句,并将这些SQL语句与Java代码...

    使用 Java DB (Derby) 数据库

    - **javadoc 子目录**:包含通过源代码注释生成的 API 文档。 - **docs 子目录**:包含 JavaDB 文档。 - **lib 子目录**:包含 JavaDB jar 文件。 3. **在 NetBeans IDE 中注册数据库**: - 在“服务”窗口中,...

    Swing+derby仿QQ聊天软件及源码

    用户可以直接运行这个文件启动聊天软件,而无需查看或修改源代码。"src"目录包含了项目的源代码,开发者可以研究这些代码来学习Swing和Derby的结合使用,了解如何创建GUI、处理用户输入、连接数据库以及执行数据库...

    myeclipse入门教程

    - **编辑器(Editor)**:用于编写和编辑源代码。 - **常见概念和操作**: - **项目(Project)**:一组相关文件的集合。 - **工作区(Workspace)**:存放项目的文件夹。 - **导入、导出Java项目**:便于项目...

    MyEclipse6Java开发中文教程

    - **CVS团队源代码管理**: 介绍如何使用CVS进行源代码管理。 - **字符编码设置**: 说明如何修改文件的字符编码。 #### 五、数据库管理 - **功能概述**: 概述MyEclipse Database Explorer的主要功能。 - **透视图...

    MyEclipse 6 Java EE 开发中文手册.pdf

    - **手工和自动编译**:手动或自动编译 Java 源代码。 - **直接粘贴 Java 源码为类文件**:直接粘贴代码生成文件。 - **复制项目中的文件**:复制文件到其他位置。 - **断点和调试器**:设置断点进行调试。 - **快速...

    oozie-4.3.1.tar.gz

    oozie-4.3.1目录下包含了Oozie的源代码、构建脚本、文档和配置文件等。主要目录结构如下: - `src/main`:存放主要的源代码,包括Java类和XML配置文件。 - `src/test`:包含单元测试代码。 - `build.xml`:Ant构建...

Global site tag (gtag.js) - Google Analytics