我维护一个IntelliJ插件 ,可以改善编写Spock规范的体验。 这个项目的挑战是在单个代码库中支持多个不兼容的IntelliJ API版本。 回想起来,该解决方案很简单(这是狂野的适配器模式的一个示例),但最初它需要一些思想和示例。 我今天再次在代码中修复对新版本的支持 ,因此决定记录一下我最初是如何解决该问题的。

根本问题是我的编译代码可以在存在多个不同API版本的JVM运行时环境中加载。 我的解决方案是将项目分为四个部分:

  • 一个主项目,它不依赖于任何变化的API调用,因此在所有API版本中都是兼容的。 主项目还具有根据其自身所在的运行时环境加载适当的适配器实现的代码。在这种情况下,我可以利用IntelliJ PicoContainer进行服务查找,但是反射API或依赖项注入也具有需要什么。
  • 一组抽象适配器,为主项目提供使用的API。 该项目也不依赖于API版本之间不同的任何代码。
  • 为每个受支持的API版本实现抽象适配器的类集。 每组适配器包装不断变化的API调用,并针对特定的API版本进行编译。

最简单的处理方法是重构API中的某些内容。 这也是实际上破坏了最后一个版本的原因。 我的主要代码需要com.intellij.lang.Language的Groovy实例。 该实例在IntelliJ 14中移动。

该代码一直持续到14岁,因此在这种情况下,我要添加一个新适配器。 在适配器模块中,我有一个抽象类LanguageLookup.java :

package com.cholick.idea.spock;import com.intellij.lang.Language;
import com.intellij.openapi.components.ServiceManager;public abstract class LanguageLookup {public static LanguageLookup getInstance() {return ServiceManager.getService(LanguageLookup.class);}public abstract Language groovy();
}

我支持的最低IntelliJ API版本是11。在11-13之间查找Groovy语言实例是恒定的,因此第一个具体适配器位于针对IntelliJ 11 API编译的模块中。 LanguageLookup11.java :

package com.cholick.idea.spock;import com.intellij.lang.Language;
import org.jetbrains.plugins.groovy.GroovyFileType;public class LanguageLookup11 extends LanguageLookup {public Language groovy() {return GroovyFileType.GROOVY_LANGUAGE;}
}

最新的API引入了重大变化,因此第二个具体适配器位于针对其API版本14编译的模块中。 LanguageLookup14.java :

package com.cholick.idea.spock;import com.intellij.lang.Language;
import org.jetbrains.plugins.groovy.GroovyLanguage;public class LanguageLookup14 extends LanguageLookup {public Language groovy() {return GroovyLanguage.INSTANCE;}
}

最后,主项目有一个SpockPluginLoader.java类,它根据加载的运行时API注册正确的适配器类(我省略了一些与示例无关的方法):

package com.cholick.idea.spock.adapter;import com.cholick.idea.spock.LanguageLookup;
import com.cholick.idea.spock.LanguageLookup11;
import com.cholick.idea.spock.LanguageLookup14;
import com.intellij.openapi.application.ApplicationInfo;
import com.intellij.openapi.components.ApplicationComponent;
import com.intellij.openapi.components.impl.ComponentManagerImpl;
import org.jetbrains.annotations.NotNull;
import org.picocontainer.MutablePicoContainer;public class SpockPluginLoader implements ApplicationComponent {private ComponentManagerImpl componentManager;SpockPluginLoader(@NotNull ComponentManagerImpl componentManager) {this.componentManager = componentManager;}@Overridepublic void initComponent() {MutablePicoContainer picoContainer = componentManager.getPicoContainer();registerLanguageLookup(picoContainer);}private void registerLanguageLookup(MutablePicoContainer picoContainer) {if(isAtLeast14()) {picoContainer.registerComponentInstance(LanguageLookup.class.getName(), new LanguageLookup14());} else {picoContainer.registerComponentInstance(LanguageLookup.class.getName(), new LanguageLookup11());}}private IntelliJVersion getVersion() {int version = ApplicationInfo.getInstance().getBuild().getBaselineVersion();if (version >= 138) {return IntelliJVersion.V14;} else if (version >= 130) {return IntelliJVersion.V13;} else if (version >= 120) {return IntelliJVersion.V12;}return IntelliJVersion.V11;}private boolean isAtLeast14() {return getVersion().compareTo(IntelliJVersion.V14) >= 0;}enum IntelliJVersion {V11, V12, V13, V14}
}

最后,在需要Groovy com.intellij.lang.Language的代码中,我获得了LanguageLookup服务的所有权并调用其groovy方法:

