当前位置: 首页 > 知识库问答 >
问题:

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

岳出野
2023-03-14

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

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

我的项目叫做DB和WEB。WEB显然依赖DB进行JPA访问;这是在Maven中配置的。由于有许多架构选择,DB必须保持为一个单独的JAR。DB不使用Spring,除了WEB使用的一些注释;WEB使用SpringMVC。

我正试图用注释处理器为我的所有JPA实体生成crudepository接口。@Repository对象应该放在WEB项目中的repo包中,因此它们可以与@Autowired一起在WEB应用程序中的任何位置使用。我正在扫描的注释是@javax。坚持不懈实体,但我也尝试了自定义注释,结果相同。

@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依赖项添加到db中并在那里生成类,但它们只在SpringMVC应用程序中起作用。我还对可能需要的配置持谨慎态度。

一些额外的信息:我正在使用maven处理器插件,我已经验证了它在WEB项目中对那里定义的类运行良好。但是,我特别希望在依赖项项目DB中注释访问类。我已经研究了方法Abstract处理器::getSupportdOptions,但我不清楚我可以在那里做什么。

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进程,但是如何注入处理器呢?


共有3个答案

宋望
2023-03-14

在您的项目中包括META-INF/bean。xml文件,其中将包含以下内容:

<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee <a href="http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd">http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"</a>
       version="1.1" bean-discovery-mode="all">
</beans>

试试看。您应该使用JavaEE7/CDI1.1。有关更多信息,请参阅JavaEE7部署描述符。

您还可以参考这个相关问题:如何@injectobject从包含为jar的不同项目模块中注入对象

邵飞鸿
2023-03-14

就我个人而言,我将在单独的maven模块中提取注释处理器,并从WEB模块向其添加依赖项。

然而,对于成功触发注释处理器来说,这并不重要。

为了让注释处理器工作,您必须提供两件事:

  • 扩展javax的类。注释。处理。抽象处理器
  • 一个特殊文件,嵌套在项目的META-INF/services

既然您提到目前没有生成任何类,我就假设您丢失了元文件。因此,打开WEB项目并导航到src/main/resources文件夹。在中,您必须创建一个META-INF文件夹,其中包含嵌套的services文件夹。然后,在services中创建一个名为javax的文件。注释。处理。处理器。文件内容应列出注释处理器的完全限定类名。如果有多个注释处理器,则完全限定的类名应位于单独的行中。但既然你只有一个,你就会有这样的东西:

com.yourdomain.processor.RepositoryFactory

请注意,您必须使用注释处理器的实际完全合格类名更改此行。

最后,您应该得到类似的结构:

这个元文件很重要,因为否则编译器不知道用户定义的注释处理器。有了它,它将利用所有注册的处理器。

之后,当您执行mvn清理安装时将清理并构建所有模块。但是,由于编译器现在会知道您的注释处理器,因此会触发它。所有生成的源(默认情况下)将位于目标/生成的源文件夹中。此外,它们都将位于您在注释过程中配置的包下,即blagae。网状物回购

为了在代码中使用生成的源代码,您必须将targer/生成的源代码添加到项目类路径中。如果您不想依赖IDE来完成此操作,您可以扩展maven

<build>
    <resources>
        ...
        <resource>
            <directory>${project.build.directory}/generated-resources</directory>
        </resource>
    </resources>
</build>

苗学民
2023-03-14

Annotation processor在项目的编译阶段工作(在您的例子中是WEB),编译器编译此项目。当前项目的依赖项已经编译,编译器(以及您的注释处理器)不会接触(或无法访问)第三方库(DB)。

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

 类似资料:
  • 我正在使用注释处理器来处理方法参数的注释。 用于参数的注释类型有一个注释@参数 现在,当注释处理器运行时,我想检查参数注释()是否有参数注释。我通过执行以下代码来实现这一点。 由于某种原因,arg始终为空。是否有注释未返回的原因?

  • 我正在尝试实现注释处理器(AnnotationProcessor)。我遵循这个教程。 我能够调试注释处理器,调试器转到方法:、、、但它不转到方法。 我在网上找不到有用的东西。你能告诉我为什么会发生这种情况以及如何解决吗? 非常感谢。

  • 我有下面的课程。两个注释(AnnotA和AnnotB),一个类的子类。java'(带@AnnotA)及其“父”基。java'(带有@AnnotB)。 编译子对象时。java,我的注释处理器报告AnnotA,但它不报告在Base中找到的注释(AnnotB)。JAVA 安诺塔。JAVA 阿诺特。JAVA 基础JAVA 小孩JAVA MyProc。JAVA 这是编译过程及其输出,正如您所看到的,没有关于

  • 问题内容: 我正在考虑启动一个项目,该项目用于使用批注在Java中生成代码(我不会详细介绍,因为它并不重要)。我对项目的有效性和实用性感到好奇,令我震惊的是对Annontation Processor Tool(apt)的依赖。 我无法从经验中得知,我想知道的是在Java中使用注释处理的缺点是什么? 这些可以是任何东西,包括以下各项: 写处理器时很难做TDD 很难将处理包含在构建系统中 处理需要很

  • 问题内容: 我有一个名为@Pojo的自定义注释,可用于自动生成Wiki文档: 我这样使用它: 注释资源方法,以便注释处理器可以自动生成描述所需资源和类型的Wiki页面。 我需要在注释处理器中读取该字段的值,但出现运行时错误。 在我的处理器的源代码中,我有以下几行: 但实际的类不适用于处理器。我认为我需要一个替代品来代替实际课程。我不确定该怎么买。 我得到的错误是: 该是我的一个提到的一类注释。 不

  • 我使用抽象处理器创建了一个自定义注释和注释处理器。这意味着我想在编译之前进行注释处理。我将自定义注释和处理器导出为Jar,并尝试将其与简单的java测试程序一起使用。我确信在编译时它会找到我的java处理器类,但不知何故,我并没有得到我在控制台上期望的o/p。下面是我的处理器中处理方法的代码。 此外,我故意使用以便我得到一个版本警告,它确认当我执行一个测试类时,它找到了我的注释处理器。 这里是我的

  • 问题内容: 我有一个自定义注释,它是Processor&ProcessorFactory。如何配置Ant构建文件,使得: 注释处理器应用于带注释的类,并在“ gen”文件夹内生成源文件 生成的源文件(通过注释处理)可以被项目中的其他源文件使用。 问题答案: 这不漂亮,但这是我要做的。(来源javac ant任务 javac手册页)使用compilerarg属性,我可以传入javac ant任务未直

  • 问题内容: 在阅读 Java 中的自定义注释处理器的代码时,我注意到处理器方法中的这段代码: 碰巧我也在使用自定义注释处理器,所以我想在我的注释处理器中使用上面的代码段。 我以这种方式尝试了上面的代码: & 这条路: 但我没有注意到处理器行为的任何变化。我得到了支票,但看不到有什么用。 我想知道在处理特定回合时有用的用例。 问题答案: 这两项检查都很重要,但是直到在同一项目中一次运行多个注释处理器