关于java:Spring:@Component vs @Bean

Spring: @Component versus @Bean

我知道在Spring2.5中引入了@Component注释,以便通过类路径扫描消除XML bean定义。

EDCOX1 1在3中引入,并可与EDCOX1 2使用,以完全摆脱XML文件,而使用Java CONFIG代替。

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


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

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

@Bean用于显式声明单个bean,而不是像上面那样让spring自动声明。它将bean的声明从类定义中分离出来,并允许您准确地创建和配置bean。

回答你的问题…

would it have been possible to re-use the @Component annotation instead of introducing @Bean annotation?

当然,可能吧,但他们选择了不去,因为这两种情况完全不同。春天已经够混乱了,但不会把水弄得更浑浊。


@组件最好用于部件扫描和自动布线。

什么时候应该使用@bean?

有时自动配置不是一个选项。什么时候?假设您想要连接来自第三方库的组件(您没有源代码,因此不能用@component注释其类),因此无法进行自动配置。

@bean注释返回一个对象,spring应该在应用程序上下文中注册为bean。方法体具有创建实例的逻辑。


让我们考虑一下,我希望具体的实现取决于某种动态状态。@Bean非常适合这种情况。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@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();
    }
}

然而,没有办法用@Component来做到这一点。


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

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

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


  • @组件使用类路径扫描自动检测和配置bean,而@bean显式声明单个bean,而不是让spring自动执行。
  • @组件不会将bean的声明与类定义分离,因为@bean会将bean的声明与类定义分离。
  • @组件是一个类级注释,其中as@bean是一个方法级注释,方法的名称作为bean名称。
  • @组件不需要与@configuration注释一起使用,因为@bean注释必须在用@configuration注释的类中使用。
  • 如果类在Spring容器外,我们不能使用@component创建类的bean,而即使类在Spring容器外,我们也可以使用@bean创建类的bean。
  • @组件有不同的专门化,如@controller、@repository和@service,而@bean没有专门化。

  • @组件这是一个通用注释,可以应用于应用程序的任何类,使其成为一个Spring管理的组件(简单地说,任何Spring管理的组件的通用原型)。当类路径被spring的component scan(@componentscan)功能扫描时,它将识别用@component annotation注释的类(在给定的包中),并创建这些类的bean并在applicationContext中注册它们。@组件是一个类级的注释,其目的是使类成为Spring管理组件和类路径扫描功能的自动检测bean。

    如果您想了解关于@component和其他构造型注释的更多信息,建议阅读本文。

    @bean用于显式声明和注册从方法返回的SpringIOC容器中的bean(作为配置bean)。@bean是一个方法级的注释,它在用@configuration注释的类中使用。简单地说,@bean注释用于将方法返回的bean注册为ioc容器中的Spring配置bean。@bean只是一个方法级注释,不能与类和对象声明一起使用。

    @bean注释指示一个方法生成一个bean,该bean应该由Spring容器管理。

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

    1
    2
    3
    4
    5
    6
    7
    8
    @Configuration
    public class ApplicationConfig {

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

    在AppultCyFig类中,您可以看到我们首先使用@配置注释来通知Spring这是一个基于Java的配置文件。然后,@bean注释用于声明SpringBean和DI需求。@bean注释等价于标记,方法名等价于标记内的id属性。我希望在阅读本文之后,您对@bean和@component注释的真正用途和使用有了一个清晰的了解。


    当使用EDCOX1的0个标记时,它与波霍(普通的Java对象)和香草bean声明方法相同(用EDCOX1(1)表示注释)。例如,下面的方法1和2将给出相同的结果。

    方法1

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    @Component
    public class SomeClass {

        private int number;

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

        public int getNumber(){
            return this.number;
        }
    }

    用豆子做"thenumber":

    1
    2
    3
    4
    @Bean
    Integer theNumber(){
        return new Integer(3456);
    }

    方法2

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    //Note: no @Component tag
    public class SomeClass {

        private int number;

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

        public int getNumber(){
            return this.number;
        }
    }

    两者都有豆子:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    @Bean
    Integer theNumber(){
        return new Integer(3456);
    }

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

    方法2允许您将bean声明放在一起,它更灵活一些,等等。您甚至可能希望添加另一个非普通的类bean,如下所示:

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

    • @组件及其专门化(@controller、@service、@repository)允许自动检测使用类路径扫描。如果我们看到像@controller、@service、@repository这样的组件类,那么Spring框架将使用组件扫描自动扫描@repository。
    • @另一方面,bean只能用于在配置类中显式声明单个bean。
    • @bean用于显式地声明单个bean,而不是让spring自动执行它。它从类定义中生成bean的septate声明。
    • 简而言之,@controller,@service,@repository用于自动检测,@bean用于从类中创建单独的bean
    1
    2
    3
    4
    5
    6
    7
    8
    9
        - @Controller
        public class LoginController
        { --code-- }

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

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


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

    此外,您可以完全控制如何创建bean,而缺省的Spring实例化还不够。

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

    Factory Methods: Decoupling the IoC Container from the Abstraction