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



我有两个类

class Fragment1{
   createView(SomeObject p1, AnoterObject p2)
}
@AutoLayout(String annotationParam)
class Fragment2 extends Fragment1{
}

如何在Fragment2上做@Around createView。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);
    }

给定此注释:

package de.scrum_master.app;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {}

让我们假设有三个类:

  • 没有注释的父类,
  • 一个没有注释的普通子类和
  • 带注释的子类:
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 ""; }
}

下面是一个小的驱动程序应用程序,实例化了所有三个类,调用了它们所有可用的方法,无论是否继承,使用不同的签名和返回类型:

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或其任何子类(因此+)中的所有方法执行,但仅当当前实例this的类具有@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()被调用了三次,但只被截获了一次。您还可以从打印的getThis()对象中看到,真正正确的执行被拦截了。

以下是示例

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

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

见下面,上面的代码片段的灵感来自于这些资源

访问通知中的注解值

Spring AOP:获取切入点注释的参数

最新更新