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

加载dll api

我维护一个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

加载dll api

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/339618.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

12生肖 c语言设计,语言十二生肖教案

十二生肖中班教案十二生肖教案反思语言教案十二生肖点击进入查看全文2010虎年运势测算,走好运,发大财!宝宝三个月,来说一说之前购买的海量的婴儿用品的使用况(配合图片),大家可以都来讨论一下吧。太败了,之…

Quarkus的其他(非标准)CDI功能

Quarkus支持CDI(上下文和依赖注入)2.0,但并非全部,仅支持最常见的功能。 但是,Quarkus确实包含一些非标准功能,这些功能对于开发人员非常方便,我想在下面的视频中进行展示。 不管您是否熟悉CDI…

c语言输出星期几的英语表达,C语言程序设计: 输入年月日 然后输出是星期几...

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼#include main(){int year,month,day0,a,b,week,c,i,sum0,days,d;printf("please input year,month,days\n");scanf("%d,%d,%d",&year,&month,&days);for(i1;i{if (year%40){if(year%1000){if (ye…

将Visual Studio Code设置为jshell中的默认编辑器

Java Shell( jshell )是用于在Java中学习和进行原型制作的交互式工具。 它是在Java 9中引入的,从那以后,我在演示过程中偶尔使用它来进行一些快速原型制作,或者只是为了验证Java语言中的新功能。 由于jshell是命令行工…

c语言中组合函数,排列组合c怎么算 公式是什么

排列有两种定义,但计算方法只有一种,凡是符合这两种定义的都用这种方法计算。定义的前提条件是m≦n,m与n均为自然数。下面介绍排列组合c的计算方法及公式,供参考。排列组合中A和C怎么算排列A(n,m)n(n-1).(n-m1)n!/(n-m)!(n为下标,…

使用Spring WebFlux构建反应性REST API –第1部分

在本文中,我们将看到如何使用Spring WebFlux构建响应式REST API。 在进入反应式API之前,让我们看看系统是如何发展的,传统REST实现遇到的问题以及现代API的需求。 如果您查看从旧版系统到下文所述的现代系统的期望, 现代系统的期…

c语言中大写a对应的数字,123456789a

大写数字网今天精心准备的是《123456789a》,下面是详解!html里,怎么把<a>123456789</a>弄到中间来例如把a标签的字移到中间来<a123456789><&#…

gradle引入依赖:_Gradle善良:获得更多的依赖性见解

gradle引入依赖:在我们的大多数项目中,我们都依赖于其他代码,例如库或其他项目。 Gradle有一个不错的DSL来定义依赖关系。 依赖性在依赖性配置中分组。 这些配置可以自己创建,也可以通过插件添加。 一旦定义了依赖关系,我们就可以…

android popupwindow 调用方法,Android PopUpWindow使用详解

释放双眼,带上耳机,听听看~!一、概述1、PopupWindow与AlertDialog的区别最关键的区别是AlertDialog不能指定显示位置,只能默认显示在屏幕最中间(当然也可以通过设置WindowManager参数来改变位置)。而PopupWindow是可以指定显示位置…

高效应用程序的7个JVM参数

在撰写本文时(2020年3月),围绕垃圾收集和内存,您可以将600多个参数传递给JVM。 如果您包括其他方面,则JVM参数总数将很容易超过1000个。 😊。 任何人都无法消化和理解太多的论据。 在本文中,我们…

junit:junit_简而言之,JUnit:另一个JUnit教程

junit:junit为什么还要另一个JUnit教程? 对于Java世界中的开发人员而言, JUnit似乎是最受欢迎的测试工具 。 因此,难怪就此主题已经写了一些好书 。 但是我仍然经常遇到程序员,他们至多对这个工具及其正确用法都不太了解。 因此&…

16.04编译android 7.0,ubuntu16.04 编译Android5.1报错

hi kylin team,我使用 ubuntu16.04 构建 android 编译环境后编译 android5.1 时出现如下报错。请向开发团队反馈看能否给出解决方案,谢谢!当我使用 ubuntu16.04 构建 Android 编译环境后, 编译报错. 报错信息如下:/home/.../proj/.../anroidsrcroot/preb…

用Java将文件读入字节数组的7个示例

嗨,大家好,Java程序员经常在现实世界中遇到编程问题,他们需要将文件中的数据加载到字节数组中,该文件可以是文本或二进制文件。 一个示例是将文件的内容转换为String以便显示。 不幸的是,用于表示文件和目录的Java的Fi…

部署gradle_使用Gradle消除开发重新部署

部署gradle为了进行服务开发,我的团队最近从Grails转到了Dropwizard框架。 但是,我真正从Grails堆栈中真正错过的一件事是自动重新加载:对源文件的任何更改在保存后立即显示在运行的应用程序中,而无需重新启动。 事实证明&#xf…

android thrift https,HTTPS 学习

https是加密的http协议,通过不对称加密确认对称加密的密钥,之后使用对称加密进行通信。通信流程:客户端-服务端1. 请求服务器 并添加支持的 非对称加密算法 对称加密算法 hash算法----2. 服务器返回证书,加密算法的种类&#xff0…

如何使用Java创建AWS Lambda函数

在本教程中,我们将看到如何在Java中创建AWS Lambda函数,我告诉你,这样做非常容易…… 基本上,我们可以通过三种方式创建AWS Lambda函数: –通过实现RequestHandler接口 –通过实现RequestStreamHandler接口 –自定义…

android 主流机型排行榜,10月份Android热门手机机型Top 50排行榜

根据《尼尔森:第三季度Android占美智能手机43%份额》的报告显示, 43%的美国人拥有智能手机,智能手机用户数量在过去六个月增加了5%,而其中Android占据了43%的份额,iPhone占据了28%,很明显Android的份额优势…

ejb生命周期_EJB 3.x:生命周期和并发模型(第1部分)

ejb生命周期对于经验丰富的专业人员来说,Java EE组件生命周期和与并发相关的详细信息可能不是新知识,但是对于初学者来说,这可能会花费一些时间。 就EJB而言,了解其生命周期 (以及相关的并发场景)对于确保…

Quarkus on OpenJ9 JVM和资源消耗

除了本机模式,Quarkus在JVM模式下也能很好地运行,这有其自身的优势。 您可以使用替代的JVM,例如OpenJ9,它可以更好地消耗资源。 在下面的视频中,我将展示交换JVM的简便性。 在视频中,我在最新标签x86_64-a…

java 并发 线程安全_Java并发教程–线程安全设计

java 并发 线程安全在回顾了处理并发程序时的主要风险(例如原子性或可见性 )之后,我们将通过一些类设计来帮助我们防止上述错误。 其中一些设计导致了线程安全对象的构造,从而使我们能够在线程之间安全地共享它们。 作为示例&…