Eclipse RCP如何集成Spring

Eclipse RCP如何集成Spring,第1张

因此,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 beanIdpublic 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配置就可以改成这个样子:改动的关键主要是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管理的视图并返回,下面看一下这个视图类的具体代码:@Componentpublic class ExampleView extends ViewPart { @Resourceprivate ExampleBean exampleBeanpublic 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了,采用第二种方式无疑更加合理。上面是某个ActionSet扩展点里面的代码,注意看Action配置的class属性,跟View配置一样写的是SpringExtensionFactory类路径,因为我要把它也交由Spring管理。以下是这个动作类的具体代码:@Componentpublic 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也允许自己设置作用域。

让你弯销世的Action实现org.eclipse.ui.IWorkbenchWindowActionDelegate,该接口有public void init(IWorkbenchWindow window)方法可以获取到window对象。一般来说,工作台菜单和工具栏的Action需要实现该埋肢接口来获取到工作台窗斗裤口对象。

Action写在扩展点里?

这不是慎铅码通常的处理方式。

你应该自定义一个WorkbenchAdvisor,它需要实现createActionBarAdvisor,于是在该ActionBarAdvisor中,你可以定义它的Actions。

这些Action都是激毕可宽哪以继承的,然后重写他们的isEnabled()就好


欢迎分享,转载请注明来源:内存溢出

原文地址: http://www.outofmemory.cn/bake/11982545.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-20
下一篇 2023-05-20

发表评论

登录后才能评论

评论列表(0条)

保存