“ Bean”与“ Autowired”的区别

为什么我不能在这种情况下使用 @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的方法不是一回事吗?

103706 次浏览
@Bean
BookingService bookingService() {
return new BookingService();
}

注释 @Bean只在 Spring 应用程序上下文中将服务注册为 bean (类似于 Object)。简而言之,这只是注册,没有别的。

@Autowired
BookingService bookingService;

@Autowired注释变量会从 Spring Application Context 注入一个 BookingService bean (即对象)。

(即)使用 @Bean注释的注册对象将被注入到使用 @Autowired注释的变量中。

希望这能消除你的疑虑!

@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,那么它将变得非常有用。

@ DaveyDaveDave 的回答很棒 In the example instead of

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

可以在 BookingService 类上使用@Service 注释

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

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

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

All components must be marked by @Component annotation. It replaces the @Bean annotation.

@Bean is just for the metadata definition to create the bean(equivalent to tag). @Autowired is to inject the dependancy into a bean(equivalent to ref XML tag/attribute).

与这里投票最多的答案所声称的相反,他们并不是两个完全不同的东西。@ Bean 和@Autowired 在大多数情况下是可互换的。

假设您有一个@Bean 方法,它返回一个 Car 的实例。您可以简单地去掉 bean 方法,在 Car 类上添加@Component,然后自动装配它。

反之亦然。无论您使用@Autowired 实例化了哪个类,您都可以在具有@Configuration 注释的类中使用方法上的@Bean 实例化它。

使用“ 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);
}