Sự khác biệt giữa @Bean và @Autowosystem


79

Tại sao tôi không thể sử dụng @Autowiredtrong trường hợp này?

@SpringBootApplication
public class Application {

    @Autowired
    BookingService bookingService;

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

nhưng có thể sử dụng @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");
    }
}

Không phải là hai cách để tạo ra BookingServicecùng một thứ?


11
Bean chú thích là đăng ký đậu của bạn trong bối cảnh mùa xuân trong khi Autowried chú thích là để nhận được đậu từ nội dung ứng dụng lò xo và dây nó như là một sự phụ thuộc cho một đối tượng khác
Prem Kumar

Bạn cũng nên cung cấp lớp BookingService. Bởi vì nếu điều đó được chú thích bằng Thành phần thì lớp đầu tiên của bạn cũng sẽ hoạt động giống như lớp thứ hai.
PowerFlower

Câu trả lời:


178

@Bean@Autowiredlàm hai điều rất khác nhau. Các câu trả lời khác ở đây giải thích chi tiết hơn một chút, nhưng ở cấp độ đơn giản hơn:

  • @Bean nói với Spring "đây là một ví dụ của lớp này, hãy giữ nó và trả lại cho tôi khi tôi hỏi".

  • @Autowirednói 'làm ơn cho tôi một ví dụ của lớp này, ví dụ, một phiên bản mà tôi đã tạo bằng @Beanchú thích trước đó'.

Điều đó có ý nghĩa? Trong ví dụ đầu tiên của bạn, bạn đang yêu cầu Spring cung cấp cho bạn một ví dụ BookingService, nhưng bạn không bao giờ tạo một ví dụ , vì vậy Spring không có gì để cung cấp cho bạn. Trong ví dụ thứ hai của bạn, bạn đang tạo một phiên bản mới BookingService, nói với Spring về nó và sau đó, trong main()phương thức, yêu cầu nó trở lại.

Nếu bạn muốn, bạn có thể xóa hai dòng bổ sung khỏi main()phương pháp thứ hai và kết hợp hai ví dụ của bạn như dưới đây:

@SpringBootApplication
public class Application {

  @Autowired
  BookingService bookingService;

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

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

Trong trường hợp này, @Beanchú thích mang lại cho Spring BookingService@Autowiredviệc sử dụng nó.

Đây sẽ là một ví dụ hơi vô nghĩa, vì bạn đang sử dụng tất cả nó trong cùng một lớp, nhưng nó sẽ hữu ích nếu bạn có @Beanđịnh nghĩa trong một lớp và @Autowiredtrong một lớp khác.


1
Bằng cách nào đó mà câu trả lời xuất hiện chỉ đúng một phần đối với tôi. Tự động hóa cũng có thể gọi các Đối tượng được chú thích bằng @Components. Hơn nữa Tự động tìm kiếm có thể được sử dụng cho các Phương thức không chỉ cho các đối tượng.
PowerFlower

7
@PowerFlower, hoàn toàn đúng, quan điểm của tôi ở đây là giải thích sự khác biệt trong ngữ cảnh của câu hỏi. Chắc chắn là có nhiều sự phức tạp hơn trong cả hai chú thích, nhưng tôi đang cố gắng đưa ra một lời giải thích đơn giản, cấp cao cho ví dụ cụ thể này.
DaveyDaveDave

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

Chú thích @Beanchỉ đăng ký dịch vụ dưới dạng bean (loại Đối tượng) trong ngữ cảnh ứng dụng mùa xuân. Nói cách đơn giản, nó chỉ là đăng ký và không có gì khác.

@Autowired
BookingService bookingService;

Chú thích một biến có @Autowiredchèn một BookingServicebean (tức là Đối tượng) từ Spring Application Context.

(tức là) bean đã đăng ký với @Beanchú thích sẽ được đưa vào biến được chú thích bằng @Autowired.

Hy vọng điều này xóa nghi ngờ của bạn!


nhưng tôi không thể sử dụng dịch vụ của BookingService nếu tôi đưa BookingService với @Autowosystem
zhuochen shen

Bây giờ tôi biết đó là vì trong main () tôi đã nhận lỗi "thay đổi sửa đổi của cuốn sách () để tĩnh", tôi có thể sử dụng đối tượng BookingService trong functions.But khác tôi không lý do tại sao
zhuochen shen

@zhuochenshen Tôi không rõ vấn đề hiện tại và lớp học bên trong của bạn là gì. Tôi chỉ trả lời câu hỏi "sự khác biệt" của bạn. Bạn có thể đăng một câu hỏi khác liên quan đến vấn đề tiếp theo của bạn.
pmverma

1
I.E,registered bean with @Bean will be inject to the variable annotated with @Autowired.Dòng này hóa ra là bản chất của tất cả những gì hai chú thích này nói về.
Mikayil Abdullayev

5

câu trả lời tuyệt vời của @DaveyDaveDave Trong ví dụ thay vì

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

Bạn có thể sử dụng chú thích @Service trên lớp BookingService


2

Đây là bài viết hay về chú thích @Autowords: http://www.baeldung.com/spring-autowire

Chú thích @Autow mong muốn có thể khởi tạo các tệp có thể tiêm của bạn bằng cách xác định @ComponentScan ("namespace.with.your.components.for.inject") trên lớp cấu hình

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

Tất cả các thành phần phải được đánh dấu bằng chú thích @Component. Nó thay thế chú thích @Bean.


0

@Bean chỉ dành cho định nghĩa siêu dữ liệu để tạo bean (tương đương với thẻ). @Autowosystem là đưa sự phụ thuộc vào một bean (tương đương với thẻ / thuộc tính ref XML).


0

Bất kỳ lớp nào bạn đã khởi tạo bằng @Autowire, bạn có thể khởi tạo nó bên trong một lớp với chú thích @Configuration bằng cách sử dụng @Bean trên phương thức.

Cả @Autowire và @Bean đều là cách khởi tạo các thể hiện của Lớp.

Sự khác biệt là nếu bạn sử dụng @Bean để khởi tạo một lớp, bạn có nhiều quyền kiểm soát hơn đối với việc khởi tạo. Ví dụ: nếu bạn đang khởi tạo một lớp bộ ngắt mạch Resilience4J, nếu bạn làm điều đó bên trong một phương thức với @Bean, bạn có tùy chọn đặt tất cả cấu hình bằng cách sử dụng mã như thế này

@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);
}

Trong trường hợp như thế này, sử dụng @Bean rõ ràng là một cách tốt hơn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.