加载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
總結
以上是生活随笔為你收集整理的加载dll api_运行时类加载以支持不断变化的API的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 全球首创,杭州亚运会开幕式主火炬将用绿色
- 下一篇: linux命令显示一页内容(linux命