11

浏览春Javaconfig参考文档 http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/html/beans.html 我发现了一些容易混淆的部分...春Javaconfig bean间的依赖关系

根据第“5.12.4使用@Configuration注释”它说:

“当@Beans对彼此依存关系,表达该依赖性是为具有一个bean方法调用另一个简单:

@Configuration 
public class AppConfig { 
    @Bean 
    public Foo foo() { 
     return new Foo(bar()); 
    } 
    @Bean 
    public Bar bar() { 
     return new Bar(); 
    } 
} 

在上面的例子中,foo bean通过构造函数注入接收对bar的引用。

好吧,如果一切是无状态的,它可能没有多大关系,但如果你有在配置上面,然后在你的应用程序做:

@Autowired 
private Foo foo; 

@Autowired 
private Bar bar; 

检查豆的散列码,事实证明,你的私有变量酒吧将指不同实例的酒吧, 所使用的这可能不是你所期望的,对不对?

我想说的正常模式,而应该是:

@Configuration 
public class AppConfig { 
    @Bean 
    public Bar bar() { 
     return new Bar(); 
    } 
    @Autowired Bar bar; 
    @Bean 
    public Foo foo() { 
     return new Foo(bar); 
    } 
} 

现在,当你在你的应用程序自动装配两个bean,你只会造成酒吧的一个实例。

我是否错过了一些东西,或者我正确地指出文档在这里是片状的?

然后,再往下,根据第“如何基于Java的配置的详细信息内部工作” 它看起来像他们试图“澄清”这个问题:

@Configuration 
public class AppConfig { 
    @Bean 
    public ClientService clientService1() { 
     ClientServiceImpl clientService = new ClientServiceImpl(); 
     clientService.setClientDao(clientDao()); 
     return clientService; 
    } 
    @Bean 
    public ClientService clientService2() { 
     ClientServiceImpl clientService = new ClientServiceImpl(); 
     clientService.setClientDao(clientDao()); 
     return clientService; 
    } 
    @Bean 
    public ClientDao clientDao() { 
     return new ClientDaoImpl(); 
    } 
} 

现在,不幸的是,这种配置在运行时甚至不会加载,因为有2个相同类型的ClientService,没有明显的属性,所以得到异常

org.springframework.beans.factory.NoUniqueBeanDefinitionException: 
No qualifying bean of type [.....] is defined: 
expected single matching bean but found 2 

但是,即使我们改变的例子略显不足,举头2种豆不同类型,

@Bean 
public ClientService1 clientService1() {...clientDao()...} 
@Bean 
public ClientService2 clientService2() {...clientDao()...} 
@Bean 
public ClientDao clientDao() { 
    return new ClientDaoImpl(); 
} 

这仍是不正确的,因为 - 违背了文字的权利要求的东西 - 我们仍然会创建3种不同的ClientDaoImpl的实例, 自动装配所有3个bean时。

同样,我完全错过了某些东西,还是文档真的和我一样糟糕?

编辑:增加了一个演示,将展示我看到了问题:

https://github.com/rop49/demo

一个bean ServiceA, 和两个豆ServiceB1ServiceB2该构造,内喷射ServiceA

然后两个测试类Config01TestConfig02Test是除了结构相同。第一次测试通过,第二次失败,因为唯一性断言。

+3

为什么你认为你会得到不同的'Bar'对象? – chrylis 2014-09-19 23:09:47

+0

我做了一个小测试,并检查beans中的hashCodes。他们是不同的。我在上面的问题中澄清了这一点,谢谢。 – Rop 2014-09-20 06:28:03

+0

任何方式你可以发布一个简单的运行在GitHub上的例子,可能与Spring Boot?我从来没有见过这种行为,如果真的发生了,这是一个错误。 – chrylis 2014-09-20 09:15:03

回答

8

检查您的配置类上是否有@Configuration注释。你的演示至少在Config01Config02课程中缺失。如果我将它们添加到测试通过的那些类中。

+0

啊,很好,我得到了整理:)谢谢菲尔! – Rop 2014-09-20 15:56:49

+0

作为一个侧面提示......如果Spring拒绝没有\ @Configuration注释的类的@SpringApplicationConfiguration类型,它会有意义吗?或者它会成为一个有效的用例吗? – Rop 2014-09-20 16:11:49

+1

不幸的是,它会破坏后向兼容性。请参阅lite-beans部分:http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/htmlsingle/#beans-java-basic-concepts – 2014-09-21 17:49:50

0

我没有测试的例子自己,这应该确保您有酒吧只有一个实例在整个应用程序上下文

@Configuration 
public class AppConfig { 
    @Bean 
    public Foo foo(Bar bar) { 
     return new Foo(bar); 
    } 
    @Bean 
    public Bar bar() { 
     return new Bar(); 
    } 
}