@Bean和@Autowired之间的区别


77

为什么@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同一事物的两种方式不是吗?


11
Bean批注用于在Spring上下文中注册您的Bean,而Autowried批注用于从Spring应用程序内容中获取Bean并将其作为另一个对象的依赖关系进行布线
prem kumar

您也应该提供BookingService类。因为如果用Component注释,则您的第一个类也将像第二个类一样工作。
PowerFlower

Answers:


172

@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


1
不知何故,该答案对我而言仅部分正确。自动装配还可以调用带@Components注释的对象。此外,“自动装配”不仅可以用于对象,还可以用于“方法”。
PowerFlower

7
@PowerFlower,绝对正确,我的意思是解释问题的不同之处。当然,两个注释中都存在更多的复杂性,但是我试图针对此特定示例给出一个简单的高级解释。
DaveyDaveDave

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

注释@Bean仅在Spring应用程序上下文中将服务注册为bean(一种Object)。简而言之,它只是注册而已。

@Autowired
BookingService bookingService;

使用注释变量会从Spring Application Context@Autowired注入一个BookingServicebean(即Object)。

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

希望这能消除您的疑问!


但是如果我通过@Autowired注入BookingService,就无法使用BookingService的功能
zhuochen shen 2015年

现在我知道这是因为在main()中出现错误“将book()的修饰符更改为静态”,可以在其他函数中使用BookingService的对象。但是我不知道为什么
zhuochen shen

@zhuochenshen我不确定您的课程内容和当前问题是什么。我只回答了您的“差异”问题。您可以针对下一个问题发布另一个问题。
pmverma 2015年

1
I.E,registered bean with @Bean will be inject to the variable annotated with @Autowired.事实证明,这条线是这两个注释所涉及的全部内容。
Mikayil Abdullayev'17年

5

@DaveyDaveDave的一个很好的答案在示例而不是

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

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


2

这是有关@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注释。


0

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


0

无论使用@Autowire实例化的任何类,都可以在方法上使用@Bean在带有@Configuration批注的类中实例化该类。

@Autowire和@Bean都是初始化Class实例的方法。

区别在于,如果使用@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);
}

在这种情况下,使用@Bean显然是更好的方法。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.