我可以在同一个Maven项目的源文件中动态生成和引用类吗?

Mar*_*ney 14 java bytecode intellij-idea maven byte-buddy

在Maven Build中,我使用字节代码生成库(Byte Buddy)动态生成一些Java类型.当然,这些类文件没有相应的源文件.这种方式只能生成几个类.该项目的大部分代码都是Java源代码.理想情况下,Java源代码将以静态方式引用生成的类型,而不是使用反射或运行时代码生成,这意味着类需要位于javac的编译类路径上.我是否可以在同一个Maven项目的编译类路径上获取生成的类,即没有单独的Maven项目和工件来保存包含源代码的Maven项目引用的生成的字节代码?

更新:我已经尝试将生成的类直接放入target/classesie project.build.outputDirectory,在Maven Build Lifecycle的早期,但它似乎不在类路径上.Maven编译器插件或 IDE 无法解析生成的类型.我还尝试使用Build Helper Maven插件在target包含生成的类的情况下添加一个额外的资源目录,然后自动将其复制到该目录中target/classes.该配置表现出相同的问题.

更新:我在GitHub上创建了一个完整的公共回购:https://github.com/mches/so-42376851

这是项目的Maven POM,我希望有静态类引用字节码增强类:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>demo</groupId>
        <artifactId>demo</artifactId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../pom.xml</relativePath>
    </parent>

    <artifactId>demo-enhanced</artifactId>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <executions>
                    <execution>
                        <phase>generate-resources</phase>
                        <goals>
                            <goal>unpack</goal>
                        </goals>
                        <configuration>
                            <artifactItems>
                                <artifactItem>
                                    <groupId>demo</groupId>
                                    <artifactId>demo-original</artifactId>
                                    <version>${project.version}</version>
                                    <overWrite>true</overWrite>
                                    <outputDirectory>${project.build.outputDirectory}</outputDirectory>
                                    <includes>**/*.class</includes>
                                    <excludes>META-INF/</excludes>
                                </artifactItem>
                            </artifactItems>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>net.bytebuddy</groupId>
                <artifactId>byte-buddy-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <phase>process-resources</phase>
                        <goals>
                            <goal>transform</goal>
                        </goals>
                        <configuration>
                            <initialization>
                                <entryPoint>net.bytebuddy.test.SimpleEntryPoint</entryPoint>
                                <groupId>demo</groupId>
                                <artifactId>demo-transformer</artifactId>
                            </initialization>
                            <transformations>
                                <transformation>
                                    <plugin>net.bytebuddy.test.SimplePlugin</plugin>
                                    <groupId>demo</groupId>
                                    <artifactId>demo-transformer</artifactId>
                                </transformation>
                            </transformations>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>
Run Code Online (Sandbox Code Playgroud)

这是父POM:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>demo</groupId>
    <artifactId>demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <modules>
        <module>demo-original</module>
        <module>demo-transformer</module>
        <module>demo-enhanced</module>
    </modules>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <byte-buddy.version>1.6.9</byte-buddy.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>net.bytebuddy</groupId>
                <artifactId>byte-buddy</artifactId>
                <version>${byte-buddy.version}</version>
            </dependency>
            <dependency>
                <groupId>demo</groupId>
                <artifactId>demo-original</artifactId>
                <version>${project.version}</version>
            </dependency>
            <dependency>
                <groupId>demo</groupId>
                <artifactId>demo-transformer</artifactId>
                <version>${project.version}</version>
            </dependency>
            <dependency>
                <groupId>demo</groupId>
                <artifactId>demo-enhanced</artifactId>
                <version>${project.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>net.bytebuddy</groupId>
                    <artifactId>byte-buddy-maven-plugin</artifactId>
                    <version>${byte-buddy.version}</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

</project>
Run Code Online (Sandbox Code Playgroud)

foo/Bar.java(原始来源):

package foo;

public class Bar {
}
Run Code Online (Sandbox Code Playgroud)

net/bytebuddy/test/SimplePlugin.java(字节码增强器):

package net.bytebuddy.test;

import net.bytebuddy.build.Plugin;
import net.bytebuddy.description.modifier.Visibility;


import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.implementation.FieldAccessor;

public class SimplePlugin implements Plugin {
    @Override
    public boolean matches(TypeDescription target) {
        return target.getName().equals("foo.Bar");
    }

    @Override
    public DynamicType.Builder<?> apply(DynamicType.Builder<?> builder, TypeDescription typeDescription) {
        if (typeDescription.getTypeName().equals("foo.Bar")) {
            builder = builder.defineField("qux", String.class, Visibility.PRIVATE)
                    .defineMethod("getQux", String.class, Visibility.PUBLIC)
                    .intercept(FieldAccessor.ofField("qux"))
                    .defineMethod("setQux", void.class, Visibility.PUBLIC)
                    .withParameter(String.class)
                    .intercept(FieldAccessor.ofField("qux"));
        }
        return builder;
    }
}
Run Code Online (Sandbox Code Playgroud)

foo/Baz.java(静态源文件引用动态类型):

package foo;

public class Baz {
    private Bar bar = new Bar();

    public String getQuux() {
        return bar.getQux();
    }

    public void setQuux(String quux) {
        bar.setQux(quux);
    }
}
Run Code Online (Sandbox Code Playgroud)

更新: Maven似乎理解一个涉及带有增强字节代码和静态类源代码的整合模块的结构,以及每个模块的单独模块,但IDE,IntelliJ和Eclipse无法理解这两种结构的类路径Maven确实如此.

小智 1

是的你可以。在预编译阶段生成类并将其放入 target/classes 文件夹中。