Eclipse 运行时(Runtime)概述
Eclipse 运行时定义了所有其他插件所依赖的插件(org.eclipse.osgi 和 org.eclipse.core.runtime),运行时负责定义插件的结构及其背后的实现细节(bundles和类加载器),运行时也负责发现和执行Eclipse 主程序,维护一个包含插件和它们所实现的扩展与扩展点的注册表。同时,运行时提供了各种各样的工具,例如日志、调试跟踪、适配器、首选项存储和一个并发基础工具。
1. 运行时插件模型
当运行Eclipse程序时,Eclipse运行时会随着运行。运行时实现了Eclipse的插件模型和基础结构,维护所有的插件及插件所提供的功能。
插件就是一个向Eclipse 系统贡献代码(或者是文档,或者两者都包含)的具有组织结构、通过一种结构化方式描述的组件,插件可以定义扩展点,供其他的插件扩展。当一个插件创建了一个扩展点的实现时,我们把这叫做向平台添加了一个扩展,扩展和扩展点是通过插件的清单文件(plugin.cml)声明的。
通过一个通用扩展模型为插件提供了一个的结构化的方法,描述插件如果被扩展和如果扩展其他插件。定义一个扩展点如果顶任何其他的API,不同的是扩展点是通过XML而不是代码来声明的。同样,客户插件也使用XML来描述所实现的扩展。
运行时的一个重要机制是,如果没有使用到安装到平台中的插件,插件就不会占用内存和产生性能损耗。平台扩展模型的声明式的特性使得运行时能够在不运行插件的同时获得插件所提供的扩展点和扩展。这样,可以安装很多插件,但是除非用户的操作请求到插件所提供的功能,插件就不会被激活。对于提供一个可伸缩的、健壮的平台来说这是一个重要的特性。
1.1 插件和束(bundles)
插件的实现机制是用OSGI框架实现的,从这个角度来说,一个插件其实就是个OSGI bundle,bundle和所关联的类定义和实现了类加载过程、先决条件管理和bundle的生命周期。在接下来的讨论中,我们会交换使用plug-in 和bundle,除非是讨论框架中的特殊类。
1.1.1 plug-in
Plugin 类表示一个运行在Eclipse平台中的插件,方便于集中管理插件的生命周期和整体语义。插件可以在其生命周期的start 和stop 阶段实现特定的功能。每一个生命周期方法都包含一个BundleContext 的引用,BundleContext 提供了插件的上下文信息。
插件生命周期的start部分值得特别讨论。我们已经看到,不需要运行插件的任何代码,就可以通过插件的清单文件获得插件的信息。通常用户在工作台中的一些操作会引起一个能够触发插件启动的事件链。从实现的角度来看,除非需要加载插件中的类,插件就不会被启动。
start 方法方便于实现插件的初始化和注册工作,但是必须认识到,插件能够在许多不同的环境下被启动,一些例如获得一个图片来装饰一个对象这样简单的过程都会导致加载插件的类,以致引起插件的启动。过早的初始化操作会导致插件在实际需要很久之前就会加载代码和数据。这样的话,就有必要仔细检查一下插件的初始化工作,考虑初始化的代替方法。
... IExtensionRegistry registry = Platform.getExtensionRegistry(); IExtensionPoint point = registry.getExtensionPoint("org.eclipse.ui.views"); if (point == null) return; IExtension[] extensions = point.getExtensions(); for (int i = 0; i < extensions.length; i++) readExtension(extensions[i]); //get the information about each extension ...
... IPreferencesService service = Platform.getPreferencesService(); boolean value = service.getBoolean("com.example.myplugin", "MyPreference", true, null); //do something with the value. ...
... IPreferencesService service = Platform.getPreferencesService(); Preferences configurationNode = new ConfigurationScope().getNode("com.example.myplugin"); Preferences instanceNode = new InstanceScope().getNode("com.example.myplugin"); Preferences[] nodes = new Preferences[] {configurationNode, instanceNode}; stringValue = service.get("MyPreference", "true", nodes); //do something with the value. ...
... IPreferencesService service = Platform.getPreferencesService(); Preferences root = service.getRootNode(); Preferences myInstanceNode = root.node(InstanceScope.SCOPE).node("com.example.myplugin"); if (myInstanceNode != null) { value = node.getBoolean("MyPreference", "true"); //do something with the value. } ...
import org.eclipse.equinox.app.IApplication; import org.eclipse.equinox.app.IApplicationContext; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.PlatformUI; /** * This class controls all aspects of the application's execution */ public class Application implements IApplication { /* (non-Javadoc) * @see org.eclipse.equinox.app.IApplication#start(org.eclipse.equinox.app.IApplicationContext) */ public Object start(IApplicationContext context) throws Exception { Display display = PlatformUI.createDisplay(); try { int returnCode = PlatformUI.createAndRunWorkbench(display, new ApplicationWorkbenchAdvisor()); if (returnCode == PlatformUI.RETURN_RESTART) return IApplication.EXIT_RESTART; else return IApplication.EXIT_OK; } finally { display.dispose(); } } /* (non-Javadoc) * @see org.eclipse.equinox.app.IApplication#stop() */ public void stop() { if (!PlatformUI.isWorkbenchRunning()) return; final IWorkbench workbench = PlatformUI.getWorkbench(); final Display display = workbench.getDisplay(); display.syncExec(new Runnable() { public void run() { if (!display.isDisposed()) workbench.close(); } }); } }