Anatolii Kokuliuk
Anatolii Kokuliuk

Reputation: 183

Aspectj pointcut method with annotation in subclass

I have 2 classes

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

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

How i can do @Around createView on Fragment2.createView call and get annotationParam? Thanks

ADD: If i add method stub into Fragment2, it is start be possible to use next annotation @Around("createMethod(inflater, group, savedState) && @within(autoInflate)"), but it is a very ugly solution

SOLUTION: Thanks to @kriegaex i found solution:

@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);
    }

Upvotes: 5

Views: 4847

Answers (2)

kriegaex
kriegaex

Reputation: 67317

Given this annotation:

package de.scrum_master.app;

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

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

Let us assume we have three classes:

  • a parent class without annotation,
  • a plain child class without annotation and
  • an annotated 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 ""; }
}

Here is a little driver application instantiating all three classes, calling all available methods on them, inherited or not, with different signatures and return types:

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);
    }
}

Finally, here is the aspect doing what was asked in the question: It intercepts all method executions in Parent or any of its subclasses (thus the +), but only if the class of the current instance this bears @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();
    }
}

The console log:

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

As you can see, doSomething() is called three times, but only intercepted once. You can also see from the printed getThis() object, that really the right execution is intercepted.

Upvotes: 4

M Sach
M Sach

Reputation: 34424

Here is the example

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


@Aspect
public class customAspect {

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

See below as above snippet is inspired by these resources

Accessing Annotation-value in advice

Spring AOP: Getting parameters of the pointcut annotation

Upvotes: 1

Related Questions