...
Language groovy = LanguageLookup.getInstance().groovy();
if (PsiUtilBase.getLanguageAtOffset(file, offset).isKindOf(groovy)) {
...

该解决方案允许相同的已编译插件JAR跨版本11-14支持IntelliJ的各种API。 我以为Android开发人员通常会实现这样的解决方案,但是作为Web应用程序开发人员,我从来不必编写这种解决方案。

翻译自: https://www.javacodegeeks.com/2014/09/runtime-class-loading-to-support-a-changing-api.html

运行时类加载以支持不断变化的API相关推荐

  1. 加载dll api_运行时类加载以支持不断变化的API

    加载dll api 我维护一个IntelliJ插件 ,可以改善编写Spock规范的体验. 这个项目的挑战是在单个代码库中支持多个且不兼容的IntelliJ API版本. 回想起来,该解决方案很简单(这 ...

  2. jvm运行时类加载机制_JVM体系结构:JVM类加载器和运行时数据区

    jvm运行时类加载机制 各位读者好! 在JVM系列的上一篇文章中,开发人员了解了Java虚拟机(JVM)及其体系结构. 本教程将帮助开发人员正确回答以下主题的问题: ClassLoader子系统 运行 ...

  3. 【容器运行时】一文理解 OCI、runc、containerd、docker、shim进程、cri、kubelet 之间的关系

    参考 docker,containerd,runc,docker-shim 之间的关系 Containerd shim 进程 PPID 之谜 内核大神教你从 Linux 进程的角度看 Docker R ...

  4. 1.Containerd容器运行时初识与尝试

    0x00 前言简述 1.基础介绍 2.专业术语 3.架构简述 0x01 安装配置 1.Ubuntu安装Containerd.io流程 0x02 简单使用 1.镜像拉取与运行 2.创建和使用网络 3.与 ...

  5. WebAssembly运行时库(WASM runtime:wasmer 或 wasmtime)\将rust官方demo猜数字编译为WASI目标并使用Wasmer运行

    文章目录 WebAssembly运行时库(wasmer 或 wasmtime.wasmer-go) 一.引子 1. 什么是WASI 2. 有哪些优秀的 WebAssembly 运行时? 二.wasme ...

  6. ART运行时垃圾收集(GC)过程分析

    ART运行时与Dalvik虚拟机一样,都使用了Mark-Sweep算法进行垃圾回收,因此它们的垃圾回收流程在总体上是一致的.但是ART运行时对堆的划分更加细致,因而在此基础上实现了更多样的回收策略.不 ...

  7. 一种基于Gradient Boosting的公交车运行时长预测方法

    一种基于Gradient Boosting的公交车运行时长预测方法 赖永炫1,2, 杨旭3, 曹琦4, 曹辉彬1,2, 王田5, 杨帆6 1 厦门大学信息学院,福建 厦门 361005 2 厦门大学深 ...

  8. 微软医疗ai_微软ai运行时内部的外观

    微软医疗ai Today, I want to wear my software archeology hat, and share with you one story about the AI e ...

  9. 蚂蚁云原生应用运行时的探索和实践 - ArchSummit 上海

    点击上方"程序猿技术大咖",关注并选择"设为星标" 回复"加群"获取入群讨论资格! Mesh 模式的引入是实现应用云原生的关键路径,蚂蚁集团 ...

最新文章

  1. 「2019中国大数据技术大会」超值学生票来啦!
  2. android仿苹果滑动,Android开发仿IOS的滑动按钮
  3. 计算机网络项目——最小网元设计(阶段四)
  4. go语言switch语句用法
  5. 机器学习基础算法12-回归实例-广告预测
  6. iOS开发之报错:IntxLNK
  7. ps打开闪退_Photoshop2020安装教程,会安装软件是学ps的前提
  8. Manjaro Linux下使RIME支持86/98五笔输入法
  9. MySQL 定时备份数据库(全)
  10. 代码 点胶gcode_Gcode代码解释
  11. 如何在网页title前面加logo
  12. ThinkPHP6 缩略图上传
  13. java 如何循环执行一个对象_养猪场循环生态循环模式及其效益分析,当前牧草成为生态循环猪场效益更好的选择,如何打造一个现代生态循环的高效益猪场?...
  14. HDU 6194:string string string
  15. android xml 圆形图片,Android ImageView实现圆角,圆形图片
  16. python连接SQL Server:Pymssql模块
  17. Ubuntu 出现这个提示“Waiting for cache lock: Could not get lock /var/lib/dpkg/lock-frontend.”?
  18. 从JSON进化到BSON
  19. DVWA 不跳转_利用url跳转漏洞冒充公安局官网的骚操作
  20. 易迅网接入微信支付,为消费者提供购物体验

热门文章

  1. 2020蓝桥杯省赛---java---C---3( 跑步训练)
  2. java开发可以转什么软件有哪些_转行开发软件Java编程必须会什么
  3. bmp180气压传感器工作原理_陕西压力传感器的工作原理信息推荐
  4. java安全 ——JAAS(Java 认证和授权服务)开发指南
  5. C语言的运算符的优先级与结合性+ASCII表
  6. web安全测试视频课程专题_有关有效企业测试的视频课程
  7. api自动化测试_API测试和自动化101:基本指南
  8. 文档 修订 非修订区别_修订和不变性
  9. hashmap大小_调整HashMap的大小:未来的危险
  10. cassandra_Spring Boot Cassandra的第一步