2010-11-06 36 views
2

当我有以下建立其工作完全正常:NoSuchBeanDefinitionException实现一个新的接口

@Service 
public class MyService { 
} 

public class Test { 
    @Autowired 
    MyService service; 
} 

我改变为MyService实现一个新的接口,这样

@Service 
public class MyService implements NewInterface { 
} 

没有什么特别的这个接口,它只是一个普通的Java接口,没有任何注释和2个非常简单的方法。

现在,Spring不能自动装配这个bean了,它给出了一个NoSuchBeanDefinitionException。我也试图在XML中明确地定义它,但它给出了相同的例外。

如果相关,我使用Spring 2.5并使用Maven构建,类Test是一个单元测试类。当我尝试运行实际的应用程序时,它使用applicationContext.getBean()来获得此服务,并给出以下例外:java.lang.ClassCastException: $Proxy81 cannot be cast to MyService

我错过了什么,该怎么办?

回答

3

当你看到一个类名为$Proxy81的类时,它告诉你Spring已经为你的一个bean自动生成了一个代理对象,在这个例子中是MyService bean的代理对象。这使用java.lang.reflect.Proxy来生成代理对象。该代理对象将实现与正在代理的类相同的接口,但它不会与目标类本身类型兼容。

现在,如果目标类没有实现任何接口,那么Spring将改为使用CGLIB来生成代理。该代理将是目标类的子类,因此代理对象可以安全地转换为目标对象的原始类型。

现在,当在Spring中使用底层代理生成的东西时,你可以经常覆盖这种行为,并告诉它总是使用CGLIB代理,但我假设因为你使用的是@Service,那么你'也使用<context:component-scan>,在这种情况下,我认为你必须坚持默认行为。

不过这不是件坏事。这鼓励你不要将你的类连接在一起,而是编程到接口。任何与MyService的交互都应该可以通过接口来表达,尽管这个概念在谈到单元测试时可能会有些模糊。

+0

感谢您的详细和明确的解释。 – Damien 2010-11-06 22:09:52

3

它看起来像通过接口自动装配,而不是按类名自动装配。

我只是对接口代码我的测试:

public class Test { 
    @Autowired 
    NewInterface service; 
} 

此外,检查this bug,因为它看起来像你的类是被代理这可能是与你有关的。

+0

谢谢,我接受了更详细的skaffman答案,但基本上你也是对的。你的代码片段并不好,因为这个现有的Test类调用的方法不会通过NewInterface公开(也不应该),所以我需要为现有的方法创建另一个新的接口。 – Damien 2010-11-06 22:11:16