Avro 架构中的多态性和继承

2022-09-01 09:59:25

是否可以编写一个Avro模式/ IDL来生成一个Java类,该类要么扩展基类,要么实现接口?似乎生成的 Java 类扩展了 .因此,实现可能是要走的路。但是,我不知道这是否可能。org.apache.avro.specific.SpecificRecordBase

我看过一些示例,其中包含在每个特定架构中定义显式“类型”字段的建议,其关联性大于继承语义。

我在我的工厂类和代码的其他部分中大量使用我的基类,并使用泛型,如.目前,我让它从JSON架构生成代码,它支持继承。<T extends BaseObject>

另一个附带问题:是否可以使用 IDL 来定义没有协议定义的记录?我认为答案是否定的,因为编译器抱怨缺少协议关键字。

帮助赞赏!谢谢。


答案 1

我找到了解决这个问题的更好方法。查看Avro中的架构生成源,我发现类生成逻辑在内部使用速度架构来生成类。

我修改了模板以实现我的特定接口。有一种方法可以使用maven构建插件中的配置来指定速度目录的位置。record.vmtemplateDirectory

我也改用了使用代替.SpecificDatumWriterreflectDatumWriter

<plugin>
  <groupId>org.apache.avro</groupId>
  <artifactId>avro-maven-plugin</artifactId>
   <version>${avro.version}</version>
   <executions>
    <execution>
      <phase>generate-sources</phase>
      <goals>
        <goal>schema</goal>
      </goals>
      <configuration>
         <sourceDirectory>${basedir}/src/main/resources/avro/schema</sourceDirectory>
         <outputDirectory>${basedir}/target/java-gen</outputDirectory>
         <fieldVisibility>private</fieldVisibility>
         <stringType>String</stringType>
         <templateDirectory>${basedir}/src/main/resources/avro/velocity-templates/</templateDirectory>
       </configuration>
    </execution>
  </executions>
</plugin>

答案 2

我希望这对其他人有所帮助,如果我在这里写它,我已经为这种情况创建了maven插件 - https://github.com/tunguski/interfacer

它遍历自动生成的类,并检查它们是否符合特定包中类路径上的接口。如果是,则将接口添加到类中。它适用于通用接口,至少在我必须处理的基本示例中是这样。

该插件不是特定于avro的,可用作生成的代码后处理器,因此它也可以在其他情况下使用。

<!-- 
  post process avro generated sources and add interfaces from package
  pl.matsuo.interfacer.showcase to every generated class that has 
  all methods from specific interface
 -->
<plugin>
    <groupId>pl.matsuo.interfacer</groupId>
    <artifactId>interfacer-maven-plugin</artifactId>
    <version>0.0.6</version>
    <executions>
        <execution>
            <configuration>
                <interfacesDirectory>${project.basedir}/src/main/java</interfacesDirectory>
                <interfacePackage>pl.matsuo.interfacer.showcase</interfacePackage>
            </configuration>
            <goals>
                <goal>add-interfaces</goal>
            </goals>
        </execution>
    </executions>
</plugin>
// src/main/java manually defined interface
public interface HasName {
  String getName();
}

// target/generated-sources/avro
public class Person {

  String name;

  public String getName() {
    return name;
  }
  // [...]
}

public class Company {

  String name;

  public String getName() {
    return name;
  }
  // [...]
}

// after this plugin run

// target/generated-sources/avro
public class Person implements HasName {

  String name;

  public String getName() {
    return name;
  }
  // [...]
}

public class Company implements HasName {

  String name;

  public String getName() {
    return name;
  }
  // [...]
}

推荐