Hot questions for Using AspectJ in pointcuts

Question:

I have the following aspect:

public aspect MyAspect {

 before(String val): args(val, ..) &&
   call(public * execute(java.lang.String, ..)) {
     // Do something
    }
}

And the following classes A & B, A uses B:

class A() {
 public void execute(String a) {
    // Do something...
    B b = new B();
    b.execute();
 }
}

class B {
  public void execute(String a) {
     // Do something
  }
}

And I have a test class:

public class TestClass {
  public static void main(String[] args) {
     A a = new A();
     a.execute("someVal"); // I want the aspect to be called for the first execute only
     B b = new B();
     b.execute("someVal");    
  }
}
  • In case we call a.execute() I do not want the execute aspect to be caught again on B.
  • On the other hand, when we call b.execute() directly from the test I do want the aspect to catch b.execute().

How can this be achieved? I tried using cflowbelow (with negation), but it didn't work.

---- edit ----

To be more precise, let's take java's FilterChain.doFilter(..) - filters can call other filters. I only want to catch the first call to doFilter (I know this can be done using ThreadLocal in case of fiter, but the filter is only an example).

Thanks,

Lin


Answer:

This worked for me:

pointcut intercept_call() : call(public * execute(java.lang.String, ..));


 before(String val): intercept_call() && !cflowbelow(intercept_call()) && args(val, ..)
{

    // do soemthing
   }
}

Don't know if it does what you are looking for.

Question:

I'm working on a small project that determines code coverage when testing a java application. It basically consists of a plugin for an IDE which finds all the classes and methods in the project and saves them in a database, and an agent with aspectJ pointcuts that weave around all of these methods to log their execution.

The problem I have is that I only want to log the methods that are actually written by the developers of that very project and not those of underlying libraries. So the pointcuts need to be defined in a way that only methods of classes in the actual project packages are woven. On the other hand, since the agent is to be used with all sorts of projects, I can't hardcode those packages.

My attempt so far was to read all the package names from the database and build a string from that. Basically what it looks like is this:

private static final String POINTCUT_STRING = AspectUtil.buildPointcutString();

And then, when defining the pointcut:

@Pointcut(POINTCUT_STRING)

Thing is, this doesn't work because apparently when defining a Pointcut, the

Attribute value needs to be a constant.

So, how can I make it so that i can only weave methods in classes in the packages that I have in my database?

Thanks in advance, have a good one!


Answer:

I don't think a dynamic aspect approach is going to work as aspectj does not expose the weaver to any state management or changes. Although this would be theoretically possible at runtime it's definitely not possible at compile time (and you have the option to add your aspects at compile time).

But to your issue...

What weave strategy are you using? compile or runtime? I've found compile to work very well and I'm not sure how to use runtime with aspectj. But what I can say is that if you use compile you'll only be weaving the application classes in any case as that is all you'll have access to.

Another comment to make is if you want to do something dynamic you'd be better off putting the condition on whether to monitor that method for code coverage downstream of the aspect. So when the aspect is executed the first thing it will do is decide if this class/method call should be monitored for coverage and then go on from there...

Question:

/* 0 */ pointcut services(Server s): target(s) && call(public * *(..))

