У меня есть проект maven, который компилируется с помощью компилятора javac/aspectj.
Я хочу запускать классы, которые были скомпилированы программой javassist, которая манипулирует скомпилированными классами и добавляет к ним материал.
Я думал, что использую "process-classes " для запуска моего инструмента.
Мой вопрос заключается в том, как лучше всего выполнить итерацию с помощью javassist по файлам классов, созданным в "target/classes", чтобы я мог впоследствии загрузить, исправить и сохранить.
Еще одно требование: чтобы запустить инструмент и на тестовых классах.
Если есть проект с открытым исходным кодом, который делает подобные вещи, было бы здорово увидеть живой пример.
Спасибо,
Авнер
Интеграция манипулирования байт-кодом javassist с компиляцией maven
Ответы (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);
}
}
Примечание: для реализации преобразователя вам нужно будет добавить плагин в качестве зависимости вашего проекта, но не беспокойтесь, поскольку он используется только во время сборки, он может быть предоставлен в области действия, таким образом, не будет зависеть от вашей окончательной сборки.
Надеюсь, это поможет! Дайте мне знать, если вам нужна дополнительная помощь.
Даниэль