用于远程 JAR 的 Java 注释处理器

标签 java maven jpa annotation-processing javacompiler

一般问题

我有两个项目 A 和 B; B 依赖于 A。我想根据 A 中对象的注释,使用注释处理器在 B 中生成一些代码。当我使用正确的处理器实现运行编译时,只会拾取来自 B 的注释对象。

我知道默认情况下必须禁用扫描其他 JAR,因为您通常不想对所有依赖项进行注释扫描。我也明白,由于编译器的魔力,我可能无法做我想做的事——我对此知之甚少——但我希望不是这样。

具体案例

我的项目叫DB和WEB。 WEB 显然依赖于 DB 的 JPA 访问;这是在 Maven 中配置的。由于许多体系结构选择,DB 必须保留为单独的 JAR。 DB除了WEB使用的一些注解外不使用Spring; WEB 使用 Spring MVC。

我正在尝试使用注释处理器为我的所有 JPA 实体生成 CrudRepository 接口(interface)。 @Repository 对象应该放在 WEB 项目的 repo 包中,因此它们可以与 @Autowired 在我的 WEB 中的任何地方一起使用应用。我执行扫描的注释是 @javax.persistence.Entity,但我也尝试了自定义注释,结果相同。

@SupportedAnnotationTypes("javax.persistence.Entity")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class RepositoryFactory extends AbstractProcessor {

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        for (Element e : roundEnv.getElementsAnnotatedWith(Entity.class)) {
            if (e.getKind() != ElementKind.CLASS) {
                continue;
            }
            // TODO: implement logic to skip manually implemented Repos
            try {
                String name = e.getSimpleName().toString();
                TypeElement clazz = (TypeElement) e;

                JavaFileObject f = processingEnv.getFiler().
                        createSourceFile("blagae.web.repo." + name + "Repo");
                try (Writer w = f.openWriter()) {
                    PrintWriter pw = new PrintWriter(w);
                    pw.println("package blagae.web.repo;");
                    pw.println("import org.springframework.data.repository.CrudRepository;");
                    pw.printf("import %s;\n", clazz.toString());
                    pw.println("import org.springframework.stereotype.Repository;");
                    pw.println("@Repository");
                    pw.printf("public interface %sRepo extends CrudRepository<%s, Long> {}\n", name, name);
                    pw.flush();
                }
            } catch (IOException ex) {
                Logger.getLogger(RepositoryFactory.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        return false;
    }
}

理想情况下,我希望有人能告诉我一个简单的注释

@ComponentScan(basePackages = "blagae.db.*")

但当然,我不指望它,因为它可能会记录在某处。作为一种解决方法,我可以将 Spring 依赖项添加到数据库并在那里生成类,但它们仅在 Spring MVC 应用程序中起作用。我也对完成这项工作可能需要的配置保持警惕。

更新

一些额外的信息:我正在使用 maven-processor-plugin,我已经验证它在 WEB 项目中对于在那里定义的类工作良好。但是,我特别想要在依赖项目数据库中注释的访问类。我研究了 AbstractProcessor::getSupportedOptions 方法,但我不清楚我能在那里做什么。

Maven 配置:

<plugin>
    <groupId>org.bsc.maven</groupId>
    <artifactId>maven-processor-plugin</artifactId>
    <version>2.2.4</version>
    <configuration>
        <processors>
            <processor>blagae.utils.RepositoryFactory</processor>
        </processors>
    </configuration>
    <executions>
        <execution>
            <id>process</id>
            <goals>
                <goal>process</goal>
            </goals>
            <phase>generate-sources</phase>
        </execution>
    </executions>
</plugin>

建议

我的另一个随机想法是在 WEB 中为 DB 项目运行一个 JavaCompiler 进程,但是我将如何注入(inject)我的 Processor

最佳答案

注释处理器在您的项目(在您的情况下为 WEB)的编译阶段工作,编译器编译该项目。当前项目的依赖项已经编译,编译器(以及您的注解处理器)不会触及(或无权访问)第三方库 (DB)。

您可以尝试将注释处理器提取到单独的项目/jar 中,并在 WEB 和 DB 项目中使用它。在这种情况下,注释处理器将在具体项目的编译阶段创建 CrudRepository。 DB项目中所有生成的类都将在WEB中可用。

关于用于远程 JAR 的 Java 注释处理器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30534261/

相关文章:

javax.ws.rs 按目标进行 REST 测试 - 在哪里获取或设置服务器地址?

java - 使用 SVN 正确将 Apache nutch 导入 eclipse EE juno

java - Jenkins Maven 使用 GIT 发布

java - 注解@ActivationConfigProperty支持的属性的完整列表是什么

java - 将 JScrollPane 添加到覆盖的 JPanel

javascript - 使用 javascript 项目运行 Sonarqube 本地分析的最佳方式

java - NullPointerException原型(prototype):crawl

java - 如何正确映射主键由两个外键组成的实体,其中一个外键本身是复合的?

java - 如何在JPA/Hibernate中根据两个外键生成id?

java - JPA Composite key(所有字段都不是Null和PRI)