@Autowire奇怪的问题
我有一个奇怪的行为自动装配时@Autowire奇怪的问题
我有一个类似这样的代码之一,它的工作原理
@Controller
public class Class1 {
@Autowired
private Class2 object2;
...
}
@Service
@Transactional
public class Class2{
...
}
的问题是,我需要的是Class2中实现了一个接口,这样我只改变了Class2中,所以它现在想:
@Controller
public class Class1 {
@Autowired
private Class2 object2;
...
}
@Service
@Transactional
public class Class2 implements IServiceReference<Class3, Long>{
...
}
public interface IServiceReference<T, PK extends Serializable> {
public T reference(PK id);
}
与此代码我得到一个org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type for Class2
。 看来@Transitional
注释与界面不兼容,因为如果我删除@Transitional
注释或者问题消失并注入bean(虽然我需要在这个类中都有)。如果我将注释@Transitional
放在方法中而不是在类中,也会发生这种情况。
如果有帮助,我使用Spring 3.0.2。
与事务性方法的接口不兼容吗? 可能是Spring bug吗?
的问题是,你的Class1的需要IServiceReference参考,而不是等级2
@Controller
public class Class1 {
@Autowired
private IServiceReference object2;
...
}
的原因,这是春天正在为您所标记@Transactional类动态代理的具体参考。因此,当创建Class2时,它包装在明显不是Class2类型但是IServiceReference类型的Proxy对象中。
如果你想使用的Class2与代理支持的行为,你将不得不打开CGLIB 阅读以下内容:
泉水文件:
Spring缺省使用标准 J2SE动态代理对于AOP代理。 这可以代理任何接口(或一组接口)。
Spring AOP也可以使用CGLIB代理。 这对于代理类, 而不是接口是必需的。默认情况下,如果业务对象 未实现接口,则使用CGLIB 。由于 是编程接口 而不是类的良好惯例,因此业务类 通常会实现一个或多个业务接口。它可以 强制使用CGLIB的,在你需要 告知未 在接口中声明的方法,或者那些 (希望罕见)情况下,您 需要一个代理对象传递给 方法作为具体类型。
重要的是要了解Spring AOP是基于代理的事实 。请参阅 标题为“了解AOP代理”的章节6.6.1, ,其中详细说明了 这个实现细节实际上是 的意思。
Transactional
注解指示Spring在带注释的bean周围生成代理对象,以实现事务性语义。生成的代理将实现与目标bean相同的接口。所以如果你的目标bean实现了IServiceReference
,那么生成的代理也是如此。
如果目标bean没有实现的接口,则生成的代理将改为目标bean类型的子类。
在您的原始示例中,事务代理将是Class2
的子类,因为Class2
未实现任何接口。当您更改Class2
以实施IServiceReference
时,生成的代理不再延长Class2
,而是实施IServiceReference
。这导致您的ClassCastException
。
这种情况的最佳方法是将参考从Class1
删除到Class2
,而是纯粹通过其接口与Class2
进行交谈。 Class2
可以实现尽可能多的接口,代理将实现所有这些接口。
你可以强制Spring生成子类代理而不管接口如何,但这是额外的复杂性,我建议不要这样做。
这正是必要的,当实现的接口实际上不涉及组件的接线。可能发生的情况是,您希望将某个组件作为参数传递到某个位置,但输入为接口。与Spring无关。如果有多个接口,没问题。如果只有一个,春天的事情对他来说就是他的工作 - 而这个@范围完美地固定了他的固定。 :-) – virgo47 2015-09-11 11:51:05
基本上我说的同样的东西:) – 2010-04-26 12:49:15