3

I'm trying to trace execution of an app running on ServiceMix 3.2 which uses spring 2.5 under the hood. I'm using CGLIB (advising classes, not interfaces) and I would like to direct tracing using pointcuts. I therefore configured spring to perform load-time weaving in one of my service unit xbean.xml files like so:

<bean id="debugInterceptor"
    class="org.springframework.aop.interceptor.SimpleTraceInterceptor"/>
<aop:config proxy-target-class="true">
    <aop:advisor advice-ref="debugInterceptor"
        pointcut="within(my.package.AClass)" order="1"/>
</aop:config>

Classes get advised, but it isn't limited to what I specified in the pointcut, i.e. methods of classes other than my.package.AClass get advised and, for reasons not important here, break class loading.

I tried defining the pointcut this way, but it made no difference:

<aop:advisor advice-ref="debugInterceptor"
    pointcut="execution(* my.package.AClass.*(..))" order="1"/>

In general, I would like to advise my.package..* classes except my.package.no_aop.*, but I don't seem to be making progress.

Why does CGLIB process classes outside of my.package.AClass? How do I prevent it? Would switching to Spring AOP (as opposed to AspectJ) make a difference?

рüффп
  • 5,172
  • 34
  • 67
  • 113
Tomislav Nakic-Alfirevic
  • 10,017
  • 5
  • 38
  • 51

1 Answers1

1

I did it using Spring 3.0.x and @AspectJ annotations, but it should be analogous using 2.5 and XML.

Class A from package my.pkg, that needs to be adviced:

package my.pkg;

public class ClassA {

    public void doFromClassA() {
        System.out.println("Hello from A!");
    }
}

Class B from package my.pkg.noaop, that needs not to be adviced:

package my.pkg.noaop;

public class ClassB {

    public void doFromClassB() {
        System.out.println("Hello from B!");
    }
}

The aspect:

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class AopTestAspect {

    @Around("within(my.pkg..*) && !within(my.pkg.noaop..*)")
    public void advice(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("Hello from adviced!");
        pjp.proceed();
    }
}

The configuration (let me know if You need XML version):

import my.pkg.ClassA;
import my.pkg.noaop.ClassB;

import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AopTestConfig {

    @Bean
    public ClassA classA() {
        return new ClassA();
    }

    @Bean
    public ClassB classB() {
        return new ClassB();
    }

    @Bean
    public AopTestAspect aspect() {
        return new AopTestAspect();
    }

    @Bean
    public AnnotationAwareAspectJAutoProxyCreator autoProxyCreator() {
        AnnotationAwareAspectJAutoProxyCreator autoProxyCreator = new AnnotationAwareAspectJAutoProxyCreator();
        autoProxyCreator.setProxyTargetClass(true);
        return autoProxyCreator;
    }
}

The test:

import my.pkg.ClassA;
import my.pkg.noaop.ClassB;

import org.junit.Test;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class AopTest {

    @Test
    public void test() {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        applicationContext.register(AopTestConfig.class);
        applicationContext.refresh();

        ClassA a = BeanFactoryUtils.beanOfType(applicationContext, ClassA.class);
        ClassB b = BeanFactoryUtils.beanOfType(applicationContext, ClassB.class);

        a.doFromClassA();
        b.doFromClassB();
    }
}

And the output from the test:

Hello from adviced!
Hello from A!
Hello from B!

As You can see only the ClassA got adviced.

Conclusion

The key is the pointcut experssion:

within(my.pkg..*) && !within(my.pkg.noaop..*)

Roadrunner
  • 6,661
  • 1
  • 29
  • 38
  • Thank you for a very extensive answer, Roadrunner. The pointcut expression helps to filter out everything from the noaop package, but it doesn't explain why `within(my.pkg.AClass)` didn't work. Also, I see a lot of CGLIB-related messages in the log and it appears methods do get advised, but I see no actual output from the spring debug aspect. :\ I guess I'll open up another question for that. If no other answers come in, I will mark this one as answered, but I would prefer to understand why the other pointcut expressions didn't work in the first place... – Tomislav Nakic-Alfirevic Jul 17 '11 at 14:47
  • In my test both `within(my.pkg.ClassA)` and `execution(* my.pkg.ClassA.*(..))` advice only the `ClassA` and `ClassB` remains not proxied. And same result gave me `within(my.pkg.*)` and `execution(* my.pkg.*.*(..))`. So it seems there's nothing wrong with Your pointuct expressions - it must be sth else in Your configuration. – Roadrunner Jul 18 '11 at 09:15
  • Maybe some other pointcut expression in Your configuration matches the `ClassB` - that's why Yous see CGLIB messages, but no output from the `SimpleTraceInterceptor`? – Roadrunner Jul 18 '11 at 09:23
  • I would make similar suggestions to yours, but no other pointcuts are defined... Also, by my understanding, SimpleTrace would then be applied invariably, regardless of other aspects...ah well, I'll have to dig a little deeper. At least I managed to advise the right classes this time. Thanks. :) – Tomislav Nakic-Alfirevic Jul 18 '11 at 10:13