假设我们有两个在Spring中定义的bean
<bean class="foo.A"/>
<bean class="foo.B"/>
public class A {
@Autowired
private B b;
}
public class B {
public void foo() {
...
}
}
我要实现的是拦截对
B.foo()
的所有调用。查看文档,我编写了拦截器C
,并如下更改了bean B
的定义:public class C implements org.springframework.aop.MethodBeforeAdvice {
public void before(final Method method, final Object[] args, final Object target) {
// interception logic goes here
}
}
<bean class="foo.C"/>
<bean class="org.springframework.aop.framework.ProxyFactoryBean" scope="prototype">
<property name="proxyTargetClass" value="true"/>
<property name="singleton" value="false"/>
<property name="target">
<bean class="foo.B" scope="prototype"/>
</property>
<property name="interceptorNames">
<list>
<value>foo.C</value>
</list>
</property>
</bean>
问题:启动时,Spring容器抱怨:没有为依赖项找到类型为[foo.B]的匹配bean:期望至少有1个有资格作为此依赖项的自动装配候选的bean。换句话说,它不能将
B
注入到A
中,因为B
隐藏在org.springframework.aop.framework.ProxyFactoryBean之后,并且不再“自动”识别。如果我将定义替换为简单的class=foo.B
,则容器可以正常启动。解决此问题的最佳方法是什么?额外的问题:是否可以在不涉及
B.foo()
且仅使用注释的情况下(最好不涉及ProxyFactoryBean
的情况下)实现对<aop:...
的拦截? 最佳答案
为foo.B
(例如foo.BInterface
)定义接口,并在类A中使用foo.BInterface
。
另请注意,Autowired
注入仅执行一次。因此,如果foo.A
是单例,它将只接收foo.B
的第一个创建实例,而您希望它是一个原型。
奖励的答案:是的,但是可能更复杂。作为一种可能的解决方案,您可以实现BeanPostProcessor
。在实现中,您可以将foo.B替换为动态代理。因此,基本上,您可以执行相同的操作,但是您可以使用基本的Spring功能自己执行操作,而不是使用<aop:
。再说一次:您没有解决“原型没有自动接线”的问题,您仍然需要一个接口。