我在向ServiceFactoryBean创建的(ServiceLoader加载的)bean应用方面时遇到问题。
我的春天语境看起来像这样:
...
<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的调用。 有什么想法吗?
答案 0 :(得分: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(),将被调用这个引用,而不是代理。这具有重要意义。这意味着自我调用不会导致与方法调用相关的建议有机会执行。