【问题标题】:Difference between @Bean and @Autowired@Bean 和 @Autowired 的区别
【发布时间】:2016-03-14 09:02:17
【问题描述】:

为什么在这种情况下我不能使用@Autowired

@SpringBootApplication
public class Application {

    @Autowired
    BookingService bookingService;

    public static void main(String[] args) {
        bookingService.book("Alice", "Bob", "Carol");
    }
}

但可以使用@Bean

@SpringBootApplication
public class Application {

    @Bean
    BookingService bookingService() {
        return new BookingService();
    }

    public static void main(String[] args) {
        ApplicationContext ctx = SpringApplication.run(Application.class, args);
        BookingService bookingService = ctx.getBean(BookingService.class);
        bookingService.book("Alice", "Bob", "Carol");
    }
}

这两种生成BookingService的方法不一样吗?

【问题讨论】:

  • Bean 注解用于在 Spring 上下文中注册您的 Bean,而 Autowried 注解用于从 Spring 应用程序内容中获取 Bean 并将其连接为另一个对象的依赖项
  • 您也应该提供 BookingService 类。因为如果那是用 Component 注释的,那么你的第一个类也可以像第二个一样工作。

标签: java spring dependency-injection


【解决方案1】:

@Bean@Autowired 做两件非常不同的事情。此处的其他答案解释得更详细,但更简单:

  • @Bean 告诉 Spring '这是这个类的一个实例,请保留它,当我问的时候把它还给我'。

  • @Autowired 说“请给我一个此类的实例,例如,我之前使用 @Bean 注释创建的实例”。

这有意义吗?在您的第一个示例中,您要求 Spring 给您一个 BookingService 的实例,但您从不创建一个实例,因此 Spring 没有什么可以给您。在您的第二个示例中,您正在创建一个 BookingService 的新实例,将其告知 Spring,然后在 main() 方法中请求返回。

如果您愿意,可以从第二个 main() 方法中删除另外两行,并将您的两个示例组合如下:

@SpringBootApplication
public class Application {

  @Autowired
  BookingService bookingService;

  @Bean
  BookingService bookingService() {
    return new BookingService();
  }

  public static void main(String[] args) {
    bookingService.book("Alice", "Bob", "Carol");
  }
}

在这种情况下,@Bean 注释为 Spring 提供了 BookingService@Autowired 使用它。

这将是一个毫无意义的示例,因为您在同一个类中使用它,但如果您将 @Bean 定义在一个类中,并将 @Autowired 定义在另一个类中,它会变得很有用。

【讨论】:

  • 不知何故,这个答案对我来说似乎只是部分正确。 Autowired 也可以调用带有@Components 注释的对象。此外,Autowired 不仅可用于对象的方法。
  • @PowerFlower,绝对正确,我的意思是解释问题上下文中的差异。当然,这两个注释都比较复杂,但我试图对这个具体示例给出一个简单、高级的解释。
  • 这个答案是错误的。不知道为什么它有这么多的赞成票。在大多数情况下,Bean 和 autowire 是可以互换的。在下面检查我的答案。
  • 那么在你的例子中,Bean和Autowired的执行顺序是Bean before Autowired?
  • @LiYingjun,你可以这么想,是的。我认为可以公平地说,任何带有@Bean 注释的方法都将在任何自动装配发生之前运行 - 这是必不可少的,因为 Spring 使用创建为@Beans 的对象(以及@Services、@Components 等) ) 注入到适当的@Autowired 目标中。
【解决方案2】:
@Bean
BookingService bookingService() {
    return new BookingService();
}

注释@Bean 仅将服务注册为spring 应用程序上下文中的bean(一种对象)。简单来说就是注册而已。

@Autowired
BookingService bookingService;

使用 @Autowired 注释变量会从 Spring 应用程序上下文中注入 BookingService bean(即对象)。

(即)带有@Bean注解的注册bean将被注入到带有@Autowired注解的变量中。

希望这能消除您的疑虑!

