本文翻译自:Spring: @Component versus @Bean
I understand that @Component
annotation was introduced in spring 2.5 in order to get rid of xml bean definition by using classpath scanning. 我了解到@Component
注释是在Spring 2.5中引入的,目的是通过使用类路径扫描摆脱xml bean的定义。
@Bean
was introduced in spring 3.0 and can be used with @Configuration
in order to fully get rid of xml file and use java config instead. @Bean
是在Spring 3.0中引入的,可以与@Configuration
一起使用,以完全摆脱xml文件并改用Java config。
Would it have been possible to re-use the @Component
annotation instead of introducing @Bean
annotation? 是否有可能重新使用@Component
注释而不是引入@Bean
注释? My understanding is that the final goal is to create beans in both cases. 我的理解是,两种情况下的最终目标都是创建bean。
#1楼
参考:https://stackoom.com/question/iUf4/春季-Component与-Bean
#2楼
@Component
and @Bean
do two quite different things, and shouldn't be confused. @Component
和@Bean
做两个完全不同的事情,不要混淆。
@Component
(and @Service
and @Repository
) are used to auto-detect and auto-configure beans using classpath scanning. @Component
(以及@Service
和@Repository
)用于使用类路径扫描自动检测和自动配置bean。 There's an implicit one-to-one mapping between the annotated class and the bean (ie one bean per class). 在带注释的类和Bean之间存在隐式的一对一映射(即,每个类一个Bean)。 Control of wiring is quite limited with this approach, since it's purely declarative. 由于此布线仅是声明性的,因此使用此方法对布线的控制非常有限。
@Bean
is used to explicitly declare a single bean, rather than letting Spring do it automatically as above. @Bean
用于显式声明单个bean,而不是像上面那样让Spring自动执行。 It decouples the declaration of the bean from the class definition, and lets you create and configure beans exactly how you choose. 它使Bean的声明与类定义脱钩,并让您完全按照自己的选择创建和配置Bean。
To answer your question... 要回答您的问题...
would it have been possible to re-use the
@Component
annotation instead of introducing@Bean
annotation? 是否有可能重新使用@Component
注释而不是引入@Bean
注释?
Sure, probably; 当然可以; but they chose not to, since the two are quite different. 但他们选择不这样做,因为两者是完全不同的。 Spring's already confusing enough without muddying the waters further. 春天已经足够混乱了,又没有使水进一步混乱。
#3楼
Let's consider I want specific implementation depending on some dynamic state. 让我们考虑根据某些动态状态来实现特定的实现。 @Bean
is perfect for that case. @Bean
非常适合这种情况。
@Bean
@Scope("prototype")
public SomeService someService() {
switch (state) {
case 1:
return new Impl1();
case 2:
return new Impl2();
case 3:
return new Impl3();
default:
return new Impl();
}
}
However there is no way to do that with @Component
. 但是,无法使用@Component
做到这一点。
#4楼
@Component Preferable for component scanning and automatic wiring. @Component优选用于组件扫描和自动接线。
When should you use @Bean ? 什么时候应该使用@Bean ?
Sometimes automatic configuration is not an option. 有时,自动配置不是一个选择。 When? 什么时候? Let's imagine that you want to wire components from 3rd-party libraries (you don't have the source code so you can't annotate its classes with @Component), so automatic configuration is not possible. 假设您想从第三方库连接组件(您没有源代码,因此不能使用@Component注释其类),因此无法进行自动配置。
The @Bean annotation returns an object that spring should register as bean in application context. @Bean批注返回一个对象 , 该对象应在应用程序上下文中作为Spring注册为bean。 The body of the method bears the logic responsible for creating the instance. 方法的主体具有负责创建实例的逻辑。
#5楼
Both approaches aim to register target type in Spring container. 两种方法都旨在在Spring容器中注册目标类型。
The difference is that @Bean
is applicable to methods , whereas @Component
is applicable to types . 不同之处在于@Bean
适用于方法 ,而@Component
适用于类型 。
Therefore when you use @Bean
annotation you control instance creation logic in method's body (see example above ). 因此,当您使用@Bean
批注时,您可以控制方法主体中的实例创建逻辑(请参见上面的示例 )。 With @Component
annotation you cannot. 使用@Component
注释不能。
#6楼
When you use the @Component
tag, it's the same as having a POJO (Plain Old Java Object) with a vanilla bean declaration method (annotated with @Bean
). 当您使用@Component
标记时,它与使用香草豆声明方法(以@Bean
注释)的POJO(普通的旧Java对象) @Bean
。 For example, the following method 1 and 2 will give the same result. 例如,下面的方法1和2将给出相同的结果。
Method 1 方法1
@Component
public class SomeClass {
private int number;
public SomeClass(Integer theNumber){
this.number = theNumber.intValue();
}
public int getNumber(){
return this.number;
}
}
with a bean for 'theNumber': 与“ theNumber”的bean:
@Bean
Integer theNumber(){
return new Integer(3456);
}
Method 2 方法二
//Note: no @Component tag
public class SomeClass {
private int number;
public SomeClass(Integer theNumber){
this.number = theNumber.intValue();
}
public int getNumber(){
return this.number;
}
}
with the beans for both: 与两个豆:
@Bean
Integer theNumber(){
return new Integer(3456);
}
@Bean
SomeClass someClass(Integer theNumber){
return new SomeClass(theNumber);
}
Method 2 allows you to keep bean declarations together, it's a bit more flexible etc. You may even want to add another non-vanilla SomeClass bean like the following: 方法2允许您将bean声明保持在一起,这更加灵活等等。您甚至可能想要添加另一个非香草的SomeClass bean,如下所示:
@Bean
SomeClass strawberryClass(){
return new SomeClass(new Integer(1));
}