1

我在将方面应用到 ServiceFactoryBean-created(ServiceLoader-loaded)bean 时遇到问题。

我的 spring 上下文看起来像这样:

...
<aop:aspectj-autoproxy/>

<bean id="myBean"
      class="org.springframework.beans.factory.serviceloader.ServiceFactoryBean"
      p:serviceType="com.test.MyInterface"/>

<bean id="myAnotherBean"
      class="com.test.MyAnotherBean"/>

我的方面定义如下:

@Aspect
public class MyAspect {

    @Pointcut("bean(myBean)")
    public void foo() {
    }

    @Pointcut("bean(myAnotherBean)")
    public void bar() {
    }

    @Around("foo()")
    public Object doFoo(final ProceedingJoinPoint jp) throws Throwable {
        return timed(jp, "foo");
    }

    @Around("bar()")
    public Object doBar(final ProceedingJoinPoint jp) throws Throwable {
        return timed(jp, "bar");
    }

    private ThreadLocal<StopWatch> stopWatch = new ThreadLocal<StopWatch>();

    private Object timed(final ProceedingJoinPoint jp, final String taskName) throws Throwable {
        stopWatch.get().add(taskName);
        try {
            return jp.proceed();
        } finally {
            if (stopWatch.get() != null) {
                stopWatch.get().stop(taskName);
            }
        }
    }
}

出于某种未知原因,方面仅应用于 myAnotherBean 的调用,而不应用于 myBean 的调用。有任何想法吗 ?

4

1 回答 1

0

正如 smp7d 在对您的问题的评论中所建议的那样,如果方法调用来自另一个对象,则 Spring 创建的代理只能将建议应用于它们。自调用不足以触发建议。

http://static.springsource.org/spring/docs/3.0.0.M3/spring-framework-reference/html/ch08s06.html

public class Main {

   public static void main(String[] args) {

      ProxyFactory factory = new ProxyFactory(new SimplePojo());
      factory.addInterface(Pojo.class);
      factory.addAdvice(new RetryAdvice());

      Pojo pojo = (Pojo) factory.getProxy();

      // this is a method call on the proxy!
      pojo.foo();
   }
}

这里要理解的关键是 Main 类的 main(..) 中的客户端代码具有对代理的引用。这意味着对该对象引用的方法调用将是对代理的调用,因此代理将能够委托给与该特定方法调用相关的所有拦截器(建议)。但是,一旦调用最终到达目标对象,在这种情况下是 SimplePojo 引用,它可能对自身进行的任何方法调用,例如 this.bar() 或 this.foo(),都将针对这个参考,而不是代理。这具有重要意义。这意味着自调用不会导致与方法调用相关的建议有机会执行。

于 2011-12-06T17:27:37.547 回答