Java @Bean和@Autowired之间的区别

Java @Bean和@Autowired之间的区别,java,spring,dependency-injection,Java,Spring,Dependency Injection,为什么我不能在这种情况下使用@Autowired @SpringBootApplication public class Application { @Autowired BookingService bookingService; public static void main(String[] args) { bookingService.book("Alice", "Bob", "Carol"); } } 但是可以使用@Bean @Sp

为什么我不能在这种情况下使用
@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
BookingService bookingService() {
    return new BookingService();
}
注释
@Bean
仅将服务注册为spring应用程序上下文中的Bean(对象类型)。简单地说,这只是注册而已

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

(即)带有
@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

由@daveydave提供的很好的答案,那么它会变得很有用 在示例中,而不是

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

您可以在BookingService类上使用@Service annotation

这里有一篇关于
@Autowired
注释的好文章:

通过在config类上定义
@ComponentScan(“namespace.with.your.components.for.inject”)
,自动连线的
@Autowired
注释可以实例化可注入项

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

所有组件必须用
@Component
注释进行标记。它取代了
@Bean
注释。

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

@Autowired和@bean都是注册Springbean的方法

与投票率最高的答案所宣称的相反,它们并不是两件完全不同的事情@Bean和@Autowired在大多数情况下是可互换的。(更多信息请参见下文)

假设有一个@Bean方法返回一个Car实例。您可以直接去掉该bean方法,在Car类上添加@Component,然后自动连接它

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

不同之处在于,如果您使用@Bean实例化一个类,那么您可以更好地控制初始化。例如,如果您正在实例化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);
}
在大多数情况下,@Autowired(和@Component)工作得非常好。
@豆子只是偶尔需要。通常是因为您无权更改类以向其添加@Component注释,或者因为您需要对类的初始化有更多的控制。

Bean注释用于在spring上下文中注册Bean,而Autowried注释用于从spring应用程序内容获取Bean并对其进行连接作为另一个对象的依赖项,您也应该提供BookingService类。因为如果使用组件对其进行注释,那么您的第一个类也会像第二个类一样工作。但是,如果我将BookingService与@AutowiredNow一起注入BookingService,则我无法使用BookingService的功能。我知道这是因为在main()中,我出现了错误“将book()的修饰符更改为static”,我可以在其他函数中使用BookingService的对象,但我不能why@zhuochenshen我不知道你们班里有什么,也不知道现在的问题。我只回答了你的“不同”问题。关于下一个问题,您可以发布另一个问题。
即,使用@bean注册的bean将被注入到使用@Autowired注释的变量。
这一行是这两个注释的精髓所在。不知怎的,这个答案对我来说似乎只是部分正确。Autowired还可以调用带有@Components注释的对象。此外,Autowired不仅可以用于对象,还可以用于方法。@PowerFlower,绝对正确,我在这里的目的是解释问题上下文中的差异。当然,这两种注释都要复杂得多,但我试图对这个具体的例子给出一个简单、高层次的解释。这个答案是错误的。不知道为什么会有这么多人投票。Bean和autowire在大多数情况下是可互换的。检查我下面的答案。对不起,我认为你错了。也许你误解了我所说的“非常不同”的意思,也许“同一枚硬币的两面”更合适。但毫无疑问,它们是不能互换的
@Bean
@Component
可以互换,因为它们都注册Bean,但是
@Autowired
不注册Bean。如果您有一个可以互换使用它们的示例,那么可以将您的答案编辑为incl