我知道在spring 2.5中引入@Component注释是为了通过使用类路径扫描来摆脱xml bean定义。
@Bean是在spring 3.0中引入的,可以和@Configuration一起使用,以便完全摆脱xml文件,而使用java配置。
是否有可能重用@Component注释而不是引入@Bean注释?我的理解是,最终目标是在这两种情况下都创建bean。
我知道在spring 2.5中引入@Component注释是为了通过使用类路径扫描来摆脱xml bean定义。
@Bean是在spring 3.0中引入的,可以和@Configuration一起使用,以便完全摆脱xml文件,而使用java配置。
是否有可能重用@Component注释而不是引入@Bean注释?我的理解是,最终目标是在这两种情况下都创建bean。
当前回答
当您使用@Component标记时,这与使用带有香草bean声明方法(用@Bean注释)的POJO(普通旧Java对象)是一样的。例如,下面的方法1和2将给出相同的结果。
方法1
@Component
public class SomeClass {
private int number;
public SomeClass(Integer theNumber){
this.number = theNumber.intValue();
}
public int getNumber(){
return this.number;
}
}
用豆子表示“数字”:
@Bean
Integer theNumber(){
return new Integer(3456);
}
方法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;
}
}
两者都有豆子:
@Bean
Integer theNumber(){
return new Integer(3456);
}
@Bean
SomeClass someClass(Integer theNumber){
return new SomeClass(theNumber);
}
方法2允许您将bean声明放在一起,它更加灵活。您甚至可能想要添加另一个非香草SomeClass bean,如下所示:
@Bean
SomeClass strawberryClass(){
return new SomeClass(new Integer(1));
}
其他回答
以上答案的附加分数
假设我们有一个在多个应用程序中共享的模块,它包含一些服务。并不是每个应用程序都需要。
如果在这些服务类上使用@Component并且在应用程序中扫描组件,
我们最终可能会检测到比必要的更多的bean
在这种情况下,您要么必须调整组件扫描的过滤,要么提供即使是未使用的bean也可以运行的配置。否则,应用程序上下文将无法启动。
在这种情况下,最好使用@Bean注释并只实例化那些bean,
每个应用程序都需要哪些
因此,本质上,使用@Bean向上下文添加第三方类。@Component如果它只是在你的单个应用程序中。
@ component 适用于元件扫描和自动布线。
什么时候应该使用@Bean?
有时自动配置不是一个选项。什么时候?让我们想象一下,您想要连接来自第三方库的组件(您没有源代码,所以不能用@Component注释它的类),因此自动配置是不可能的。
@Bean注释返回一个对象,spring应该在应用程序上下文中将该对象注册为bean。方法主体承担负责创建实例的逻辑。
Spring支持多种类型的注解,比如@Component、@Service、@Repository。所有这些都可以在org.springframework.stereotype包下找到。
@Bean可以在org.springframework.context.annotation包下找到。
当应用程序中的类使用上述任何注释时,在项目启动期间spring扫描(使用@ComponentScan)每个类,并将类的实例注入到IOC容器中。@ComponentScan要做的另一件事是运行带有@Bean的方法,并将返回对象作为bean恢复到Ioc容器中。
@ component
如果我们用@Component或者其他的Stereotype注释来标记一个类,这些类将会被类路径扫描自动检测到。只要这些类在我们的基本包下,或者Spring意识到要扫描另一个包,就会为每个类创建一个新bean。
package com.beanvscomponent.controller;
import org.springframework.stereotype.Controller;
@Controller
public class HomeController {
public String home(){
return "Hello, World!";
}
}
在带注释的类和bean之间存在隐式的一对一映射(即每个类一个bean)。这种方法对连接的控制非常有限,因为它是纯声明式的。同样重要的是要注意原型注释是类级注释。
@ bean
@Bean用于显式地声明单个bean,而不是像我们使用@Controller那样让Spring自动完成。它将bean的声明与类定义解耦,并允许您按照自己的选择创建和配置bean。对于@Bean,您没有将这个注释放在类级别。如果你尝试这样做,你会得到一个无效的类型错误。@Bean文档将其定义为:
Indicates that a method produces a bean to be managed by the Spring container.
通常,@Bean方法在@Configuration类中声明。我们有一个需要实例化的用户类,然后使用该实例创建一个bean。这就是我前面说过的对bean的定义有更多控制的地方。
package com.beanvscomponent;
public class User {
private String first;
private String last;
public User(String first, String last) {
this.first = first;
this.last = last;
}
}
正如我前面提到的,@Bean方法应该在@Configuration类中声明。
package com.beanvscomponent;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ApplicationConfig {
@Bean
public User superUser() {
return new User("Partho","Bappy");
}
}
方法的名称实际上就是bean的名称。如果我们调出执行器中的/beans端点,就可以看到bean的定义。
{
"beans": "superUser",
"aliases": [],
"scope": "singleton",
"type": "com.beanvscomponent.User",
"resource": "class path resource
[com/beanvscomponent/ApplicationConfig.class]",
"dependencies": []
}
@组件vs @Bean
我希望这澄清了什么时候使用@Component和什么时候使用@Bean的一些问题。这可能有点令人困惑,但随着您开始编写更多的应用程序,它将变得非常自然。
这两种方法都旨在在Spring容器中注册目标类型。
区别在于@Bean适用于方法,而@Component适用于类型。
因此,当您使用@Bean注释时,您可以在方法主体中控制实例创建逻辑(参见上面的示例)。而@Component注释则不行。
Bean和Component的区别: