有没有一种方法可以调用Java中的延迟实现



我不确定这里的术语是否完全正确。

我有一个类,它包含一些静态方法,这些方法由很久以前编写的一些库代码中的其他几个类调用。

具有由其他几个类调用的静态方法的类引用了第三方类,该类现在具有版本2。

有没有一种方法可以对这个类进行编码,使其执行类似于";当这个静态方法被调用时,你需要调用一些东西来查看你应该使用哪个版本的库"?

这样,当我把这个库代码作为jar文件拉到一个新项目中时,我可以在每个项目中包含一些内容,这些内容将告诉我在库中使用静态方法的类使用特定版本。

这样我就不需要提供库中每个类的版本1和版本2。

我的延期是否正确?

可能是lambda函数?

有点像。Java不会加载类,除非你真的需要它。这意味着你可以做这样的事情:

public String getFoo() {
switch (versionRequired()) {
case 1: return new Version1Impl().getFoo();
default: return new Version2Impl().getFoo();
}
}
boolean versionRequired() {
// figure out which version is needed here.
// if you're having trouble with this, you can use `Class.forName` to check
// if a certain type is even available. Worst case scenario, you can
// ask a class for its own bytecode and hash that. This is very tricky.
return 1;
}
private static class Version1Impl {
public String getFoo() {
return new UseSomethingFromV1().getFoo();
}
}

这里奇怪的"重定向到内部类"内容的线索是,在切换分支被采用之前,内部类不会被加载,只要例如Version2Impl从未加载,你也永远不会得到它引用了一个不存在的类的错误(因为它是为该库的v2设计的,但只有v1可用(。


NB:关于版本检测方案:哈希类的问题是,一个类在两个主要版本之间可能没有改变(你希望它不同,但不会(。或者,另一方面,一个小的发布更新可能已经改变了它(现在不同了,但你不希望它是这样(。一种解决方案是对许多类进行散列,这有助于第一种情况(您希望注意到更改(,但会使第二种情况更糟。您可以使用例如try (InputStream in = String.class.getResourceAsStream("String.class")) {来实现这一点,它适用于任何类。将这个输入流通过hasher(如果你不知道如何搜索网络,这是一个非常常见的任务,有很多教程可以找到(。

许多库都有一种受支持的方式来询问它们的版本,但没有标准,所以请查看该库的文档。

根据第三方库的变化情况,您的问题有几种不同的解决方案。

我假设您的第三方类的版本2有新的方法,而不是您需要的版本1?

最简单的解决方案是针对库的版本2实现类,但要处理LinkageError(或更具体的子类,例如NoSuchMethodError(,并在发现这些错误时恢复到版本1调用。您还可以通过处理NoClassDefFoundError来处理它是否是一个完全不同的类。

或者,如果性能不重要,也可以使用反射。

目前,我已经创建了一个基于文件的解决方案。在类路径上查找一个文件,如果它在那里,请从文件中读取指示的版本。如果没有文件,请使用默认(原始(版本。

package com.nach.core.util.fhir.parser;
import java.io.File;
import org.hl7.fhir.instance.model.api.IBaseResource;
import com.nach.core.util.file.FileUtil;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.parser.IParser;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class FhirJsonParser {
private static final FhirContext CTX;

private static final IParser PARSER;
static {
File fhirContextFile = FileUtil.getFile("/fhir-context.txt");
if (fhirContextFile != null && fhirContextFile.exists()) {
String fhirContext = FileUtil.getAsString(fhirContextFile).trim();
if ("Dstu3".equals(fhirContext)) {
log.info("USING DSTU3 FOR FHIR PARSING");
CTX = FhirContext.forDstu3();
} else if ("R4".equals(fhirContext)) {
log.info("USING R4 FOR FHIR PARSING");
CTX = FhirContext.forR4();
} else {
CTX = FhirContext.forDstu3();
}
} else {
CTX = FhirContext.forDstu3();
}
PARSER = CTX.newJsonParser();
}
/**
* Generate a class from a json string.
*/
public static <T extends IBaseResource> T parse(String jsonString, Class<T> cls) {
try {
IParser parser = CTX.newJsonParser();
parser.setStripVersionsFromReferences(false);
CTX.getParserOptions().setStripVersionsFromReferences(false);
IParser jsonParser = CTX.newJsonParser();
T rtn = jsonParser.parseResource(cls, jsonString);
return rtn;
} catch (Exception exp) {
throw new RuntimeException(exp);
}
}
/**
* Generate a json string from a class.
*/
public static String serialize(IBaseResource resource) {
String rtn = PARSER.encodeResourceToString(resource);
return rtn;
}

}

最新更新