经过对OSGI Host的研究,把Equinox、spring osgi等技术整合起来,进行了java系统模块化开发研究。于是,进一步想如何利用spring osgi和Eclipse RCP整合起来应用呢?于是在网上查找响应的资料,不是很多,发现了下面这篇文章,写的非常到位,拷贝如下,为尊重原创作者,标明原始url如下:
http://www.ralfebert.de/blog/eclipsercp/spring_osgi/
在完成实验工程的过程中,遇到了一些问题,进行了整理,是为文章系列二。
Spring is not only a helpful framework for the server side, its
“Spring Dynamic Modules for OSGi” can be beneficial for Eclipse RCP
applications on the client side as well:
- Spring’s IoC container is the most well known implementation of
dependency injection. As inversion of control and dependency injection
are very general concepts for structuring software applications, you may
want to use it to inject the dependencies of your UI and non-UI
client-side components as well.
- Spring provides a bunch of general-purpose abstractions for other
frameworks which are enriched with additional functionality. Some of
these might make sense in RCP applications as well. For example, you
could use Spring Remoting to communicate with your back-end components.
Getting started
I assume that you know Eclipse RCP and Spring quite well and just want to know how to integrate both.
At first, you need to get the Spring Dynamic Modules plug-ins and add
them to your target platform. I recommend keeping those separate in a
folder and add a new directory entry to your target definition. You can
download all the bundles from the Spring Bundle Repository.
I added them to my example target platform as well, so you can look up a
list of all required plug-ins or download them as one package: eclipse_rcp_de/spring_osgi.
You should also install the Spring IDE
plug-ins in your Eclipse IDE. These help a lot with editing Spring configuration files. The update site is here:
http://dist.springframework.org/release/IDE
Adding Spring application contexts to your bundles
With Spring Dynamic Modules, every bundle gets its own application context. The XML configuration files are added to the folder META-INF/spring/
of your bundle. The naming convention for these files is [module]-context.xml
:
de.ralfebert.someplugin
|-- META-INF
| |-- MANIFEST.MF
| `-- spring
| `-- services-context.xml
|-- build.properties
`-- src
If you’ve installed the Spring IDE, you can add the Spring nature to
your plug-in (Plug-in project context menu > Spring Tools > Add
Spring Project Nature). You can then create the configuration files
using New > Spring > Spring Bean Configuration File
.
You can read more about the bundle structure in the Spring documentation: Bundle Format And Manifest Headers
Extender
Spring Dynamic Modules comes with a bundle org.springframework.osgi.extender
that is responsible for instantiating the Spring application contexts.
You need to make sure that this bundle is started, because only then the
application contexts for your bundles will be available.
When you run your application from the Eclipse IDE, you can configure start levels in the Plug-ins
tab of the run configuration:
For the exported product, you can specify start levels in the Configuration
tab of the product. These settings are written to the file config.ini
in your application configuration folder. Unfortunately, when you add a
start level here, the default start levels are not applied any more
(see bug #272768).
So you need to configure the start levels of the framework bundles as
well. This is the correct configuration for the start levels:
An alternative to the config.ini
file is to start the
extender programmatically. This can be done by adding the following code
in a place that is guaranteed to be used as part of the application
startup (for example the Activator
of the bundle that contains the RCP application or the Application
class itself):
// Enforcing that Spring Dynamic Modules extender is started
Platform.getBundle("org.springframework.osgi.extender").start();
If you updated your run configuration and run your application, you should see the Spring extender startup in the console log:
30.07.2009 19:26:28 org.springframework.osgi.extender.internal.activator.ContextLoaderListener start
INFO: Starting [org.springframework.osgi.extender] bundle v.[1.2.0]
30.07.2009 19:26:28 org.springframework.osgi.extender.internal.support.ExtenderConfiguration <init>
INFO: No custom extender configuration detected; using defaults...
You can read more about the extender in the Spring documentation: The Spring Dynamic Modules Extender bundle
Injecting into view components
At this point, you can use Spring Dynamic Modules to declare beans
and inject their dependencies in the same way as on the server-side. But
how can you inject dependencies in your view components like View-
or EditorParts
?
To inject their dependencies we need them to be Spring beans.
Unfortunately, the Eclipse workbench is responsible for instantiating
these objects. How can we delegate this responsibility to the Spring IoC
container?
A little detail about the Eclipse extension mechanism comes in handy
here. Wherever you can specify a class as attribute of an extension
element, you can also specify a factory class (that implements IExecutableExtensionFactory
). Then Eclipse will not instantiate the object itself but ask the factory instead.
Martin Lippert wrote a SpringExtensionFactory
that will ask the bundle application context for the object. You can read download it below.
After you added the org.eclipse.springframework.util
plug-in to your project and imported the package org.eclipse.springframework.util
in your bundle manifest, you can use the SpringExtensionFactory
like this:
<extension point="org.eclipse.ui.views">
<view
id="de.ralfebert.someview"
class="org.eclipse.springframework.util.SpringExtensionFactory"
name="SomeView"
restorable="true">
</view>
</extension>
The SpringExtensionFactory
will look up the bean with the id de.ralfebert.someview
and Eclipse will use this object. You can also specify the bean id
independently from the id attribute of the contribution element using:
org.eclipse.springframework.util.SpringExtensionFactory:somebeanid
The bean has to be declared in the contributing plug-in. As view components are usually not singletons, you should use Spring’s prototype
scope (this will make Spring instantiate a new instance every time this bean is requested):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="de.ralfebert.someview" class="de.ralfebert.SomeViewPart" scope="prototype"/>
</beans>
OSGi services
So far we have seen how to declare application contexts for bundles
and how to inject dependencies in view components. Every bundle has its
own, separate application context - what if multiple bundles want to act
together? This is done using OSGi services.
You can export OSGi services in one bundle and import them in another bundle using a special XML namespace for OSGi:
Exporting a service
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:osgi="http://www.springframework.org/schema/osgi"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/osgi
http://www.springframework.org/schema/osgi/spring-osgi.xsd">
<bean id="someService" class="de.ralfebert.services.internal.SomeServiceImpl"/>
<osgi:service ref="someService" interface="de.ralfebert.services.ISomeService"/>
</beans>
Importing a service
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:osgi="http://www.springframework.org/schema/osgi"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/osgi
http://www.springframework.org/schema/osgi/spring-osgi.xsd">
<osgi:reference id="someService" interface="de.ralfebert.services.ISomeService"/>
</beans>
You can read more about importing and exporting services in the Spring documentation: Exporting A Spring Bean As An OSGi Service, Defining References To OSGi Services
分享到:
相关推荐
12章)系统讲解了Eclipse RCP应用开发的基础知识、Eclipse RCP软件产品各个组成部分的构建方法,以及Eclipse RCP扩展的使用和扩展点的开发,掌握这些技术知识的读者将能构建一个结构完整的Eclipse RCP软件,并解决...
比较好的OSGi学习教程,分享给大家,简单易学...。。。
eclipse rcp应用系统开发方法与实战源代码.zip
Eclipse Rich Client Platform (RCP) 的目标是在各种不是集成开发环境 (IDE) 的最终用户应用程序中使用 Eclipse。随着 Eclipse V3.1 的发布,创建 RCP 应用程序变得容易。本教程将指导您一步步创建自己的 RCP 应用...
ECLIPSE+RCP应用系统开发方法与实战 PDF 比较清晰 有目录 本人在网上找了N久一直没找到,在taobao上买的。 所以收了5分,不要说我太黑哦。
非常好的一本JAVA RCP入门实战的书,兼顾理论和实战。
Eclipse RCP应用系统开发方法与实战
该教程主要介绍了怎么把spring整合到eclipse rcp的开发中去
Eclipse RCP 软件打包发布方法。之前花了5分下了一个教材,更不不好用。现在自己摸索写了一个,绝对赞~
Eclipse RCP 应用系统开发方法与实战
基于Eclipse RCP的复合应用,IBM中国研发中心的人写的
clipse RCP允许开发者使用eclipse结构风格设计弹性的可扩展的应用程序,可重用Eclipse中已存在的方法和编码模式。俗话说,万事开头难。Eclipse RCP入手可能会比较困难、费时。接下来我们将主要讲述如何让RCP工作 ...
Eclipse RCP 应用系统开发方法与实战 源代码
eclipse rcp应用系统开发 方法与实践 随书源代码
陈冈所著的Eclipse RCP应用系统开发方法与实战 源码中所需要的所有jar包。如果某位手上有完整的文本材料也请发我一份,谢谢
Eclipse RCP富客户端平台,基于Eclipse开发的。
开发你的第一个EclipseRCP应用程序汇编.pdf
Eclipse RCP中使用第三方包,图文并茂很不错。
Eclipse RCP允许开发者使用eclipse结构风格设计弹性的可扩展的应用程序,可重用Eclipse中已存在的方法和编码模式。俗话说,万事开头难。Eclipse RCP入手可能会比较困难、费时。接下来我们将主要讲述如何让RCP工作. ...