Annotations, inner classes and set && withincode

View: New views
3 Messages — Rating Filter:   Alert me  

Annotations, inner classes and set && withincode

by Captain Haddock-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Can't seem to get a pointcut to work on a setter that is within a method
of an inner class.

A pointcut on the outer class works fine (see "doSomething").

Also a pointcut of just the "set" or just the "within" works fine, just
not the && of the two.

Any thoughts?

thx in advance, Haddock

package foo;
public class App
{
     private int count;

     public static void main( String[] args )
     {
         try {
             App app = new App();
             app.doSomething();
         } catch (Exception e) {
             e.printStackTrace();
         }

         System.exit(1);
     }

     public App() {
     }

     private void doSomething() {
         System.out.println("> before");
         count = 30;
         System.out.println("> after");
         new App.Inner().innerDoSomething();
     }

     private class Inner {
         private void innerDoSomething() {
             System.out.println(">> before");
             count = 25;
             System.out.println(">> after");
         }
     }
}

package aspects;
@Aspect
public class LoggingAspect {
     @Pointcut("set(int foo.App.count) && withincode(void
foo.App.doSomething())")
     void doSomething() {}

     @Before("doSomething()")
     public void logDoSomething() {
         System.out.println("doSomething()");
     }

     @Pointcut("set(int foo.App.count) && withincode(void
foo.App.Inner.innerDoSomething())")
     void innerDoSomething() {}

     @Before("innerDoSomething()")
     public void logInnerDoSomething() {
         System.out.println("innerDoSomething()");
     }
}

_______________________________________________
aspectj-users mailing list
aspectj-users@...
https://dev.eclipse.org/mailman/listinfo/aspectj-users

Re: Annotations, inner classes and set && withincode

by Andy Clement :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Because your 'count' field is private, the inner type cannot directly see it and must go through an accessor generated by the compiler (this is nothing to do with AspectJ, this is how java compilers tend to work).

If you javap the App class you will see, javap -private foo.App

public class foo.App extends java.lang.Object{
    private int count;
    public static void main(java.lang.String[]);
    public foo.App();
    private void doSomething();
    static void access$0(foo.App, int);
}

That final method 'access$0' is used to write a value into the field.  The join point 'set(int foo.App.count)' actually occurs within the code of the accessor, not within your innerDoSomething().  If we look inside innerDoSomething() we can see it delegate to the accessor:

  Code:
   Stack=2, Locals=1, Args_size=1
   0:   getstatic       #21; //Field java/lang/System.out:Ljava/io/PrintStream;
   3:   ldc     #27; //String >> before
   5:   invokevirtual   #29; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   8:   aload_0
   9:   getfield        #10; //Field this$0:Lfoo/App;
   12:  bipush  25
   14:  invokestatic    #35; //Method foo/App.access$0:(Lfoo/App;I)V
   17:  getstatic       #21; //Field java/lang/System.out:Ljava/io/PrintStream;
   20:  ldc     #41; //String >> after
   22:  invokevirtual   #29; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   25:  return

in the middle you see the load up of 25 and then a call to the accessor.

If you make the count field anything other than private, your code will match fine as the accessor is not required


Andy

2009/6/17 Captain Haddock <davidg@...>
Can't seem to get a pointcut to work on a setter that is within a method of an inner class.

A pointcut on the outer class works fine (see "doSomething").

Also a pointcut of just the "set" or just the "within" works fine, just not the && of the two.

Any thoughts?

thx in advance, Haddock

package foo;
public class App
{
   private int count;

   public static void main( String[] args )
   {
       try {
           App app = new App();
           app.doSomething();
       } catch (Exception e) {
           e.printStackTrace();
       }

       System.exit(1);
   }

   public App() {
   }

   private void doSomething() {
       System.out.println("> before");
       count = 30;
       System.out.println("> after");
       new App.Inner().innerDoSomething();
   }

   private class Inner {
       private void innerDoSomething() {
           System.out.println(">> before");
           count = 25;
           System.out.println(">> after");
       }
   }
}

package aspects;
@Aspect
public class LoggingAspect {
   @Pointcut("set(int foo.App.count) && withincode(void foo.App.doSomething())")
   void doSomething() {}

   @Before("doSomething()")
   public void logDoSomething() {
       System.out.println("doSomething()");
   }

   @Pointcut("set(int foo.App.count) && withincode(void foo.App.Inner.innerDoSomething())")
   void innerDoSomething() {}

   @Before("innerDoSomething()")
   public void logInnerDoSomething() {
       System.out.println("innerDoSomething()");
   }
}

