Я изучаю АОП и использую gradle + aspectJ для создания своего кода. Итак, я сделал, как говорится в какой-то демонстрации, добавил аспектJtools в начало build.gradle.
dependencies {
...
classpath 'org.aspectj:aspectjtools:1.9.5'
}
И в app / build.gradle добавьте задачу в код плетения:
variants.all { variant ->
JavaCompile javaCompile
if (variant.hasProperty('javaCompileProvider')) {
//android gradle 3.3.0 +
javaCompile = variant.javaCompileProvider.get()
} else {
javaCompile = variant.javaCompile
}
def buildType = variant.buildType.name
javaCompile.doLast {
MessageHandler handler = new MessageHandler(true)
String[] javaArgs = [
"-showWeaveInfo",
"-1.8",
"-inpath", javaCompile.destinationDir.toString(),
"-aspectpath", javaCompile.classpath.asPath,
"-d", javaCompile.destinationDir.toString(),
"-classpath", javaCompile.classpath.asPath,
"-bootclasspath", project.android.bootClasspath.join(File.pathSeparator)
]
new Main().run(javaArgs, handler)
String[] kotlinArgs = [
"-showWeaveInfo",
"-1.8",
"-inpath", project.buildDir.path + "/tmp/kotlin-classes/" + buildType,
"-aspectpath", javaCompile.classpath.asPath,
"-d", project.buildDir.path + "/tmp/kotlin-classes/" + buildType,
"-classpath", javaCompile.classpath.asPath,
"-bootclasspath", project.android.bootClasspath.join(File.pathSeparator)
]
new Main().run(kotlinArgs, handler)
for (IMessage message : handler.getMessages(null, true)) {
switch (message.getKind()) {
case IMessage.ABORT:
case IMessage.ERROR:
case IMessage.FAIL:
log.error message.message, message.thrown
break
case IMessage.WARNING:
case IMessage.INFO:
log.info message.message, message.thrown
break
case IMessage.DEBUG:
log.debug message.message, message.thrown
break
}
}
}
}
Затем я добавьте мой аспект, например:
@Aspect
public class AspectInCommon extends BaseAspect {
@Pointcut("execution(* com.example.cheng.test.MainActivityKt.on**(..))")
public void kotlinMainOn() {
}
@After("kotlinMainOn()")
public void hookKotlinMain(JoinPoint joinPoint) throws Throwable {
log(joinPoint.getSignature().toLongString());
}
...
}
И мой MainActivity выглядит так:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
...
}
}
Таким образом, я действительно вплел аспект в свой код. И вот некоторые результаты: Сначала он работает нормально, пока я снова не нажму кнопку «Отладка внизу», после чего весь вывод больше не запускается. Затем, после нескольких тестов, я обнаружил, что после чистой сборки он переплетается только в том случае, если один из моих файлов находится в kotlin. Поэтому я пытаюсь изменить mainActivity и файл аспекта на java или kotlin. И вот результаты теста:
MainActivity language Aspect language Weave results
Java Java Weave every time
Java Kotlin Weave after clean build *
Kotlin Java Weave after clean build
Kotlin Kotlin Weave after clean build
*: я поместил файл аспекта в подмодуль, и он вылетел во второй сборке после чистой сборки. Сообщение об ошибке:
java.lang.NoSuchMethodError: No static method aspectOf()
Интересно, как сделать аспектное переплетение кода kotlin каждый раз, а не только один раз после чистой сборки, потому что большая часть кода моего реального проекта основана на kotlin. Идеально не использовать просто плагин. Большое спасибо.