Spring:@Component与@Bean

时间:2012-05-15 15:45:46

标签: java spring annotations autowired

我知道在第2.5版中引入了@Component注释,以便通过使用类路径扫描来消除xml bean定义。

@Bean是在3.0版本中引入的,可以与@Configuration一起使用,以便完全摆脱xml文件并改为使用java配置。

是否可以重复使用@Component注释而不是引入@Bean注释?我的理解是,最终目标是在两种情况下都创建bean。

16 个答案:

答案 0 :(得分:333)

@Component@Bean做了两件截然不同的事情,不应该混淆。

@Component(以及@Service@Repository)用于使用类路径扫描自动检测和自动配置bean。注释类和bean之间存在隐式的一对一映射(即每个类一个bean)。这种方法对布线的控制非常有限,因为它纯粹是声明性的。

@Bean用于显式声明单个bean,而不是像上面那样让Spring自动执行。它将bean的声明与类定义分离,并允许您根据自己的选择创建和配置bean。

回答你的问题...

  

是否可以重复使用@Component注释而不是引入@Bean注释?

当然可能;但他们选择不这样做,因为两者完全不同。春天已经足够混乱,没有进一步混淆水域。

答案 1 :(得分:256)

<强> @Component 优选用于元件扫描和自动布线。

什么时候应该使用 @Bean

有时自动配置不是一种选择。 什么时候?让我们假设您想要连接第三方库中的组件(您没有源代码,因此您无法使用@Component注释其类),因此无法自动配置。

@Bean 注释返回一个对象,spring应该在应用程序上下文中注册为bean。 方法主体承担了负责创建实例的逻辑。

答案 2 :(得分:147)

让我们考虑一下,我希望具体实现取决于某些动态状态。 private void TestGrid_CellValidating(object sender, DataGridViewCellValidatingEventArgs e) { int currentCell = TestGrid.CurrentCell.ColumnIndex; var oldValue = TestGrid[e.ColumnIndex, e.RowIndex].Value; var newValue = TestGrid[e.ColumnIndex, e.RowIndex].EditedFormattedValue; /* Perform some logic here*/ } 非常适合这种情况。

@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(); } } 无法做到这一点。

答案 3 :(得分:66)

这两种方法都旨在在Spring容器中注册目标类型。

区别在于/Users/john/.ssh/config适用于方法,而@Bean适用于类型

因此,当您使用@Component注释时,您可以控制方法体中的实例创建逻辑(请参阅example above)。使用@Bean注释,您不能。

答案 4 :(得分:46)

  1. @Component 自动检测并使用类路径扫描对其进行配置,而@Bean 明确声明为单个bean,而不是让Spring自动执行。
  2. @Component 不会从类定义中分离bean的声明,而@Bean 会从类定义中分离bean的声明
  3. @Component是类级别的注释,其中@Bean是方法级别的注释,方法的名称用作Bean名称。
  4. @Component 不需要与@Configuration 注释一起使用,因为@Bean注释必须在用@Configuration注释的类中使用。
  5. 如果该类在spring容器之外,我们不能使用@Component创建类的bean ,而即使使用,我们也可以使用类创建一个bean 该课程出现在弹簧容器之外
  6. @Component具有不同的专业化,例如@ Controller,@ Repository和@Service,而@Bean具有没有专业化

答案 5 :(得分:32)

@Component 这是一个通用注释,可以应用于应用程序的任何类,以使其成为Spring托管组件(简单来说,是任何Spring托管组件的通用构造型)。当通过spring的component-scan (@ ComponentScan)功能扫描类路径时,它将识别在给定包中带有 @Component 批注的类,并创建这些类的bean并在ApplicationContext中注册它们。 @Component 是一个类级别的注释,其目的是使该类成为spring托管组件和用于类路径扫描功能的自动检测bean。

如果您想进一步了解 @Component 和其他构造型注释,建议使用look at this article

@Bean 用于在方法返回的Spring IOC容器中显式声明和注册一个Bean(作为配置Bean)。 @Bean是方法级别的注释,它在用 @Configuration 注释的类中使用。只需使用 @Bean 批注将方法返回的Bean注册为IOC容器中的spring配置Bean。 @Bean 只是方法级别的注释,不能与类和对象声明一起使用。

@Bean 注释表示方法产生了一个应由Spring容器管理的bean。

要声明一个bean,只需使用 @Bean 注释对方法进行注释。当JavaConfig遇到这样的方法时,它将执行该方法并将返回值注册为ApplicationContext中的Bean。默认情况下,bean名称将与方法名称相同。以下是@Bean方法声明的简单示例。

@Configuration
public class ApplicationConfig {

    @Bean
    public User adminUserProfile() {
        return new User("Rami","Nassar");
    }
}

在ApplicationConfig类中,您可以看到我们首先使用 @Configuration 批注通知Spring这是一个基于Java的配置文件。之后, @Bean 批注用于声明Spring bean和DI需求。 @Bean 注释等效于 标记,方法名称等效于 标记内的id属性。 我希望阅读完本文后,您对 @Bean @Component 批注的实际用途和用法有了清晰的认识。

答案 6 :(得分:13)

当您使用@Component标记时,它与使用带有vanilla bean声明方法的POJO(Plain Old Java Object)相同(使用@Bean注释)。例如,以下方法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来获取&#39; theNumber&#39;:

@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:

@Bean
Integer theNumber(){
    return new Integer(3456);
}

@Bean
SomeClass someClass(Integer theNumber){
    return new SomeClass(theNumber);
}

方法2允许您将bean声明保持在一起,它更灵活等等。您甚至可能想要添加另一个非vanilla SomeClass bean,如下所示:

@Bean
SomeClass strawberryClass(){
    return new SomeClass(new Integer(1));
}

