Eclipse RCP:使用@Inject时如何通过本地上下文解决依赖问题
刚好我之前在维护RCP3项目的时候,做过引入RCP4 DI并处理多视图作用域的改造,给你分享一下具体的实现思路和步骤:
在RCP3应用中引入RCP4 DI的视图级作用域实现方案
1. 先确认基础环境已就绪
既然你已经把全局服务注入到了顶层Application Context,首先要确保项目已经引入了RCP4 DI的核心依赖:org.eclipse.e4.core.di、org.eclipse.e4.core.contexts这几个bundle必须在你的target platform里,并且已经添加到项目的依赖中。另外要保证顶层IEclipseContext是正确初始化并全局可获取的(比如在应用启动类里把它存到静态容器,或者通过PlatformUI的服务桥接获取)。
2. 为每个视图创建独立的本地上下文
RCP4的DI是基于上下文层级结构的,每个视图可以创建顶层上下文的子上下文——这个子上下文就是视图的本地作用域,它会继承顶层上下文的所有服务,同时可以存储视图独有的实例和配置,天然实现隔离。
具体代码实现
在你的RCP3视图类(继承ViewPart)中,重写createPartControl和dispose方法:
import org.eclipse.e4.core.contexts.IEclipseContext; import org.eclipse.e4.core.contexts.ContextInjectionFactory; import org.eclipse.ui.part.ViewPart; public class MyMultiInstanceView extends ViewPart { private IEclipseContext localViewContext; @Override public void createPartControl(Composite parent) { // 1. 获取全局顶层Application Context IEclipseContext appContext = AppContextHolder.getGlobalContext(); // 2. 创建视图专属的子上下文 localViewContext = appContext.createChild(); // 3. 往本地上下文添加视图独有的对象(比如视图状态、临时数据) localViewContext.set(ViewSessionState.class, new ViewSessionState()); // 如果是带参数打开的视图,可以把secondaryId存入上下文做区分 localViewContext.set("viewSecondaryId", getViewSite().getSecondaryId()); // 4. 对当前视图实例执行DI注入 ContextInjectionFactory.inject(this, localViewContext); // 5. 后续正常创建视图UI组件... } @Override public void dispose() { // 视图销毁时必须销毁本地上下文,避免内存泄漏 if (localViewContext != null) { localViewContext.dispose(); } super.dispose(); } }
注:AppContextHolder是你自己实现的静态类,用来全局持有顶层Application Context,比如在Application类的start方法里初始化并存储。
3. 处理同类型多视图的隔离与区分
由于每个视图实例的本地上下文都是独立的子上下文,所以:
- 注入的全局服务会从顶层上下文获取(共享实例)
- 注入的本地对象(比如上面的
ViewSessionState)每个视图实例都是独立的,天然实现隔离
如果需要针对同类型的不同视图实例做差异化处理,可以:
- 在创建本地上下文时存入视图的
secondaryId或自定义参数(如上面代码所示) - 在需要区分的地方通过
@Named注解注入标识:
@Inject public void initView(@Named("viewSecondaryId") String secondaryId) { // 根据secondaryId做不同的初始化逻辑 }
4. 视图内DI的使用方式
在视图类里,你可以完全使用RCP4的DI注解:
- 注入全局服务:
@Inject private MyGlobalDataService dataService; - 注入本地上下文对象:
@Inject private ViewSessionState sessionState; - 直接注入本地上下文:
@Inject private IEclipseContext localContext;(方便动态修改上下文内容)
5. 关键注意事项
- 上下文销毁:必须在视图
dispose方法里销毁本地上下文,否则会持有视图对象导致内存泄漏。 - 服务桥接:如果需要注入RCP3原生服务(比如
IWorkbenchPage),要引入org.eclipse.e4.ui.workbenchbundle,它会自动把RCP3的服务桥接到RCP4的上下文里。 - 注解编译:确保项目启用了注解处理器,
org.eclipse.e4.core.di.annotations的注解需要编译时生成代理类,否则注入会失效。
内容的提问来源于stack exchange,提问作者Teshte
相关产品推荐
相关产品推荐

