我有很深的类层次结构,我想告诉JAXB绑定所有类。我有以下几种:
webpack-dev-server --mode development --hot
有什么方法可以绑定所有这些类,而无需在每个超类中使用@XmlSeeAlso,也不必提及所有子类,因为我有很多子类。
答案 0 :(得分:0)
如评论中所述,Java不支持通过运行时在反射时获取所有子类的请求功能。
但是应该可以在编译时检查项目中的所有类,并在jar文件中生成jaxb.index。
这样的注释处理器的一个例子(不完整,因此不能直接工作,但是要证明这个想法)如下:
@SupportedAnnotationTypes("*")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class JaxbProcessor extends AbstractProcessor {
@Override
public synchronized void init(ProcessingEnvironment env) {
super.init(env);
// Java 8 compiler plugin API to hook on compilation of every single class.
JavacTask.instance(env).addTaskListener(new TaskListener() {
// Prepare the writer
PrintWriter writer = new PrintWriter(env.getFiler().createResource(/* Details of output jaxb.index file */).openWriter());
Set<TypeElement> jaxbParents = new HashSet<>();
@Override public void started(TaskEvent taskEvent) {
// Nothing needs to be done here.
}
@Override public void finished(TaskEvent taskEvent) {
if(taskEvent.getKind() == ANALYZE) {
// This is where the compiler invokes our code.
// Side effect of this inspection is to collect all classes, that should be included in our jaxb.index
// into the jaxbParents set.
inspect(taskEvent.getTypeElement());
// Now simply write it to the file (output details to be provided).
// We should actually only write down difference from previous invocation. Let me fix it later.
jaxbParents.forEach(writer::println);
}
}
private void inspect(TypeElement type) {
// First inspect current class element
testForJaxbParent(type);
// Do not forget to inspect also inner classes.
type.getEnclosedElements().stream().filter(TypeElement.class::isInstance).map(TypeElement.class::cast).forEach(this::testForJaxbParent);
}
/**
* Test if the type should be added to JAXB index file.
*/
private boolean testForJaxbParent(TypeElement type) {
if(jaxbParents.contains(type)) {
// It's already in the set, so no need to bother with it.
return true;
}
if(type.getAnnotation(JaxbRoot.class) != null || testForJaxbParent((TypeElement) env.getTypeUtils().asElement(type.getSuperclass()))) {
// If our type is annotated with our special "extension" to JAXB - JaxbRoot, it means, that it is our
// root class, that needs to be added to the jaxb.index.
//
// If it is not annotated, then still test hierarchy of superclasses recursively, and if there is any
// superclass being the root, then add it including all children on the stack at the return from the
// recursion.
return jaxbParents.add(type);
}
return false;
}
});
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
// No real annotation processing needed.
return false;
}
}
一旦在批注中包含注解JaxbRoot
和该处理器,并且理想情况下,还可以通过服务描述符使Java自动在jar中找到该处理器,然后只需将jar添加到您的类路径中,仅注释您的root类,您将获得带有其所有子类的生成的jaxb.index。
即使将项目分成多个jar,将根类放在一个jar中,将子类放在另一个jar中,处理器仍会被调用并为每个jar生成索引文件。然后,您只需要将它们全部合并在一起,这可以是与处理器一起交付的一个实用程序类。