子类中带有注释的Aspectj切入点方法

Aspectj pointcut method with annotation in subclass

我有2个类

class Fragment1{
   createView(SomeObject p1, AnoterObject p2)
}

@AutoLayout(String annotationParam)
class Fragment2 extends Fragment1{
}

如何在 Fragment2.createView 调用上执行 @Around createView 并获取 annotationParam?谢谢

添加: 如果我将方法存根添加到 Fragment2 中,则可以开始使用下一个注释 @Around("createMethod(inflater, group, savedState) && @within(autoInflate)"),但这是一个非常丑陋的解决方案

解决方案: 感谢@kriegaex 我找到了解决方案:

@Around("execution(* com.github.a_kokulyuk.kotakt.ui.BaseFragment+.*(*, *, *)) && args(inflater, parent, savedState) && @this(an)")
    public Object doLayout(ProceedingJoinPoint jo, LayoutInflater inflater, ViewGroup parent, Bundle savedState, AutoLayout an) throws Throwable {
        return inflater.inflate(an.value(), parent, false);
    }

这是例子

public @interface customAnnotation {
    String value() default "someValue";
}


@Aspect
public class customAspect {

    @Around(value="@annotation(customAnnotation)")
    public Object customAdvice(ProceedingJoinPoint joinPoint, CustomAnnotation customAnnotation ) throws Throwable {
    // ...
     }
}

请参阅下文,上面的代码段灵感来自这些资源

Accessing Annotation-value in advice

Spring AOP: Getting parameters of the pointcut annotation

鉴于此注释:

package de.scrum_master.app;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {}

让我们假设我们有三个 classes:

  • a parent class 无注释,
  • 没有注释的普通childclass和
  • 一个注释 child class:
package de.scrum_master.app;

public class Parent {
    public void doSomething() {}
}
package de.scrum_master.app;

public class PlainChild extends Parent {
    int doSomethingElse() { return 11; }
}
package de.scrum_master.app;

@MyAnnotation
public class AnnotatedChild extends Parent {
    String doSomethingSpecial(int number) { return ""; }
}

这是一个小驱动程序应用程序,它实例化了所有三个 classes,调用它们的所有可用方法,继承与否,具有不同的签名和 return 类型:

package de.scrum_master.app;

public class Application {
    public static void main(String[] args) {
        new Parent().doSomething();
        new PlainChild().doSomething();
        new PlainChild().doSomethingElse();
        new AnnotatedChild().doSomething();
        new AnnotatedChild().doSomethingSpecial(123);
    }
}

最后,这是做问题中所问的方面:它拦截 Parent 或其任何子 class 中的所有方法执行(因此 +) , 但前提是当前实例 this 的 class 包含 @MyAnnotation:

package de.scrum_master.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class MyAspect {
    @Around(
        "execution(* de.scrum_master.app.Parent+.*(..)) && " +
        "@this(de.scrum_master.app.MyAnnotation)"
    )
    public Object myAdvice(ProceedingJoinPoint thisJoinPoint) {
        System.out.println(thisJoinPoint);
        System.out.println("  " + thisJoinPoint.getThis());
        return thisJoinPoint.proceed();
    }
}

控制台日志:

execution(void de.scrum_master.app.Parent.doSomething())
  de.scrum_master.app.AnnotatedChild@681a9515
execution(String de.scrum_master.app.AnnotatedChild.doSomethingSpecial(int))
  de.scrum_master.app.AnnotatedChild@13221655

可以看到,doSomething()被调用了3次,只被拦截了一次。从打印出来的getThis()object也可以看出,确实是正确的执行被拦截了