实现BeanNameAware打破Autowired

时间:2014-07-23 07:26:47

标签: spring spring-mvc

我正在使用Spring 3.2.5,我正在尝试创建一个类实现BeanNameAware如果没有实现此类,我的应用程序就可以运行。 当我实现它时,无法启动错误,如:

  

引起:   org.springframework.beans.factory.NoSuchBeanDefinitionException:没有   找到类型为[mypackage.AccountSiebelDataHolder]的限定bean   依赖:预计至少有1个bean有资格成为autowire   这种依赖的候选人。依赖注释:   {@ org.springframework.beans.factory.annotation.Qualifier(值= accountSiebelDataHolder),   @ org.springframework.beans.factory.annotation.Autowired(所需=真)}

我有这样的classe:

@Transactional
public abstract class DataHolder<T extends DbObject> implements BeanNameAware{

    private String beanName;

    ...

    @Override
    public void setBeanName(String name) {
        System.out.println(name);
        this.beanName=name;

    }
}

有几个课程扩展了这门课程:

public class AccountSiebelDataHolder extends DataHolder<AccountSiebel> {
 ...
}

bean是在xml:

中创建的
<bean id="accountSiebelDataHolder" class="mypackage.AccountSiebelDataHolder">
...
</bean>

我知道我的豆子很好,因为我在控制台中看到每个豆子的名字。 调用setBeanName()方法。 但在此之后,它在自动装配时失败(有或没有@Qualifier相同)

我在childs类中尝试了实现BeanNameAware,它给了我相同的结果。

也许这很重要:这些Dataholder类由Spring根上下文实例化。然后注入@Controller bean,这些bean在@MVC上下文中实例化。但它在BeanNameAware之后效果很好。

1 个答案:

答案 0 :(得分:3)

问题出现在@Transactional。使用AOP应用事务,默认情况下Spring uses proxies应用AOP。

如果没有接口,spring将使用cglib创建基于类的代理。在运行时,会创建一个动态子类,此子类仍然是DataHolder实例。

添加接口将导致创建JDK动态代理,即接口。在运行时,创建动态类,实现对象的所有接口以进行代理。这导致类成为BeanNameAware实例,而不再是DataHolder的实例。

要解决此问题,请求您的事务支持始终使用基于类的代理。为此,将proxy-target-class上的<tx:annoation-driven />属性设置为true

<tx:annotation-driven proxy-target-class="true" />