Spring:@Component与@Bean

use*_*576 387 java spring annotations autowired

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

@Bean是在3.0版本中引入的,可以用来@Configuration完全摆脱xml文件并使用java配置.

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

ska*_*man 388

@Component@Bean做两个完全不同的事情,不应该混为一谈.

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

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

回答你的问题......

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

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

  • 现在我理解了这个概念(从阅读其他人的答案),你的解释是有道理的.这告诉我,你的解释对于那些尚未理解这些概念的人来说并不好. (9认同)
  • 对不起,但我无法理解你的解释.您清楚地了解这一点,请您写一个明确的解释或指向相应的文档? (5认同)
  • 所以我只能在需要自动装配时使用`@ Component`?似乎`@ Bean`不能影响`@Autowired` (3认同)
  • 将'@component'用于基于服务的类,将'@Bean'作为工厂定制的对象,例如jdbc数据源 (2认同)
  • @Jaskey你可以使用`@Autowired`和`@ Bean`,如果你用`@Configuration注释你的bean类 (2认同)
  • 看起来“Dan Vega”喜欢你的回答,因为他在他的网站上复制了确切的措辞!https://therealdanvega.com/blog/2017/05/17/spring-component-vs-bean (2认同)

Mag*_*GGG 341

@Component优先 用于元件扫描和自动布线.

什么时候应该使用@Bean

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

所述@Bean注释返回一个对象该弹簧应在应用程序上下文豆注册.方法主体承担负责创建实例的逻辑.

  • 我陷入了困境,直到我读到“如果你没有源代码怎么办”?然后,卡布拉姆!当然,如果您拥有源代码,则可以使用“@Component”,但如果您想要组件化没有源代码的其他类,则可以使用“@Bean”。我确信还有其他差异,但女士们先生们,这一点是最重要的。 (5认同)
  • 我认为这是最合理的。如果我理解正确,`@ Component`会自己处理类,而`@ Bean`会处理类方法(产生类对象的实例)。 (3认同)
  • @ajaysinghnegi,这里“源代码不可用”意味着,您没有可编辑的源代码,但可以将其用作外部库或依赖项。 (2认同)

out*_*dev 159

让我们考虑一下我需要具体的实现,具体取决于一些动态状态. @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();
    }
}
Run Code Online (Sandbox Code Playgroud)

然而,没有办法做到这一点@Component.

  • @PowerFlower 这个方法应该在配置类中,用`@Configuration`注释 (10认同)
  • 你怎么称呼那个示例课程? (3认同)

Nur*_*yev 80

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

区别在于@Bean适用于方法,而@Component适用于类型.

因此,当您使用@Bean注释时,您可以控制方法体中的实例创建逻辑(请参阅上面的示例).有了@Component注释,你不能.


小智 73

  1. @Component 使用类路径扫描自动检测和配置bean,而@Bean 显式声明一个bean,而不是让Spring自动执行.
  2. @Component 不会将 bean的声明与类定义分离,因为@Bean bean的声明与类定义分离.
  3. @Component是类级别注释,其中@Bean是方法级别注释,方法名称用作bean名称.
  4. @Component 不需要与@Configuration注释一起使用,因为@Bean注释必须在使用@Configuration注释的类中使用.
  5. 我们不能创建一个bean使用@Component一类,如果类是外spring容器,而我们可以创建一个bean使用@Bean即使类是存在的一类Spring容器外.
  6. @Component具有不同的特性,如@ Controller,@ Repository和@Service,而@Bean 没有特化.

  • 4. 实际上@Bean 可以在非配置类中声明。它被称为精简模式 (7认同)

Som*_*Guy 15

当您使用@Component标记时,它与具有vanilla bean声明方法(带注释@Bean)的POJO(Plain Old Java Object)相同.例如,以下方法1和2将给出相同的结果.

方法1

@Component
public class SomeClass {

    private int number;

    public SomeClass(Integer theNumber){
        this.number = theNumber.intValue();
    }

    public int getNumber(){
        return this.number;
    }
}
Run Code Online (Sandbox Code Playgroud)

用'theNumber'的豆子:

@Bean
Integer theNumber(){
    return new Integer(3456);
}
Run Code Online (Sandbox Code Playgroud)

方法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;
    }
}
Run Code Online (Sandbox Code Playgroud)

与两者的豆:

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

@Bean
SomeClass someClass(Integer theNumber){
    return new SomeClass(theNumber);
}
Run Code Online (Sandbox Code Playgroud)

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

@Bean
SomeClass strawberryClass(){
    return new SomeClass(new Integer(1));
}
Run Code Online (Sandbox Code Playgroud)


Par*_*tho 13

Spring支持@Component、@Service、@Repository等多种类型注解。所有这些都可以在 org.springframework.stereotype 包下找到。

@Bean可以在org.springframework.context.annotation包下找到。

当我们应用程序中的类使用上述任何注释进行注释时,然后在项目启动期间 spring 扫描(使用 @ComponentScan)每个类并将类的实例注入 IOC 容器。@ComponentScan 要做的另一件事是运行带有 @Bean 的方法,并将返回对象作为 bean 恢复到 Ioc 容器。

@成分

如果我们用 @Component 或其他 Stereotype 注释之一标记一个类,这些类将使用类路径扫描自动检测。只要这些类位于我们的基础包下或者 Spring 知道要扫描另一个包,就会为每个类创建一个新的 bean。

package com.beanvscomponent.controller;

import org.springframework.stereotype.Controller;

@Controller
public class HomeController {

    public String home(){
       return "Hello, World!";
   }

 }
Run Code Online (Sandbox Code Playgroud)

带注释的类和 bean 之间存在隐式的一对一映射(即每个类一个 bean)。这种方法的接线控制非常有限,因为它纯粹是声明性的。还需要注意的是,构造型注释是类级别注释。

@豆

@Bean 用于显式声明单个 bean,而不是像我们使用 @Controller 那样让 Spring 自动执行此操作。它将 bean 的声明与类定义分离,并允许您准确地按照您选择的方式创建和配置 bean。使用@Bean,您不会将此注释放置在类级别。如果您尝试这样做,您将收到无效类型错误。@Bean 文档将其定义为:

Indicates that a method produces a bean to be managed by the Spring container.
Run Code Online (Sandbox Code Playgroud)

通常,@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;
   }
}
Run Code Online (Sandbox Code Playgroud)

正如我之前提到的,@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");
   }

}
Run Code Online (Sandbox Code Playgroud)

该方法的名称实际上就是我们 bean 的名称。如果我们在执行器中拉出 /beans 端点,我们可以看到定义的 bean。

{
"beans": "superUser",
"aliases": [],
"scope": "singleton",
"type": "com.beanvscomponent.User",
"resource": "class path resource 
    [com/beanvscomponent/ApplicationConfig.class]",
"dependencies": []
}
Run Code Online (Sandbox Code Playgroud)

@Component 与 @Bean

在此输入图像描述

我希望这能够澄清一些关于何时使用 @Component 以及何时使用 @Bean 的问题。这可能有点令人困惑,但是当您开始编写更多应用程序时,它会变得非常自然。


xpi*_*eer 12

我看到了很多答案,几乎所有提到的@Component都是用于自动装配的,用于在扫描组件的地方进行自动装配,而@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");
Run Code Online (Sandbox Code Playgroud)
  • @零件

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

我们得到这样的东西。

@Component
class User {
}

//to get Bean
@Autowired
User user;
Run Code Online (Sandbox Code Playgroud)

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

  • 我认为当您使用“@Bean”方法时,没有必要从ApplicationContext获取User对象。您仍然可以使用“@Autowire”来获取 bean,就像使用“@Component”一样。`@Bean` 只是将 Bean 添加到 Spring 容器,就像 `@Component` 一样。差异如下。1. 使用`@Bean`,您可以将第三方类添加到Spring容器中。2.使用`@Bean`,您可以在运行时获得所需的接口实现(使用工厂设计模式) (21认同)

Aza*_*rEJ 11

Bean和组件的区别:

Bean 和组件的区别

  • 对于第 3 方库,我认为 @Bean 是可能的,因为 @Bean 不需要类定义存在于 Spring 容器内,相反,在这种情况下 @Component 是不可能的。 (5认同)

elv*_*vis 10

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

@Bean
public ViewResolver viewResolver() {

    InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();

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

    return viewResolver;
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

  • 如果这个答案也能用一个如何使用该 bean 的例子来更新,那就太好了 (2认同)

Dai*_*Niu 8

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


小智 6

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

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

我写了一篇文章谈论它。

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


alo*_*lok 5

  • @component及其特长(@ Controller,@ service,@ repository)允许使用类路径扫描进行自动检测。如果我们看到像@Controller,@service,@repository这样的组件类,Spring框架会使用组件扫描来自动扫描@repository。
  • 另一方面,@Bean仅可用于在配置类中显式声明单个bean。
  • @Bean用于显式声明单个bean,而不是让spring自动执行。它从类定义中使bean分开声明。
  • 简而言之,@ Controller,@ service,@ repository用于自动检测,@ Bean用于创建与类分离的bean
    -@Controller
    公共类LoginController 
    {--code--}

    -@配置
    公共类AppConfig {
    @豆
    公共SessionFactory sessionFactory() 
    {--code--}


Aza*_*rEJ 5

上述答案的补充要点

\n\n

让\xe2\x80\x99s 说我们有一个在多个应用程序中共享的模块,并且它包含一些服务。并非每个应用程序都需要所有内容。

\n\n

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

\n\n
\n

我们最终可能会检测到不必要的豆子

\n
\n\n

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

\n\n

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

\n\n
\n

每个应用程序都需要单独的

\n
\n\n

因此,本质上,使用 @Bean 将第三方类添加到上下文中。如果它就在您的单个应用程序中,则@Component 。

\n