假设我们有两个在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:。再说一次:您没有解决“原型没有自动接线”的问题,您仍然需要一个接口。

10-07 19:09
查看更多