将javassist字节代码操作与maven编译集成

Avn*_*evy 4 java bytecode-manipulation maven annotation-processing javassist

我有一个使用javac/aspectj编译器编译的maven项目.
我想在编译javassist程序的类上运行,该程序操作编译的类并向其添加内容.
我想使用"进程类"阶段来运行我的工具.
我的问题是在"target/classes"中创建的类文件上使用javassist进行迭代的最佳方法是什么,以便我可以在之后加载,修复和保存.
另一个要求是在测试类上运行该工具.
如果有一个开源项目做类似的事情,那么很高兴看到一个实例.
谢谢,
Avner

Dan*_*tti 6

我最近偶然发现了同样的问题,我写了一个小的Maven插件来在构建期间应用Javassist类转换.我在https://github.com/drochetti/javassist-maven-plugin上分享了这些代码

你猜对了,你应该使用进程类阶段,而棘手的部分是类路径设置.经过一些试验和错误后,我设法猜测了Project,Dependencies和Javassist中的整个ClassPath问题(com.github.drochetti.javassist.maven.JavassistMojo.execute()如果你想检查解决方案,请参考代码).

上面有关于GitHub链接的一些指导,但基本上你需要:

1 - 在pom.xml上配置插件

<plugin>
    <groupId>com.github.drochetti</groupId>
    <artifactId>javassist-maven-plugin</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <configuration>
        <includeTestClasses>false</includeTestClasses>
        <transformerClasses>
            <transformerClass>com.domain.ToStringTransformer</transformerClass>
        </transformerClasses>
    </configuration>
    <executions>
        <execution>
            <phase>process-classes</phase>
            <goals>
                <goal>javassist</goal>
            </goals>
        </execution>
    </executions>
</plugin>
Run Code Online (Sandbox Code Playgroud)

2 - 实现一个ClassTransformer,这是一个例子:

/**
 * Silly transformer, used to hack the toString method.
 */
public class ToStringTransformer extends ClassTransformer {

    /**
     * We'll only transform subtypes of MyInterface.
     */
    @Override
    protected boolean filter(CtClass candidateClass) throws Exception {
        CtClass myInterface = ClassPool.getDefault().get(MyInterface.class.getName());
        return !candidateClass.equals(myInterface) && candidateClass.subtypeOf(myInterface);
    }

    /**
     * Hack the toString() method.
     */
    @Override
    protected void applyTransformations(CtClass classToTransform) throws Exception {
        // Actually you must test if it exists, but it's just an example...
        CtMethod toStringMethod = classToTransform.getDeclaredMethod("toString");
        classToTransform.removeMethod(toStringMethod);

        CtMethod hackedToStringMethod = CtNewMethod.make(
                "public String toString() { return \"toString() hacked by Javassist\"; }",
                classToTransform);
        classToTransform.addMethod(hackedToStringMethod);
    }

}
Run Code Online (Sandbox Code Playgroud)

注意:要实现一个转换器,你需要添加插件作为项目的依赖项,但不要担心,因为它只在构建时使用它可以提供作用域,这样它不会是你的依赖最终构建.

我希望有所帮助!如果您需要进一步的帮助,请告诉我.

丹尼尔