答案 7 :(得分:8)

Bean与组件之间的区别:

Difference between Bean and Component

答案 8 :(得分:4)

  • @component及其特化(@ Controller,@ service,@存储库)允许自动检测 使用类路径扫描。如果我们看到像@Controller这样的组件类,@ service,@ update将由spring框架使用组件扫描自动扫描。
  • 另一方面,
  • @Bean只能用于在配置类中显式声明单个bean。
  • @Bean用于显式声明单个bean,而不是让spring自动执行。它从类定义中创建了bean的septate声明。
  • 简而言之,@ Controller,@ service,@存储库用于自动检测,@ Bean用于从类创建seprate bean
    - @Controller
    public class LoginController 
    { --code-- }

    - @Configuration
    public class AppConfig {
    @Bean
    public SessionFactory sessionFactory() 
    {--code-- }

答案 9 :(得分:4)

您有两种生成bean的方法。   一种是用注解@Component创建一个类。   另一种是创建一个方法并用@Bean对其进行注释。对于那些包含方法@Bean的类,应使用@Configuration进行注释。   运行spring项目后,带有@ComponentScan批注的类将扫描带有@Component的每个类,并将该类的实例还原到Ioc容器。 @ComponentScan要做的另一件事是运行带有@Bean的方法,并将返回对象作为bean恢复到Ioc容器。  因此,当需要根据当前状态决定要创建哪种类型的bean时,需要使用@Bean。您可以编写逻辑并返回所需的对象。  值得一提的是,@Bean方法的名称是bean的默认名称。

答案 10 :(得分:2)

@Bean的创建是为了避免在编译时将Spring和您的业务规则耦合在一起。这意味着您可以在其他框架(如PlayFramework或JEE)中重用业务规则。

此外,您可以完全控制如何创建bean,而这在默认的Spring实例中还不够。

我写了一篇关于它的文章。

https://coderstower.com/2019/04/23/factory-methods-decoupling-ioc-container-abstraction/

答案 11 :(得分:2)

您可以使用@Bean使现有的第三方类可用于您的Spring框架应用程序上下文。

@Bean
public ViewResolver viewResolver() {

    InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();

    viewResolver.setPrefix("/WEB-INF/view/");
    viewResolver.setSuffix(".jsp");

    return viewResolver;
}

通过使用@Bean批注,您可以将第三方类(它可能没有@Component,并且可能不使用Spring)包装为Spring bean。然后,使用@Bean包装它之后,它就作为一个单例对象,可以在您的Spring框架应用程序上下文中使用。现在,您可以使用依赖项注入和@Autowired在应用程序中轻松共享/重用此bean。

因此,请注意@Bean注释是第三方类的包装器/适配器。您希望使第三方类可用于您的Spring框架应用程序上下文。

通过在上面的代码中使用@Bean,我明确声明了一个bean,因为在方法内部,我使用new关键字明确创建了对象。我还手动调用给定类的setter方法。因此,我可以更改前缀字段的值。因此,此手动工作称为显式创建。如果我将@Component用于同一类,则在Spring容器中注册的Bean将具有前缀字段的默认值。

另一方面,当我们用@Component注释一个类时,不需要我们手动使用new关键字。它由Spring自动处理。

答案 12 :(得分:1)

我看到了很多答案,几乎所有提到的@Component都是用于自动装配的,其中扫描了组件,而@Bean精确地声明该bean的使用方式不同。让我展示一下它的不同之处。

  • @Bean

首先是方法级别的注释。 其次,通常使用Java代码配置bean(如果不使用xml配置),然后使用  ApplicationContext的getBean方法。 像

 @Configuration
class MyConfiguration{
    @Bean
    public User getUser(){
        return new User();
    }
}

class User{
}



//Getting Bean 
User user = applicationContext.getBean("getUser");
  • @Component

这是注释bean而不是专用bean的通用方法。 类级别的注释,用于避免通过Java或xml配置进行的所有配置工作。

我们得到这样的东西。

@Component
class User {
}

//to get Bean
@Autowired
User user;

就是这样。引入它是为了避免实例化和使用该bean的所有配置步骤。

答案 13 :(得分:1)

1。关于@Component
@Component功能类似于@Configuration。

它们都表明带注释的类具有一个或多个bean,需要注册到Spring-IOC-Container

@Component注释的类,我们称之为Component of Spring。这个概念包含几个bean。

Spring需要对Component class进行自动扫描,以注册component class的那些bean。

2。关于@Bean
@Bean用于注释component-class的方法(如上所述)。它指示通过带注释的方法撤消的实例需要注册到Spring-IOC-Container

3。结论
两者之间的区别相对明显,它们用在different circumstances中。 常规用法是:

    // @Configuration is implemented by @Component
    @Configuration
    public ComponentClass {

      @Bean
      public FirstBean FirstBeanMethod() {
        return new FirstBean();
      }

      @Bean
      public SecondBean SecondBeanMethod() {
        return new SecondBean();
      }
    }

答案 14 :(得分:1)

以上答案中的附加点

假设我们有一个模块,该模块可以在多个应用程序中共享,并且其中包含一些服务。并非每个应用程序都需要全部。

如果在这些服务类上使用@Component并在应用程序中扫描组件,则

我们可能最终检测到的豆超过了必要

在这种情况下,您要么必须调整组件扫描的过滤,要么提供即使未使用的bean也可以运行的配置。否则,应用程序上下文将无法启动。

在这种情况下,最好使用@Bean批注并仅实例化那些bean,

每个应用中分别需要的

因此,从本质上讲,可以使用@Bean将第三方类添加到上下文中。还有@Component(如果它位于您的单个应用程序中)。

答案 15 :(得分:0)

@Component的意思是“导入”。

@Bean的意思是“导出”。