I have an annotation like:
@Retention(RUNTIME)
@Target(AnnotationTarget.FUNCTION)
annotation class MyAspect(val value: MyType)
I have an aspect for this annotation:
@Aspect
open class MyAspectInterceptor {
@After("@annotation(com.example.MyAspect)")
suspend fun wrapMethod(point: JoinPoint): Unit {
// do some logic in coroutine
}
}
I'm weaving in post compile using freefair plugin. In process of weaving errors appears:
[error] formal unbound in pointcut
[error] Found @AspectJ annotation on a non around advice not returning void 'wrapMethod(Lorg/aspectj/lang/JoinPoint;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;'
[error] the parameter $completion is not bound in [all branches of] pointcut
I then decompiled this class and found that the suspend
modifier adds another parameter to this method and changes its signature:
@Aspect
@Metadata(mv = {1, 8, 0}, k = 1, xi = 48, d1 = {"\000 \n\002\030\002\n\002\020\000\n\002\b\002\n\002\030\002\n\000\n\002\020\002\n\000\n\002\030\002\n\002\b\002\b\027\030\0002\0020\001B\005\006\002\020\002J\031\020\005\032\0020\0062\006\020\007\032\0020\bH\001\000\006\002\020\tR\022\020\003\032\0020\0048\002@\002X\006\002\n\000\002\004\n\002\b\031\006\n"}, d2 = {"Lcom/example/MyAspect;", "", "()V", "auditService", "Lcom/example/MyAspectInterceptor;", "wrapMethod", "", "point", "Lorg/aspectj/lang/JoinPoint;", "(Lorg/aspectj/lang/JoinPoint;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;", "service"})
public class MyAspectInterceptor {
static {
try {
ajc$postClinit();
} catch (Throwable throwable) {
ajc$initFailureCause = throwable = null;
}
}
public static boolean hasAspect() {
return (ajc$perSingletonInstance != null);
}
public static AuditAspect aspectOf() {
if (ajc$perSingletonInstance == null)
throw new NoAspectBoundException("com.example.MyAspect", ajc$initFailureCause);
return ajc$perSingletonInstance;
}
@After("@annotation(com.example.MyAspect)")
@Nullable
public final Object wrapMethod(@NotNull JoinPoint point, @NotNull Continuation $completion) {
Intrinsics.checkNotNull(point.getSignature(), "null cannot be cast to non-null type org.aspectj.lang.reflect.MethodSignature");
// business logic
return Unit.INSTANCE;
}
}
And here my question: Is it possible to make an aspect of AspectJ in Kotlin that will run in coroutine?
I've found a work around, we can use GlobalScope. Steps to make it work:
org.jetbrains.kotlinx:kotlinx-coroutines-core
@DelicateCoroutinesApi
GlobalScope#launch
inside an aspect method@DelicateCoroutinesApi
@After("@annotation(...)")
fun wrapMethod(point: JoinPoint): Unit {
GlobalScope.launch {
// our logic in coroutine
}
}