Интеграция манипулирования байт-кодом javassist с компиляцией maven

У меня есть проект maven, который компилируется с помощью компилятора javac/aspectj.
Я хочу запускать классы, которые были скомпилированы программой javassist, которая манипулирует скомпилированными классами и добавляет к ним материал.
Я думал, что использую "process-classes " для запуска моего инструмента.
Мой вопрос заключается в том, как лучше всего выполнить итерацию с помощью javassist по файлам классов, созданным в "target/classes", чтобы я мог впоследствии загрузить, исправить и сохранить.
Еще одно требование: чтобы запустить инструмент и на тестовых классах.
Если есть проект с открытым исходным кодом, который делает подобные вещи, было бы здорово увидеть живой пример.
Спасибо,
Авнер


person Avner Levy    schedule 14.09.2012    source источник


Ответы (1)


Недавно я наткнулся на ту же проблему и написал небольшой плагин Maven для применения преобразований классов Javassist во время сборки. Я разместил код на https://github.com/drochetti/javassist-maven-plugin.

Вы правильно догадались, вам следует использовать фазу process-classes, а сложная часть — это настройка пути к классам. После некоторых проб и ошибок мне удалось угадать всю проблему ClassPath среди Project, Dependencies и Javassist (пожалуйста, обратитесь к коду 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>

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);
    }

}

Примечание: для реализации преобразователя вам нужно будет добавить плагин в качестве зависимости вашего проекта, но не беспокойтесь, поскольку он используется только во время сборки, он может быть предоставлен в области действия, таким образом, не будет зависеть от вашей окончательной сборки.

Надеюсь, это поможет! Дайте мне знать, если вам нужна дополнительная помощь.

Даниэль

person Daniel Rochetti    schedule 29.12.2012
comment
Спасибо за решение. Я уже использовал плагин maven exec для запуска моего процессора, но я проверю его, как только у меня будет время. - person Avner Levy; 30.12.2012
comment
@Daniel Rochetti, плагин выглядит хорошо. Пожалуйста, просто продвиньте его немного дальше, опубликовав в центре и предоставив пример. - person Snicolas; 05.05.2014