@Bean和@Autowired之间的区别

zhu*_*hen 56 java spring dependency-injection

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

@SpringBootApplication
public class Application {

    @Autowired
    BookingService bookingService;

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

但可以使用 @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");
    }
}
Run Code Online (Sandbox Code Playgroud)

是不是两种方式生成BookingService相同的东西?

Dav*_*ave 139

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

在这种情况下,@Bean注释给Spring BookingService,并@Autowired使用它.

这将是一个稍微毫无意义的例子,因为你在同一个类中使用它,但是如果你@Bean在一个类中定义了它,而在另一个类中定义了它,它就会变得有用@Autowired.

  • @PowerFlower,绝对正确,我的观点是解释问题背景的差异.当然,两个注释都有更多的复杂性,但我试图给出这个具体例子的简单,高级解释. (4认同)
  • 不知何故,这个答案对我来说似乎只是部分正确。Autowired 也可以调用用@Components 注释的对象。此外,Autowired 不仅可以用于对象,还可以用于方法。 (2认同)

pmv*_*rma 10

@Bean
BookingService bookingService() {
    return new BookingService();
}
Run Code Online (Sandbox Code Playgroud)

注释@Bean仅在Spring应用程序上下文中将服务注册为bean(一种Object).简单来说,它只是注册而不是别的.

@Autowired
BookingService bookingService;
Run Code Online (Sandbox Code Playgroud)

通过从Spring Application Context @Autowired注入BookingServicebean(即Object)来注释变量.

(即)带@Bean注释的已注册bean 将注入带注释的变量@Autowired.

希望这清除你的怀疑!


dev*_*747 7

与这里投票最高的答案所声称的相反,它们并不是两个截然不同的东西。@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);
}
Run Code Online (Sandbox Code Playgroud)

  • 抱歉,但我认为你错了。也许你误解了我所说的“非常不同”的意思,也许“同一枚硬币的两面”更合适。但可以肯定的是,它们是不可互换的。“@Bean”和“@Component”(在某种程度上)可以互换,因为它们都注册 bean,但“@Autowired”不注册 bean。如果您有一个可以互换使用它们的示例,那么也许可以编辑您的答案以包含它? (5认同)
  • 是的,但是这些“@Autowired”注释与被删除的“@Bean”注释位于完全不同的位置,对吧?因为它们不可互换。他们是不同的。它们实现了类似的事情,因为它们提供依赖注入功能,但它们执行不同的工作。同样,用非常简单的术语来说 - `@Bean` 向 Spring 注册一个对象,`@Autowired` 告诉 Spring 在哪里使用它。 (2认同)

Kri*_*wat 5

@DaveyDaveDave的很好答案在示例中,而不是

@Bean
  BookingService bookingService() {
    return new BookingService();
  }
Run Code Online (Sandbox Code Playgroud)

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