【讨论】:

  • 但是如果我用 @Autowired 注入 BookingService ,我将无法使用 BookingService 的功能
  • 现在我知道这是因为在 main() 中出现错误“将 book() 的修饰符更改为 static”,我可以在其他函数中使用 BookingService 的对象。但我不知道为什么跨度>
  • @zhuochenshen 我不确定你的课程和当前的问题是什么。我只回答了你的“差异”问题。您可以针对下一个问题发布另一个问题。
  • I.E,registered bean with @Bean will be inject to the variable annotated with @Autowired. 这一行是这两个注解的本质。
【解决方案3】:

@DaveyDaveDave 的精彩回答 在示例中,而不是

@Bean
  BookingService bookingService() {
    return new BookingService();
  }

您可以在 BookingService 类上使用 @Service 注解

【讨论】:

    【解决方案4】:

    这里有一篇关于@Autowired注解的好文章:http://www.baeldung.com/spring-autowire

    @Autowired 注解可以通过在配置类上定义@ComponentScan("namespace.with.your.components.for.inject") 来实例化你的注入

    @Configuration
    @ComponentScan("com.baeldung.autowire.sample")
    public class AppConfig {}
    

    所有组件必须用@Component注解标记。它替换了@Bean 注释。

    【讨论】:

      【解决方案5】:

      与此处投票最高的答案所声称的相反,它们不是两个截然不同的东西。 @Bean 和 @Autowired 在大多数情况下可以互换。

      假设您有一个返回 Car 实例的 @Bean 方法。您可以从字面上摆脱该 bean 方法并在 Car 类上添加 @Component 然后自动装配它。

      反之亦然。无论您使用@Autowired 实例化了什么类,您都可以在方法上使用@Bean 使用@Configuration 注解在一个类中实例化它。

      您将使用@Bean 而不是@Autowired 的地方

      1>您无权更改类以添加@Component 注解,因此您无法自动装配它。

      2>您想自定义类的实例化。

      例如,如果您要实例化 Resilience4J 断路器类,如果您在使用 @Bean 的方法中执行此操作,则可以选择使用这样的代码设置所有配置

      @Bean
      public CircuitBreaker fooCircuitBreaker() {
          CircuitBreakerConfig.Builder builder = CircuitBreakerConfig.custom().
                  slidingWindowSize(xxx).
                  failureRateThreshold(xxx).
                  waitDurationInOpenState(xxx)).
                  ignoreException(e -> {
                      if (e instanceof HttpStatusCodeException) {
                          HttpStatusCodeException httpStatusCodeException = (HttpStatusCodeException) e;
                          if (httpStatusCodeException.getStatusCode().is4xxClientError()) {
                              return true;
                          }
                      }
                      return false;
                  });
          circuitBreakerRegistry.addConfiguration(xxx, builder.build());
          return circuitBreakerRegistry.circuitBreaker(xxx, xxx);
      }
      

      【讨论】:

      • 对不起,我认为你错了。也许你误解了我所说的“非常不同”的意思,也许“同一枚硬币的两个面”更合适。但可以肯定的是,它们不可互换。 @Bean@Component (在某种程度上)可以互换,因为它们都注册了 bean,但 @Autowired 没有注册 bean。如果您有一个可以互换使用它们的示例,那么也许可以编辑您的答案以包含它?
      • @DaveyDaveDave 如果您订阅了复数视力,请观看 Bryan Hansen 的春季基础课程。在本教程中,他首先使用 Bean 注释连接 bean,然后他介绍了 Autowired 注释,他摆脱了 Bean 注释。 app.pluralsight.com/library/courses/…
      • 对,但是那些@Autowired 注释与被删除的@Bean 注释完全不同,对吧?因为它们不可互换。他们是不同的。它们实现了类似的事情,因为它们提供了依赖注入功能,但它们执行不同的工作。同样,用非常简单的术语 - @Bean 向 Spring 注册一个对象,@Autowired 告诉 Spring 在哪里使用它。
      【解决方案6】:

      @Bean 仅用于创建 bean 的元数据定义(相当于标记)。 @Autowired 是将依赖注入到一个bean中(相当于ref XML标签/属性)。

      【讨论】:

        猜你喜欢
        • 2019-05-06
        • 2011-11-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多