_______________________________________________
aspectj-users mailing list
aspectj-users@...
https://dev.eclipse.org/mailman/listinfo/aspectj-users


_______________________________________________
aspectj-users mailing list
aspectj-users@...
https://dev.eclipse.org/mailman/listinfo/aspectj-users

Re: Annotations, inner classes and set && withincode

by Captain Haddock-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Duh! .. yes of course!!!

In the real case I won't be able to change the scope of the field .. but
since you have pointed out the underlying problem I think a workable
solution in my real life case is to wrap the "withincode" with a
"cflowbelow" .. that works fine

thx for the input, Haddock

Andy Clement wrote:

> Because your 'count' field is private, the inner type cannot directly
> see it and must go through an accessor generated by the compiler (this
> is nothing to do with AspectJ, this is how java compilers tend to work).
>
> If you javap the App class you will see, javap -private foo.App
>
> public class foo.App extends java.lang.Object{
>     private int count;
>     public static void main(java.lang.String[]);
>     public foo.App();
>     private void doSomething();
>     static void access$0(foo.App, int);
> }
>
> That final method 'access$0' is used to write a value into the field.  
> The join point 'set(int foo.App.count)' actually occurs within the code
> of the accessor, not within your innerDoSomething().  If we look inside
> innerDoSomething() we can see it delegate to the accessor:
>
>   Code:
>    Stack=2, Locals=1, Args_size=1
>    0:   getstatic       #21; //Field
> java/lang/System.out:Ljava/io/PrintStream;
>    3:   ldc     #27; //String >> before
>    5:   invokevirtual   #29; //Method
> java/io/PrintStream.println:(Ljava/lang/String;)V
>    8:   aload_0
>    9:   getfield        #10; //Field this$0:Lfoo/App;
>    12:  bipush  25
>    14:  invokestatic    #35; //Method foo/App.access$0:(Lfoo/App;I)V
>    17:  getstatic       #21; //Field
> java/lang/System.out:Ljava/io/PrintStream;
>    20:  ldc     #41; //String >> after
>    22:  invokevirtual   #29; //Method
> java/io/PrintStream.println:(Ljava/lang/String;)V
>    25:  return
>
> in the middle you see the load up of 25 and then a call to the accessor.
>
> If you make the count field anything other than private, your code will
> match fine as the accessor is not required
>
>
> Andy
>
> 2009/6/17 Captain Haddock <davidg@... <mailto:davidg@...>>
>
>     Can't seem to get a pointcut to work on a setter that is within a
>     method of an inner class.
>
>     A pointcut on the outer class works fine (see "doSomething").
>
>     Also a pointcut of just the "set" or just the "within" works fine,
>     just not the && of the two.
>
>     Any thoughts?
>
>     thx in advance, Haddock
>
>     package foo;
>     public class App
>     {
>        private int count;
>
>        public static void main( String[] args )
>        {
>            try {
>                App app = new App();
>                app.doSomething();
>            } catch (Exception e) {
>                e.printStackTrace();
>            }
>
>            System.exit(1);
>        }
>
>        public App() {
>        }
>
>        private void doSomething() {
>            System.out.println("> before");
>            count = 30;
>            System.out.println("> after");
>            new App.Inner().innerDoSomething();
>        }
>
>        private class Inner {
>            private void innerDoSomething() {
>                System.out.println(">> before");
>                count = 25;
>                System.out.println(">> after");
>            }
>        }
>     }
>
>     package aspects;
>     @Aspect
>     public class LoggingAspect {
>        @Pointcut("set(int foo.App.count) && withincode(void
>     foo.App.doSomething())")
>        void doSomething() {}
>
>        @Before("doSomething()")
>        public void logDoSomething() {
>            System.out.println("doSomething()");
>        }
>
>        @Pointcut("set(int foo.App.count) && withincode(void
>     foo.App.Inner.innerDoSomething())")
>        void innerDoSomething() {}
>
>        @Before("innerDoSomething()")
>        public void logInnerDoSomething() {
>            System.out.println("innerDoSomething()");
>        }
>     }
>
>     _______________________________________________
>     aspectj-users mailing list
>     aspectj-users@... <mailto:aspectj-users@...>
>     https://dev.eclipse.org/mailman/listinfo/aspectj-users
>
>
>
> ------------------------------------------------------------------------
>
> _______________________________________________
> aspectj-users mailing list
> aspectj-users@...
> https://dev.eclipse.org/mailman/listinfo/aspectj-users

_______________________________________________
aspectj-users mailing list
aspectj-users@...
https://dev.eclipse.org/mailman/listinfo/aspectj-users