0

Assume that we have two aspects:

public aspect TestAspect {
    pointcut publicMethodExecuted(): execution(public !static * *(..));

    int around() : publicMethodExecuted() {
        System.out.println("Test string");
        Object[] args = thisJoinPoint.getArgs();
        System.out.println(args[0]);
        int original_return_value = proceed();
        return original_return_value * 100;
    }
}

public aspect AnotherTestAspect {
    pointcut anotherPublicMethodExecuted(): execution(public !static * *(..));

    int around() : anotherPublicMethodExecuted() {
        System.out.println("Another Test string");
        Object[] args = thisJoinPoint.getArgs();
        System.out.println(args[0]);
    }
}

As you can see these two aspects have completely the same poincut. Therefore they're intercepting the same method invocation. Is it safe to do so?

Please, don't suggest I put all this in the same aspect. I'm asking about AspectJ working principles and potential possiblities.

Ori Lentz
  • 3,668
  • 6
  • 22
  • 28
St.Antario
  • 26,175
  • 41
  • 130
  • 318
  • I'm going out on a limb here as I don't know the internals of AspectJ, but I reckon if you couldn't attach two aspects to the same invocation (whatever the pointcut), AspectJ would be next to useless. The fact that it isn't suggests that it is possible and safe to do so. (Though it probably isn't a good idea for one aspect to rely on the other already having run.) – biziclop May 28 '15 at 13:28
  • In PostSharp (C#) it is possible to define how aspects shall be weaved, e.g. which one is inserted first. See http://www.postsharp.net/blog/post/introducing-postsharp-2-0-3-aspect-dependencies – Thomas Weller May 28 '15 at 13:38
  • @Thomas Looks like AspectJ doesn't provide such a capability... – St.Antario May 28 '15 at 13:39
  • Seems similar for AspectJ: https://doanduyhai.wordpress.com/2012/01/01/advanced-aspectj-part-iv-declaring-aspects-precedence/ – Thomas Weller May 28 '15 at 13:40
  • @St.Antario This is possible in AspectJ. It is called precedence: https://doanduyhai.wordpress.com/2012/01/01/advanced-aspectj-part-iv-declaring-aspects-precedence/ – Wim Deblauwe May 28 '15 at 13:41

2 Answers2

1

The simple answer is "yes, but..."

Keeping it simple, what AspectJ does is basically going pointcut-to-pointcut and searching how to weave it, and then, well, weaves it. In the case of two pointcuts to the same method, one of the pointcuts will weave and then the other one will weave and will basically override that first weaving. Unless the second pointcut proceeds!

Let me explain this with a short example. Suppose you have the following class:

public class TestClass {

     public static void main(String... args) {
        new TestClass().x();
     }

     public void x() {
         System.out.println("Hello, world!");
     }
}

Now let's define an aspect:

public aspect FirstAspect {

     public pointcut hello1() : execution(void mypackage.TestClass.x());
     void around() : hello1() {
         System.out.println("first");
     }

}

What will happen is that the aspect will weave the method x, basically replace the call to x with a method that AspectJ created.

Now let's suppose we have another aspect:

public aspect SecondAspect {

     public pointcut hello2() : execution(void mypackage.TestClass.x());
     void around() : hello2() {
         System.out.println("second");
     }

}

With loss of generality and to be consistent, let us assume that FirstAspect is weaved first. At that point, we have the same result as we had before. But now AspectJ continues and weaved SecondAspect. It finds method x() and replaces its' execution (or call, depending on the pointcut type) with a new method, effectively overriding that previous weaving and leaving it obsolete (ironically enough, the first weaved code is remained but is useless).

However, if SecondAspect's advice calls proceed() at any point, then the part it will proceed to will actually be the first weaving. That's because because it weaved, that's what x was doing as far as AspectJ is concerned.

Try this out. You'll see only one of the pointcuts is actually left weaved: you'll only get one print: either first or second but not both, unless you proceed, as such:

 System.out.println("second");
 proceed();

It doesn't even matter when you proceed(), as long as you do:

 proceed();
 System.out.println("second");

If you want to ensure which pointcut is weaved first, you can look at AspectJ precedence declaration.

Ori Lentz
  • 3,668
  • 6
  • 22
  • 28
1

Yes.

Suppose you have this class:

public class TestClass
{
public static void main( String[] args )
{
    new TestClass().print();
}

public void print()
{
    System.out.println("Hello World");
}
}

And these aspects:

public aspect FirstAspect
{
public pointcut hello1() : execution(void TestClass.print());
void around() : hello1() {
    System.out.println("first");
    proceed();
    System.out.println("first after");
}
}

public aspect SecondAspect
{

    public pointcut hello2() : execution(void TestClass.print());
    void around() : hello2() {
        System.out.println("second");
        proceed();
        System.out.println("second after");
    }
}

When you run, this the following output is produced:

first
second
Hello World
second after
first after
Wim Deblauwe
  • 25,113
  • 20
  • 133
  • 211