[译]Spring中@Configuration和@Component的对比
本文翻译自Spring @Configuration vs @Component。
在前一篇文章中,我说过我们可以使用@Component作为@Configuration的一个备用选择,实际上这是来自于Spring team的官方建议
也就是说,
@Bean在我们不使用任何CGLIB代理时有一种精简模式:只需在未使用@Configuration注释的类上声明@Bean方法(但通常需要用另一种Spring中的stereotype实现替代,如@Component),只要我们不在 @Bean 方法之间进行编程调用,程序就能正常工作。
简而言之,下面显示的每个应用程序上下文配置将以完全不同的方式来生效:
@Configuration
public static class Config {
@Bean
public SimpleBean simpleBean() {
return new SimpleBean();
}
@Bean
public SimpleBeanConsumer simpleBeanConsumer() {
return new SimpleBeanConsumer(simpleBean());
}
}
@Component
public static class Config {
@Bean
public SimpleBean simpleBean() {
return new SimpleBean();
}
@Bean
public SimpleBeanConsumer simpleBeanConsumer() {
return new SimpleBeanConsumer(simpleBean());
}
}
第一段代码能按照预期正常工作,SimpleBeanConsumer将获取一个指向SimpleBean单例的链接,不幸的是,该段代码在Java数字签名环境中不生效。
第二个代码则是完全不正确的,因为Spring会创建SimpleBean的单例bean,但是SimpleBeanConsumer会获得另一个SimpleBean实例,该实例不受Spring上下文控制。
此现象的原因解释如下:
如果使用@Configuration,则所有标记为@Bean的方法都将被包装到CGLIB包装器中,该包装器的工作方式为该方法第一次调用时将执行原始方法的主体,并将生成的对象注册在Spring上下文中,之后对该方法的调用都只返回从Spring上下文中获取到的bean。
在上面的第二个代码块中,new SimpleBeanConsumer(simpleBean())只是调用一个纯java方法调用,要更正该代码块,可修改如下:
@Component
public static class Config {
@Autowired
SimpleBean simpleBean;
@Bean
public SimpleBean simpleBean() {
return new SimpleBean();
}
@Bean
public SimpleBeanConsumer simpleBeanConsumer() {
return new SimpleBeanConsumer(simpleBean);
}
}
这篇文章的所有代码示例都可以在我的个人GitHub中找到。