Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[aspectj-users] Re: [NEWSDELIVER] pointcut all method calls on an object that implements an interface


Tom,

Good question. I have posted this response to aspect-users where you will have a better chance of a discussion. This issue of condition advice when using call & target is well known. The problem lies with the substitutability principle of inheritance. When weaving the call join point (shadow) the compiler does not know the actual target object type: is it a subclass that implements the required interface? Therefore we must advise every method call and add a (cheap) instanceof test which appears in Eclipse as a conditional advice marker. To avoid this you must scope your advice to the classes you are interested in e.g. TheSubject. Solving the problem for execution advice is easier.

In the modified example below I have used two aspects instead of one to distinguish between call & execution advice. I have also included a subclass to show that advice is called for that as well. Both of the other pointcuts worked for me; you might have encountered an incremental compilation bug so do a full build.

package tc;
public class TheSubject implements TheInterface{

         public void interfaceDeclared() {}

         public void classDeclared(){}                
         
         public static void main(String[] args){                                                                    
                          TheSubject sub = new TheSubclass();                                  
                          System.out.println("Calling subjects implementation of interface");
                          sub.interfaceDeclared();                                  
                          System.out.println("\nCalling subjects own method");                                  
                          sub.classDeclared();
                         
                          TheSubclass subc = (TheSubclass)sub;
                          subc.subClassDeclared();
         }                
}


package tc;
public class TheSubclass extends TheSubject {

        public void classDeclared(){}                

        public void subClassDeclared(){}                

}


package tc;
public aspect TheCallAspect {

        before () : call(* TheSubject+.*(..)) && target(TheInterface) {
                System.out.println("TheCallAspect.before() " + thisJoinPoint);
        }
}


package tc;
public aspect TheExecutionAspect {

        before () : execution(* *(..)) && this(TheInterface) {
                System.out.println("TheExecutionAspect.before() " + thisJoinPoint);
        }


}

Calling subjects implementation of interface
TheCallAspect.before() call(void tc.TheSubject.interfaceDeclared())
TheExecutionAspect.before() execution(void tc.TheSubject.interfaceDeclared())

Calling subjects own method
TheCallAspect.before() call(void tc.TheSubject.classDeclared())
TheExecutionAspect.before() execution(void tc.TheSubclass.classDeclared())
TheCallAspect.before() call(void tc.TheSubclass.subClassDeclared())
TheExecutionAspect.before() execution(void tc.TheSubclass.subClassDeclared())

Matthew Webster
AOSD Project
Java Technology Centre, MP146
IBM Hursley Park, Winchester,  SO21 2JN, England
Telephone: +44 196 2816139 (external) 246139 (internal)
Email: Matthew Webster/UK/IBM @ IBMGB, matthew_webster@xxxxxxxxxx

http://w3.hursley.ibm.com/~websterm/

To:        undisclosed-recipients:
cc:        
Subject:        [NEWSDELIVER] pointcut all method calls on an object that implements an interface



Hi everybody,

Been toying with this idea for a day or so and hoping someone will be able
to come up with a better solution than i have!

I want to match on any method calls on an object that implements an
interface, not only the methods defined by that interface, but all other
method calls on the obj as well. Heres some class that should make it abit
clearer.

public class TheSubject implements TheInterface{

                public void interfaceDeclared() {}

                public void classDeclared(){}                
               
                public static void main(String[] args){                                                                    
                                 TheSubject sub = new TheSubject();                                  
                                 System.out.println("Calling subjects implementation of interface");
                                 sub.interfaceDeclared();                                  
                                 System.out.println("\nCalling subjects own method");                                  
                                 sub.classDeclared();
                }                
}

public interface TheInterface {
                public void interfaceDeclared();
}

An now for the aspect

public aspect TheAspect {
               
                pointcut interfaceMethod () : execution(void TheInterface.* ());
               
                void around() : interfaceMethod(){
                                 System.out.println("Interface joinpoint triggered");
                }
               
                pointcut classMethod(): execution (void TheSubject.* ());
               
                void around() : classMethod(){
                                 System.out.println("Class joinpoint triggered");
                }
               
                /*//This results in conditional advice around almost every method call
and does'nt match on the TheSubject calls....
                pointcut anyMethod() : execution(void * ()) &&
if(implementsInter(TheInterface.class, thisJoinPoint.getThis()));
               
                before() : anyMethod(){
                                 System.out.println("Any Method aspect triggered");
                }
               
                private static boolean implementsInter(Class inter, Object obj){
                                 return inter.isInstance(obj);
                }*/
               
                //This works but results in conditional advice around almost every method
called!
                pointcut anyMethod() : target(TheInterface) && call(void * ( .. ));
               
                before() : anyMethod(){
                                 System.out.println("Any Method joinpoint triggered");
                }
               
                /*//Does'nt work and results in many conditional advice markers
                pointcut anyMethod() :execution(void * ( .. )) && this(TheInterface);
               
                before() : anyMethod(){
                                 System.out.println("Any Method aspect triggered");
                }*/
               
}

The output im looking for

Calling subjects implementation of interface
Any Method joinpoint triggered
Interface joinpoint triggered

Calling subjects own method
Any Method joinpoint triggered
Class joinpoint triggered



As you can see i have managed to make it work. However this results in a
huge number of 'conditional' advice markers, which is something i'd rather
not have.  Planning to use this idea in a medium sized project and having
a conditional advice marker round every method is a little unacceptable
(Am i right in thinking that these conditionals with be tested at runtime
everytime a method is called?? thereby introducing abit of a slow dwn?).

So what im really looking for is a technique of matching all calls to on
object that implements a given interface at compile time.

Look forward to your ideas!

Tom

p.s. if anyones got the time i wld'nt mind hearing a little abit about why
the other commented pointcuts don't work as well.....





Back to the top