如何将切面编织限制在被aop:advisor切入点引用的类中?

3

我正在尝试跟踪在ServiceMix 3.2上运行的应用程序的执行,该应用程序在后台使用spring 2.5。我正在使用CGLIB(对类进行建议,而不是接口),并且我希望使用切入点来指导跟踪。因此,我在我的一个服务单元xbean.xml文件中配置了spring以执行load-time weaving,如下所示:

<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>

类得到了建议,但不限于我在切入点中指定的内容,即除my.package.AClass之外的其他类的方法也被建议,并且由于某些原因破坏了类加载。

我尝试以这种方式定义切入点,但没有任何区别:

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

一般来说,我建议使用my.package..*类,但不包括my.package.no_aop.*,但我好像没有取得进展。
为什么CGLIB会处理my.package.AClass之外的类?如何防止它?转换到Spring AOP(而不是AspectJ)是否有所不同?

有人吗?我很惊讶没有任何人能够快速回答这个与Spring和AOP相关的严肃问题... :\ - Tomislav Nakic-Alfirevic
有谁能重新表达这个问题,让它更清晰易懂吗? - Tomislav Nakic-Alfirevic
1个回答

1

我使用 Spring 3.0.x 和 @AspectJ 注解完成了它,但使用 2.5 和 XML 应该是类似的。

需要被增强的 my.pkg 包中的 A 类:

package my.pkg;

public class ClassA {

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

来自包my.pkg.noaop的B类,不需要被建议:

package my.pkg.noaop;

public class ClassB {

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

方面:

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();
    }
}

配置(如果需要XML版本,请告诉我):
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;
    }
}

测试:

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();
    }
}

测试的输出结果为:

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

正如您所见,只有ClassA被通知了。

结论

关键在于切入点表达式:

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


非常感谢你详尽的答复,Roadrunner。切入点表达式有助于过滤掉来自noaop包的所有内容,但它并没有解释为什么“within(my.pkg.AClass)”无法工作。此外,我在日志中看到了很多与CGLIB相关的消息,并且似乎确实对方法进行了建议,但我没有看到来自spring debug aspect的实际输出。\ : \ 我想我会针对这个问题开另一个问题。如果没有其他答案,我将把这个标记为已回答,但我更愿意了解为什么其他切入点表达式一开始不起作用... - Tomislav Nakic-Alfirevic
在我的测试中,within(my.pkg.ClassA)execution(* my.pkg.ClassA.*(..)) 只会对 ClassAClassB 进行增强,而其他类则不会。而 within(my.pkg.*)execution(* my.pkg.*.*(..)) 也得到了相同的结果。因此,您的切点表达式似乎没有问题 - 必须是配置中的其他问题。 - Roadrunner
也许您的配置中有其他的切入点表达式匹配了ClassB,这就是为什么您会看到CGLIB消息,但没有从SimpleTraceInterceptor输出任何内容的原因? - Roadrunner
我会提出与你类似的建议,但是没有定义其他切入点... 另外,根据我的理解,SimpleTrace将无论其他方面如何都会被应用...啊,好吧,我得深入挖掘一下。 至少我这次成功地向正确的类提供建议。谢谢 :) - Tomislav Nakic-Alfirevic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接