This pointcut, named services, picks out those points in the execution of the program when Server objects have their public methods called. It also allows anyone using the services pointcut to access the Server object whose method is being called. (taken from https://eclipse.org/aspectj/doc/released/progguide/language-anatomy.html)

I'm trying to understand AspectJ's pointcuts, and am quite a bit confused at the moment. My main question is: how do you read the above pointcut, and how do you "puzzle" its meaning together?

To illustrate my confusion, let's try to build things up from scratch:

The following pointcut would intercept all public method calls to any object, right?

/* 1 */ pointcut services() : call(public * *(..))

Now, what about this:

/* 2 */ pointcut services() : call(public * Server.*(..)) 

I assume that would intercept any points when public methods of the Server object are called.

Now, how do I get from here to the initial example 0? And how do I read it?

Would you first provide the parameter list when building the pointcut up?

/* 3a */ pointcut services(Server s) : call(public * *(..))

Is that the same as number 2 above? (I have a feeling it wouldn't work, and if it did, it would "intercept" every public method call, just like number 1.) Anyway, would the following be the same? (I'm not "capturing" s with a native pointcut yet, so I can't really define it, can I?)

/* 4a */ pointcut services(Server /* only type, no variable */) : call(public * *(..))

Or would you start by specifying a native pointcut, to "capture" the target object, like so:

/* 3b */ pointcut services() : target(s) && call(public * *(..))

I suppose that would still intercept all public method calls on any object?

Would the following work to only intercept calls on the Server object, and to "capture" that object (without making it available to be passed on later, e.g. to an advice)?

/* 5 */ pointcut services(/*nothing here*/) : target(s) && call(public * Server.*(..))

Now, going back to the original pointcut:

/* 0 */ pointcut services(Server s): target(s) && call(public * *(..))

Is that the same as

/* 6 */ pointcut services(Server s): target(s) && call(public * Server.*(..))

So, to summarize: How do you start deciphering 0?

Do you first look at the target pointcut, then at the paramter type of the services pointcut and read it "inside out"/"from right to left"? Or do you look at the parameter list first, and then look into the services pointcut to see where the argument came from (i.e. target(s))?

Or am I making this far too complicated? Am I missing an important bit somewhere to help me understand this?

Edit: the manual explains it left to right - but where does the argument to parameter Server s come from if I haven't "executed" target(s) yet?


Answer:

1: Yes, it intercepts any public method call.

2: It intercepts any public method call on an object declared as a Server, whereas 0 intercepts any public call on an object which is an instance of a Server. See the semantics.

3a: As s is not bound, it doesn't compile:

[ERROR] formal unbound in pointcut
        .../src/main/aspect/MyAspect.aj:18
pointcut services(Server s): call(public * *(..));

4a: The syntax is not valid, just like you need to name parameters when declaring methods in an interface:

[ERROR] Syntax error, insert "... VariableDeclaratorId" to complete FormalParameterList
        .../src/main/aspect/MyAspect.aj:18
pointcut services(Server): call(public * *(..));
                  ^

3b: It's not valid either, s hasn't been declared:

[WARNING] no match for this type name: s [Xlint:invalidAbsoluteTypeName]
        .../src/main/aspect/MyAspect.aj:18
pointcut services(): target(s) && call(public * *(..));

5: Like 3b, s hasn't been declared.

6: It's not the same as 0, it only matches public Server method calls (i.e. declared in Server) to a Server instance.

I have illustrated the different cases in a Github repository: switch between the branches to try them. There's an extra case in the aspect7 branch, based on 6, where I override hashCode() in Server.

You can (and should) try yourself, to get a better understanding.


To answer your final question, the argument to the pointcut comes from the fact that we want to (be able to) access the target of the call in the advice, by having it supplied as a parameter to the advice. The signature of the advice needs to contain parameters for all the referenced pointcuts, and the pointcut parameters need to reference parameters in the advice.

So, to have a Server parameter in the advice, I need it in the pointcut, and it needs to be bound to something in the pointcut definition.

Question:

In AOP in Java (AspectJ) when we talk about method pointcuts, we can differentiate them into two different sets: method call pointcuts and method execution pointcuts.

Basing on these resources here on SO:

  • execution Vs. call Join point
  • Difference between call and execution in AOP

And some AspectJ background, we can tell that basically the differences between the two can be expressed as the following:

Given these classes:

class CallerObject {
      //...
      public void someMethod() {
         CompiletimeTypeObject target = new RuntimeTypeObject();
         target.someMethodOfTarget();
      }
      //...
}

class RuntimeTypeObject extends CompileTypeObject {
    @Override
    public void someMethodOfTarget() {
       super.someMethodOfTarget();
       //...some other stuff
    }
}

class CompiletimeTypeObject {
    public void someMethodOfTarget() {
       //...some stuff
    }
}
  • A method call pointcut refers to the call of a method from a caller object which calls the method of a target object (the one which actually implements the method being called). In the example above, the caller is CallerObject, the target is RuntimeTypeObject. Also, a method call pointcut refers to the compile time type of the object, i.e. "CompiletimeTypeObject" in the example above;

So a method call pointcut like this:

pointcut methodCallPointcut(): 
   call(void com.example.CompiletimeTypeObject.someMethodOfTarget())

Will match the target.someMethodOfTarget(); join point inside the CallerObject.someMethod() method as the compile type of the RuntimeTypeObject is CompiletimeTypeObject, but this method call pointcut:

pointcut methodCallPointcut(): 
   call(void com.example.RuntimeTypeObject.someMethodOfTarget())

Will not match, as the compile time type of the object (CompiletimeTypeObject) is not a RuntimeTypeObject or a subtype of it (it is the opposite).

  • A method execution pointcut refers to the execution of a method (i.e. after the method has been called or right before the method call returns). It doesn't give information about the caller and more important it refers to the runtime type of the object and not to the compile time type.

So, both these method execution pointcuts will match the target.someMethodOfTarget(); execution join point:

pointcut methodCallPointcut(): 
       execution(void com.example.CompiletimeTypeObject.someMethodOfTarget())

pointcut methodCallPointcut(): 
       execution(void com.example.RuntimeTypeObject.someMethodOfTarget())

As the matching is based on the runtime type of the object which is RuntimeTypeObject for both and RuntimeTypeObject is both CompiletimeTypeObject (first pointcut) and a RuntimeTypeObject (second pointcut).

Now, as PHP doesn't provide compile time types for objects (unless type-hinting is used to somehow emulate this behaviour), does it make sense to differentiate method call and method execution pointcuts in a PHP AOP implementation? How then will the pointcuts differ from each other?

Thanks for the attention!

EDIT: @kriegaex has pointed out another interesting aspect between call and method execution pointcuts in AspectJ.

Thank you for the great and concise example. I have tried to make an example myself too and here is what I understood:

In case A (I use a 3rd party library), I actually can't intercept the execution of a library method because the library itself was already compiled into bytecode and any aspect concerning that library was already woven into that bytecode too (I would need to weave the sources in order to do so).

So I can only intercept the method calls to the library methods, but again I can only intercept the calls to library methods in my code and not the calls to library methods from within the library itself because of the same principle (the calls to library methods from within the library itself are also already compiled).

The same applies for System classes (same principle) as is said here (even if the reference refers to JBoss):

https://docs.jboss.org/jbossaop/docs/2.0.0.GA/docs/aspect-framework/reference/en/html/pointcuts.html

System classes cannot be used within execution expressions because it is impossible to instrument them.

In case B (I provide a library for other users), if I actually need to intercept the usage of a method of my library either in the library itself or in the future user code which will use that method, then I need to use an execution pointcut as the aspect weaver will compile both the method execution and call pointcuts that concern my library and not the user code which will use my library methods (simply because the user code doesn't exist yet when I am writing the library), therefore using an execution pointcut will ensure that the weaving will occur inside the method execution (for a clear and intuitive example, look at the @kriegaex pseudo-code below) and not wherever the method is called within my library (i.e. at the caller side).

So I can intercept the usage (more precisely, execution) of my library method both when the method is used within my library and in the user's code. If I had used a method call pointcut in this case, I would have intercepted only the calls made from within my library, and not the calls made in the user's code.

Anyway, still think if these considerations make sense and can be applied in the PHP world, what do you think guys?


Answer:

Disclaimer: I do not speak PHP, not even a little. So my answer is rather general in nature than specific to PHP.

AFAIK, PHP is an interpreted rather than a compiled language. So the difference is not compile time vs. runtime type, but semantically rather declared vs. actual type. I imagine that a PHP-based AOP framework would not "compile" anything but rather preprocess source code, injecting extra (aspect) source code into the original files. Probably it would still be possible to differentiate declared from actual types somehow.

But there is another important factor which is also relevant to the difference between call vs execution joinpoints: The place in which the code is woven. Imagine situations in which you use libraries or provide them by yourself. The question for each given situation is which parts of the source code is under the user's control when applying aspect weaving.

  • Case A: You use a 3rd party library: Let us assume you cannot (or do not want to) weave aspects into the library. Then you cannot use execution for intercepting library methods, but still use call pointcuts because the calling code is under your control.
  • Case B: You provide a library to other users: Let us assume your library should use aspects, but the library's user does not know anything about it. Then execution pointcuts will always work because the advices are already woven into your library's methods, no matter if they are called from outside or from the library itself. But call would only work for internal calls because no aspect code was woven into the user's calling code.

Only if you control the calling as well as the called (executed) code it does not make so much difference whether you use call or execution. But wait a minute, it still makes a difference: execution is just woven in one place while call it woven into potentially many places, so the amount of code generated is smaller for execution.


Update:

Here is some pseudo code, as requested:

Let us assume we have a class MyClass which is to be aspect-enhanced (via source code insertion):

class MyClass {
    method foo() {
        print("foo");
        bar();
    }

    method bar() {
        print("bar");
        zot();
    }

    method zot() {
        print("zot");
    }

    static method main() {
        new McClass().foo();
    }
}

Now if we apply a CallAspect like this using call()

aspect CallAspect {
    before() : call(* *(..)) {
        print("before " + thisJoinPoint);
    }
}

upon our code, it would look like this after source code weaving:

class MyClass {
    method foo() {
        print("foo");
        print("before call(MyClass.bar())");
        bar();
    }

    method bar() {
        print("bar");
        print("before call(MyClass.zot())");
        zot();
    }

    method zot() {
        print("zot");
    }

    static method main() {
        print("before call(MyClass.foo())");
        new McClass().foo();
    }
}

Alternatively, if we apply an ExecutionAspect like this using execution()

aspect ExecutionAspect {
    before() : execution(* *(..)) {
        print("before " + thisJoinPoint);
    }
}

upon our code, it would look like this after source code weaving:

class MyClass {
    method foo() {
        print("before execution(MyClass.foo())");
        print("foo");
        bar();
    }

    method bar() {
        print("before execution(MyClass.bar())");
        print("bar");
        zot();
    }

    method zot() {
        print("before execution(MyClass.zot())");
        print("zot");
    }

    static method main() {
        print("before execution(MyClass.main())");
        new McClass().foo();
    }
}

Can you see the difference now? Pay attention to where the code is woven into and what the print statements say.

Question:

I need to write an aspect (let's call it A) that shows all the executed pointcuts at runtime. Is there a way to write a pointcut like call(...) that points directly to another pointcut without using the aspects' names ?

I've written something that uses mostly calls to generic functions and within() so that when a function in a aspect is called my aspect A prints something. I feel that it's not an ideal solution because I'd always need to write all the aspects names and would be to long with many aspects.

public class Main {
    public static void main(String[] args) {
        ClassA a = new ClassA();
        a.methodA();
        a.methodA();
        a.methodB();
        a.methodA();
    }
}

public class ClassA {
    public void methodA() {
            System.out.println("MethodA");
    }
    public void methodB() {
        System.out.println("MethodB");
    }
    public void methodC() {
        System.out.println("MethodC");
    }
}

public aspect MethodAAspect {
    pointcut MethA():
        call(public * ClassA.methodA());
    pointcut MethC():
        call(public * ClassA.methodC());
    after():
        MethA() {
            System.out.println("Aspect here, methodA ended.");
        }
    after():
        MethC() {
            System.out.println("Aspect here, methodC ended.");
        }       
}

If, in this example, I'd need an aspect that counts how many times all pointcuts have been executed or prints something when a pointcut is executed how should I write it?


Answer:

I am not sure I understand correctly what you want to achieve because your description is somewhat imprecise. For example, a pointcut is not "executed", an application method or an advice inside an aspect are. So I am not sure if you want to just log each method call (or maybe method execution, see below for the difference) or maybe need some kind of meta aspect which counts how many times aspect advices are being executed. I am assuming the former, simpler case here because it makes most sense to me.

Your application code, but with package names:

package de.scrum_master.app;

public class ClassA {
  public void methodA() {
    System.out.println("MethodA");
  }

  public void methodB() {
    System.out.println("MethodB");
  }

  public void methodC() {
    System.out.println("MethodC");
  }
}
package de.scrum_master.app;

public class Main {
  public static void main(String[] args) {
    ClassA a = new ClassA();
    a.methodA();
    a.methodA();
    a.methodB();
    a.methodA();
  }
}

Aspect intercepting method execution:

This aspect intercepts all method executions (not calls!) in your own code.

package de.scrum_master.aspect;

public aspect MyAspect {
  after() : execution(* *(..)) {
    System.out.println(thisJoinPoint);
  }
}

The log output is:

MethodA
execution(void de.scrum_master.app.ClassA.methodA())
MethodA
execution(void de.scrum_master.app.ClassA.methodA())
MethodB
execution(void de.scrum_master.app.ClassA.methodB())
MethodA
execution(void de.scrum_master.app.ClassA.methodA())
execution(void de.scrum_master.app.Main.main(String[]))

Please note that also the execution of Main.main(..) is being logged even though the method is never called explicitly (but executed nevertheless!).

Aspect intercepting method execution:

This aspect intercepts all method calls from your own code, which also includes calls to third-party or JDK classes.

Please note that in order to avoid an endless loop we have to add && !within(MyAspect) because the aspect advice also calls a JDK method.

package de.scrum_master.aspect;

public aspect MyAspect {
  after() : call(* *(..)) && !within(MyAspect) {
    System.out.println(thisJoinPoint);
  }
}

The log output in this case is:

MethodA
call(void java.io.PrintStream.println(String))
call(void de.scrum_master.app.ClassA.methodA())
MethodA
call(void java.io.PrintStream.println(String))
call(void de.scrum_master.app.ClassA.methodA())
MethodB
call(void java.io.PrintStream.println(String))
call(void de.scrum_master.app.ClassA.methodB())
MethodA
call(void java.io.PrintStream.println(String))
call(void de.scrum_master.app.ClassA.methodA())

Of course you could also use call() and limit calls to your own packages, for example:

package de.scrum_master.aspect;

public aspect MyAspect {
  after() : call(* de.scrum_master.app..*(..)) && !within(MyAspect) {
    System.out.println(thisJoinPoint);
  }
}

The log output here is:

MethodA
call(void de.scrum_master.app.ClassA.methodA())
MethodA
call(void de.scrum_master.app.ClassA.methodA())
MethodB
call(void de.scrum_master.app.ClassA.methodB())
MethodA
call(void de.scrum_master.app.ClassA.methodA())

It always depends on what you want to achieve.

If this is not what you wanted, please update your question to be more precise and notify me with a comment. Then I see what I can do.


Update concerning follow-up question about meta aspect:

package de.scrum_master.aspect;

public aspect MetaAspect {
  before() : adviceexecution() && !within(MetaAspect) {
    System.out.println(thisJoinPoint);
  }
}

Log for first MyAspect version using execution() changes to:

MethodA
adviceexecution(void de.scrum_master.aspect.MyAspect.after(JoinPoint))
execution(void de.scrum_master.app.ClassA.methodA())
MethodA
adviceexecution(void de.scrum_master.aspect.MyAspect.after(JoinPoint))
execution(void de.scrum_master.app.ClassA.methodA())
MethodB
adviceexecution(void de.scrum_master.aspect.MyAspect.after(JoinPoint))
execution(void de.scrum_master.app.ClassA.methodB())
MethodA
adviceexecution(void de.scrum_master.aspect.MyAspect.after(JoinPoint))
execution(void de.scrum_master.app.ClassA.methodA())
adviceexecution(void de.scrum_master.aspect.MyAspect.after(JoinPoint))
execution(void de.scrum_master.app.Main.main(String[]))

Question:

In package com.repository I have :

  1. Standalone interfaces extending spring data Repository
  2. Interfaces extending spring data Repository with my own implementation in the same package
  3. Repository classes implementing my repository interfaces

I would like to measure execution time of all methods from com.repository package (communication with database). But I would like to avoid duplications

now with

@Pointcut("execution(public * com.repository..(..))")

I have some methods logged twice - from interface and from class implementing this interface. I would like either not to log methods from interfaces which have implementing class in the same package, or not to log methods from classes which implement interface from the same package.

How can I express it with pointcut and advice?

My question is a bit related to AspectJ : Issue when combining multiple pointcuts in @Around advice, but it doesn't solve my problem.


Answer:

If the objects you're monitoring are located to a specific package, why you don't bound the pointcut only to that package.

So use

@Pointcut("execution(* com.repository.*.*(..))")

instead of

@Pointcut("execution(public * com.repository..*.*(..))")

which include "com.repository" package and all its sub packages.

Question:

I need help to write some Aspectj advice on this particular case:

Suppose we have this class:

package org.group;

public class Person {

   public void method1(String id, String number) {
       //some code
       List<String> list = getList(number);
       //some code
   }

   public List<String> getList(String number) {
       return Arrays.asList(number);
   }

}

I want to create an Aspectj advice into method1 to get the result of getList. I try this:

@Pointcut("execution(* org.group.Person.getList(..))")
public void methodGetList() {

}

@AfterReturning(pointcut = "methodGetList()", returning = "result")
public void afterMethodGetList(JoinPoint joinPoint, List<String> result) {
    System.out.println("I can see the list result: " + result.toString());
}

This advice works on all executions of getList method, but what I want exactly, is to get the result inside the method1 call to get an information with the method1's id , for example like this:


'I can see the list result [4] for the person with id : XXX'

Thank you for your help.


Answer:

You need to limit your pointcut to the executions within the control flow - cflow() - of the calling method and also bind the calling method's parameter of interest via args().

Application:

package org.group;

import java.util.Arrays;
import java.util.List;

public class Person {
  public void method1(String id, String number) {
    // some code
    List<String> list = getList(number);
    // some code
  }

  public List<String> getList(String number) {
    return Arrays.asList(number);
  }

  public static void main(String[] args) {
    // Should not be intercepted
    new Person().getList("22");
    // Should be intercepted
    new Person().method1("John Doe", "11");
  }
}

Aspect:

package de.scrum_master.aspect;

import java.util.List;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class MyAspect {
  @Pointcut("execution(* org.group.Person.getList(..))")
  public void methodGetList() {}

  @Pointcut("execution(* org.group.Person.method1(..)) && args(id, *)")
  public void methodMethod1(String id) {}

  @AfterReturning(
    pointcut = "methodGetList() && cflow(methodMethod1(id))",
    returning = "result"
  )
  public void afterMethodGetList(JoinPoint joinPoint, String id, List<String> result) {
    System.out.println(
      "I can see the list result " + result +
      " for the person with id " + id
    );
  }
}

Console log:

I can see the list result [11] for the person with id John Doe

Question:

I am attempting to create an android library that checks if internet is available before executing a method that has a custom annotation I have defined. I'm using AspectJ to accomplish this.

My annotation is as follows :

@Target({METHOD}) @Retention(RUNTIME)
public @interface InternetRequired  {

}

Now for my aspect:

@Aspect
public class CilantroAspect
{

    private static final String POINTCUT_METHOD = "execution(@com.cilantro.service.InternetRequired * *(..))";
    private static final String POINTCUT_METHOD2 ="@annotation(com.cilantro.service.InternetRequired)";
    ;

    @Pointcut(POINTCUT_METHOD2)
    public void internetAnnotatedMethod() {
    }

    @Around("internetAnnotatedMethod()")
    public void checkInternetConnectivity(ProceedingJoinPoint joinPoint) throws Throwable {
        Log.v("Aspect","advice being triggered");
        if (Cilantro.isConnected()) {
            joinPoint.proceed();
        } else {
            Cilantro.Toast("Internet not available");
        }
    }
}

Snippet of my activity with the annotated method.

    ....
    Cilantro.init(this);
    test();
}

@InternetRequired
public void test()
{
    Toast.makeText(this,"Test method",Toast.LENGTH_LONG).show();
}

When I run my android app the around advice is not being triggered. I tried using POINTCUT_METHOD and POINTCUT_METHOD2. Still no luck.

My android app is configured to use Aspect J so I know that's not the problem because if I make errors within the pointcut definitions it's detected..but just to be sure let me share.

Main build script

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.2.3'
        classpath 'com.uphyca.gradle:gradle-android-aspectj-plugin:0.9.+'
}
....

module containing Aspects

apply plugin: 'com.android.library'
apply plugin: 'android-aspectj' 
....

Answer:

The around advice wasn't being triggered because I was using annotations related to the Aspect from the app level while the aspect was contained in the library. For the aspects to be weaved into the app module at compile time I had to simply publish the library to maven (local for testing and maven central for distribution) and then include the library as a project dependency in a gradle plugin which contains the AspectJ weaving tasks.The plugin is then applied to the app's module.

Here's a snippet of my plugin that's written in groovy. I add my library that contains my Aspects and then run the weaving tasks on the app's module.

project.dependencies {
    compile 'com.github.jd-alexander:flender-runtime:1.0'
    // TODO this should come transitively
    compile 'org.aspectj:aspectjrt:1.8.5'
}

variants.all { variant ->

    variant.dex.doFirst {
        String[] args = [
                "-showWeaveInfo",
                "-1.5",
                "-inpath", javaCompile.destinationDir.toString(),
                "-aspectpath", javaCompile.classpath.asPath,
                "-d", javaCompile.destinationDir.toString(),
                "-classpath", javaCompile.classpath.asPath,
                "-bootclasspath", project.android.bootClasspath.join(File.pathSeparator)
        ]
        log.debug "ajc args: " + Arrays.toString(args)

        MessageHandler handler = new MessageHandler(true);
        new Main().run(args, handler);

For a complete example of how this is done you can check my library out on github https://github.com/jd-alexander/flender

Question:

I would like to create a class that pointcuts to methods within the list interface. This seems to work until I add the target(list) to my advice. I would like to view the elements of a list before and after adding to (for example) see what has changed but I cannot seem to pass my list in as I would an object. Here is what I have so far, this does not run with the target(list) but does run without it :

pointcut addPointCut() : call(boolean List.add(..));

before(List<Integer> list) : addPointCut() && target(list) {
    System.out.println("testing");
    for(Object i : list) {
        System.out.println(i);
    }
}

Answer:

NĂ¡ndor's answer is correct insofar as he describes the compiler error you see. I want to go a little further and also explain why you get this error:

First of all, the problem is not directly related to AspectJ but rather to how Java implements generics. Please make yourself familiar with a phenomenon called type erasure before you continue to read.

Well, because type erasure is a JVM reality and because target() and this() are resolved during runtime rather than compile time - you can indirectly conclude this from the fact that both getTarget() and getThis() are methods of JoinPoint rather than JoinPoint.StaticPart - what you want to do cannot work and consequently leads to an AspectJ compiler error. The only thing you can do is use instanceof in order to dynamically determine what gets added to the target list. The most elegant way to do this is an if() pointcut expression.

Here is some sample code:

Driver application:

So as to make things a little more interesting we use two types of lists and also two types of add(..) calls. The goal should be to only intercept integers to be added to the corresponding list, no matter which signature the add(..) method has.

package de.scrum_master.app;

import java.util.ArrayList;
import java.util.List;

public class Application {
    public static void main(String[] args) {
        List<Integer> integers = new ArrayList<>();
        integers.add(11);
        integers.add(0, 22);
        integers.add(33);

        List<String> strings = new ArrayList<>();
        strings.add("foo");
        strings.add(0, "bar");
        strings.add("zot");
    }
}

Aspect:

package de.scrum_master.aspect;

import java.util.List;

@SuppressWarnings({"rawtypes", "unchecked"})
public aspect GenericsAspect {
    pointcut addPointCut(List list, Object newElement) :
        !within(GenericsAspect) &&            // avoid stack overflow due to recursion
        call(* List.add(..)) &&               // intercept all calls to List.add
        args(.., newElement) &&               // capture last method parameter
        if(newElement instanceof Integer) &&  // only capture added int/Integer elements
        target(list);                         // target is a List

    before(List list, Object newElement) :
        addPointCut(list, newElement)
    {
        System.out.println(thisJoinPoint + " -> new element = " + newElement);
        for(Object i : list)
            System.out.println("  " + i);

        // Type erasure in action:
        // During runtime there is no such thing as List<Integer>, only a raw List.
        // Thus, we can easily add a String to a list declared as List<Integer>.
        list.add("#" + newElement + "#");
    }
}

Console log:

call(boolean java.util.List.add(Object)) -> new element = 11
call(void java.util.List.add(int, Object)) -> new element = 22
  #11#
  11
call(boolean java.util.List.add(Object)) -> new element = 33
  22
  #11#
  11
  #22#

Any further questions?