Eclipse RCP如何集成Spring

牵手byXR
2013-10-09 · TA获得超过3116个赞
知道小有建树答主
回答量:919
采纳率:0%
帮助的人:2179万
展开全部
因此,RCP与Spring集成的关键其实就在于如何加载上下文,个人的做法是在激活器(Activator)里面加上一个静态变量:private static ApplicationContext ctx;然后在start方法里面加上这样一句:ctx = new ClassPathXmlApplicationContext("applicationContext.xml");意思一目了然,就是读取类路径下名为applicationContext.xml的配置文件,如果有多个Spring配置文件的话也可以传入字符串数组,至此,上下文已经加载完毕。为了在其他类更方便地访问Spring管理的Bean,我们再写一个静态方法:public static Object getBean(String name) { return ctx.getBean(name); }传入参数是Bean在Spring里的配置名,返回的对象就是你想要的那个Bean了。举例来说,要在一个视图(ViewPart)里使用某Service,现在这样写就可以了:AnyService anyService = (AnyService) Activator.getBean("anyService");以上做法是我在之前的公司项目里用的,虽说与Spring集成这个目的是达到了,但能不能更优雅地把Bean倚赖注入给视图呢?直接按常规去写肯定是不行的,因为视图类并不受Spring管理,那好吧我将视图类加入到Spring配置里去,但是一跑你会发现报空指针异常了,说明某Bean根本没有注入进去。要解释这个问题首先要明白一点,正常RCP应用在构建一个视图的时候,是根据id去配置文件plugin.xml找到相应视图类,再进行实例化的,也就是说与Spring管理的视图完全是两个东西,倚赖注入当然不起作用了。原因说白了其实就是那么简单一回事,如果构建的时候直接返回Spring管理的视图就解决了,但实际要怎么做呢?网上找了一下,最后从一个开源项目里找到了线索,方法是自己实现IExecutableExtension和IExecutableExtensionFactory接口,具体代码如下:public class SpringExtensionFactory implements IExecutableExtension, IExecutableExtensionFactory { private String beanId; public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException { beanId = config.getAttribute("id"); } public Object create() throws CoreException { return Activator.getBean(beanId); }}有了这个SpringExtensionFactory之后,原来plugin.xml里的View配置就可以改成这个样子:<view name="ExampleView" class="springrcp.util.SpringExtensionFactory" id="exampleView"> </view>改动的关键主要是class属性的值,原来是写自己的视图类路径,现在则是SpringExtensionFactory类路径,而id属性要求与Spring配置里的相同。这样一改,构建视图时将会进入SpringExtensionFactory,并依次执行setInitializationData和create方法。首先看setInitializationData方法,传入参数里的config,里面记录了视图的各种属性,比如id、name和class,这里把id的值即exampleView取出来保存到全局变量beanId里(PS:如果打印一下参数propertyName和data,你会发现它们分别是class和null,假设class属性值为springrcp.utils.SpringExtensionFactory:exampleView的话,此时data将会是exampleView,这也是另一个为beanId赋值的方法)。然后看create方法,这里根据beanId获取到Spring管理的视图并返回,下面看一下这个视图类的具体代码:@Component public class ExampleView extends ViewPart { @Resource private ExampleBean exampleBean; public void createPartControl(Composite parent) { parent.setLayout(new GridLayout()); Label label = new Label(parent, SWT.NULL); label.setText(exampleBean.sayHello()); } public void setFocus() {}}其实跟平时写的没两样,要注意的是我用了Spring注解配置,@Component注解用处是把这个视图配置到上下文,id默认为类名首字母小写即exampleView,至于@Resource注解则是根据属性名exampleBean,在上下文找到相应的Bean并注入。视图本身只有一个Label而已,上面显示了sayHello方法的返回(其实就是那个传说中的Hello World),如无意外运行效果大概会是这样:集成的要点大概就上面那么多,其实还是挺简单的,特别是使用注解的时候,视图只要在plugin.xml里面配置就够了。当然话说回来,简单的RCP应用不一定用得上Spring,但如果是开发大型桌面程序的话,其中好处不用我多说大家都明白。而且一旦有了Spring这个“万能黏着剂”,再去集成其他框架如CXF什么的更是轻而易举了。 ========================我是分隔线========================12.12追加心得(上周来不及写了-_-|||):通过前面所写的SpringExtensionFactory,我们已经可以使用Spring管理的视图了,然而这还能更进一步,使之应用到其他的扩展点。比如说动作(Action),常见于菜单栏和工具栏上面的事件处理,根据习惯一般有两种编码方式:1、实现IAction接口(继承Action会更简单),然后修改ApplicationActionBarAdvisor的makeActions和fillMenuBar方法(视需求也可能是fillCoolBar或者fillStatusLine);2、实现IWorkbenchWindowActionDelegate接口,然后在plugin.xml里面配置菜单和动作的扩展点。个人之前用第一种方式比较多,原因是不想写太多东西到plugin.xml去,但现在既然集成Spring了,采用第二种方式无疑更加合理。<menu label="菜单" id="exampleMenu"> <separator name="exampleGroup"/></menu><actionlabel="打开/关闭" class="springrcp.util.SpringExtensionFactory" menubarPath="exampleMenu/exampleGroup" id="exampleAction"> </action>上面是某个ActionSet扩展点里面的代码,注意看Action配置的class属性,跟View配置一样写的是SpringExtensionFactory类路径,因为我要把它也交由Spring管理。以下是这个动作类的具体代码:@Component public class ExampleAction implements IWorkbenchWindowActionDelegate { public void run(IAction action) {try {IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); IViewPart view = page.findView("exampleView"); if (view == null) page.showView("exampleView");elsepage.hideView(view); } public void selectionChanged(IAction action, ISelection selection) {} public void dispose() {} public void init(IWorkbenchWindow window) {}}同样通过@Component注解实现Spring管理,此时就可以在里面注入其他Bean了,这里不再示范。事件处理的关键是run方法,功能是在当前页面寻找视图,找不到就重新显示,找得到就把它隐藏,由此控制视图的打开和关闭。好了,我们已经把RCP与Spring的集成又一次延伸,当然有需要的话你仍然可以继续下去。最后,我给大家补充说明一个集成带来的变化,由于Spring默认使用单例模式,这意味着运行过程中只会存在一个实例。为了方便理解我们把先前的ExampleView修改一下,首先增加一个全局变量size:private int size = 9;然后在createPartControl方法里面增加一句:label.setFont(new Font(null, "微软雅黑", size++, SWT.NORMAL));保存后运行,结合上面写的ExampleAction,反复执行打开和关闭视图,你会发现Hello World的字体在不断变大,说明size的状态被保留了。正常RCP应用里是不会这样的,因为每次打开视图都会创建一个实例,所以size一直是9不会改变。不丢失状态的好处是明显的,例如关闭视图并且要在下次打开时还原数值,之前让我想破头的效果,现在轻轻松松就实现了。倘若你没有这样的需求,甚至说单例会影响到功能实现的话,Spring也允许自己设置作用域。
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式