Mùa xuân: @Component so với @Bean


459

Tôi hiểu rằng @Componentchú thích đã được giới thiệu vào mùa xuân 2.5 để loại bỏ định nghĩa xml bean bằng cách sử dụng quét classpath.

@Beanđã được giới thiệu vào mùa xuân 3.0 và có thể được sử dụng @Configurationđể loại bỏ hoàn toàn tệp xml và sử dụng cấu hình java thay thế.

Có thể sử dụng lại @Componentchú thích thay vì giới thiệu @Beanchú thích không? Hiểu biết của tôi là mục tiêu cuối cùng là tạo ra đậu trong cả hai trường hợp.


4
Có nơi nào @Bean có thể được sử dụng ngoài lớp Cấu hình không?
Willa


@Willa Vâng, có. Đó gọi là Lite mode. Và nó không được khuyến khích. Xem tại đây: docs.spring.io/spring/docs/civerse/spring-framework-reference/ mẹo
smwikipedia

9
Tôi tóm tắt nó nói rằng một phương thức @beantrả về một thể hiện của bean mùa xuân có thể tùy chỉnh, trong khi @componentđịnh nghĩa một lớp có thể được kích hoạt sau bởi công cụ IoC mùa xuân khi cần.
Sebas

Câu trả lời:


433

@Component@Beanlàm hai việc khá khác nhau, và không nên nhầm lẫn.

@Component(và @Service@Repository) được sử dụng để tự động phát hiện và tự động định cấu hình các bean bằng cách sử dụng quét đường dẫn lớp. Có một ánh xạ một-một ngầm định giữa lớp chú thích và bean (tức là một bean cho mỗi lớp). Kiểm soát hệ thống dây điện khá hạn chế với phương pháp này, vì nó hoàn toàn là khai báo.

@Beanđược sử dụng để khai báo một cách rõ ràng một bean, thay vì để Spring tự động làm như trên. Nó tách phần khai báo của bean khỏi định nghĩa lớp và cho phép bạn tạo và cấu hình các bean chính xác như cách bạn chọn.

Để trả lời câu hỏi của bạn ...

nó có thể sử dụng lại @Componentchú thích thay vì giới thiệu @Beanchú thích không?

Chắc chắn, có lẽ; nhưng họ đã chọn không, vì hai người khá khác nhau. Mùa xuân đã đủ khó hiểu mà không làm vấy bẩn vùng biển hơn nữa.


3
Vì vậy, tôi chỉ có thể sử dụng @Componentkhi cần thiết tự động? Dường như @Beankhông thể ảnh hưởng@Autowired
Jaskey

3
sử dụng '@component' cho các lớp dựa trên dịch vụ, '@Bean' làm nhà máy sản xuất thêm các đối tượng được tạo ra, ví dụ như nguồn dữ liệu jdbc
Junchen Liu

2
@Jaskey bạn có thể sử dụng @Autowiredvới @Beannếu bạn đã chú thích lớp bean của bạn với@Configuration
starcorn

6
Xin lỗi nhưng tôi không thể hiểu một lời giải thích của bạn. Bạn hiểu rõ điều này vì vậy xin vui lòng viết một lời giải thích rõ ràng hoặc chỉ vào tài liệu phù hợp?
Alex Worden

13
Bây giờ tôi đã hiểu khái niệm (từ việc đọc câu trả lời của người khác), lời giải thích của bạn có ý nghĩa. Điều này cho tôi biết thêm rằng lời giải thích của bạn là không tốt cho bất cứ ai chưa hiểu các khái niệm.
Alex Worden

397

@Component Thích hợp cho quét thành phần và nối dây tự động.

Khi nào bạn nên sử dụng @Bean ?

Đôi khi cấu hình tự động không phải là một lựa chọn. Khi nào? Hãy tưởng tượng rằng bạn muốn nối các thành phần từ các thư viện của bên thứ 3 (bạn không có mã nguồn để bạn không thể chú thích các lớp của nó với @Component), vì vậy không thể cấu hình tự động.

Các @Bean chú thích trả về một đối tượng mà mùa xuân nên đăng ký như đậu trong bối cảnh ứng dụng. Phần thân của phương thức chịu logic chịu trách nhiệm tạo cá thể.


5
Tôi nghĩ rằng điều này có ý nghĩa nhất. Nếu tôi hiểu chính xác thì tự @Componentđi vào các lớp trong khi @Beantiếp tục các phương thức lớp (tạo ra các thể hiện của các đối tượng lớp).
vui vẻ

182

Hãy xem xét tôi muốn thực hiện cụ thể tùy thuộc vào một số trạng thái động. @Beanlà hoàn hảo cho trường hợp đó.

@Bean
@Scope("prototype")
public SomeService someService() {
    switch (state) {
    case 1:
        return new Impl1();
    case 2:
        return new Impl2();
    case 3:
        return new Impl3();
    default:
        return new Impl();
    }
}

Tuy nhiên không có cách nào để làm điều đó với @Component.


3
Làm thế nào bạn gọi lớp ví dụ đó?
PowerFlower

1
@PowerFlower Phương thức này phải ở trong một lớp cấu hình, được chú thích bằng@Configuration
Juh_

98
  1. @Component auto tự động phát hiện và định cấu hình các bean bằng cách sử dụng quét classpath trong khi @Bean tuyên bố rõ ràng một bean duy nhất, thay vì để Spring tự động làm điều đó.
  2. @Component không tách rời khai báo của bean từ định nghĩa lớp trong khi @Bean tách riêng khai báo của bean từ định nghĩa lớp.
  3. @Component là một chú thích cấp độ lớp trong khi @Bean là một chú thích cấp độ phương thức và tên của phương thức đóng vai trò là tên bean.
  4. Không cần sử dụng @Component với chú thích @Configuration trong đó chú thích @Bean phải được sử dụng trong lớp được chú thích bằng @Configuration .
  5. Chúng ta không thể tạo một bean của một lớp bằng cách sử dụng @Component, nếu lớp đó nằm ngoài container mùa xuân trong khi chúng ta có thể tạo một bean của một lớp bằng cách sử dụng @Bean ngay cả khi lớp có mặt bên ngoài container mùa xuân .
  6. @Component có các chuyên ngành khác nhau như @Controll, @Rep repository và @Service trong khi @Bean không có chuyên môn .

3
4. Trên thực tế @Bean có thể được khai báo trong lớp không cấu hình. Nó được gọi là chế độ lite
voipp

1
Về điểm 5. Tôi nghĩ rằng chúng ta đặt một hạt đậu bên trong thùng chứa mùa xuân. Vì vậy, mỗi lớp là bên ngoài container mùa xuân. Tôi đoán, điểm 5 nên được khen thưởng
eugen

97

Cả hai cách tiếp cận đều nhằm mục đích đăng ký loại mục tiêu trong container Spring.

Sự khác biệt là @Beanáp dụng cho các phương pháp , trong khi @Componentáp dụng cho các loại .

Do đó, khi bạn sử dụng @Beanchú thích, bạn sẽ điều khiển logic tạo cá thể trong phần thân của phương thức (xem ví dụ ở trên ). Với @Componentchú thích bạn không thể.


Một loại là gì?
Jac Frall

20

Tôi thấy rất nhiều câu trả lời và hầu như ở mọi nơi @Component được đề cập của nó là để tự động tìm kiếm nơi thành phần được quét và @Bean chính xác tuyên bố rằng bean được sử dụng khác nhau. Hãy để tôi cho thấy nó khác nhau như thế nào.

  • @Hạt đậu

Đầu tiên nó là một chú thích cấp độ phương thức. Thứ hai, bạn thường sử dụng để cấu hình các bean trong mã java (nếu bạn không sử dụng cấu hình xml) và sau đó gọi nó từ một lớp bằng phương thức getBean của ApplicationContext. giống

 @Configuration
class MyConfiguration{
    @Bean
    public User getUser(){
        return new User();
    }
}

class User{
}



//Getting Bean 
User user = applicationContext.getBean("getUser");
  • @Component

Đó là cách chung để chú thích một hạt đậu và không phải là một loại đậu chuyên dụng. Một chú thích cấp lớp và được sử dụng để tránh tất cả những thứ cấu hình đó thông qua cấu hình java hoặc xml.

Chúng tôi nhận được một cái gì đó như thế này.

@Component
class User {
}

//to get Bean
@Autowired
User user;

Đó là nó . Nó chỉ được giới thiệu để tránh tất cả các bước cấu hình để khởi tạo và sử dụng bean đó.


5
Tôi nghĩ rằng không cần thiết phải lấy đối tượng Người dùng từ ApplicationContext khi bạn sử dụng @Beanphương pháp tiếp cận. Bạn vẫn có thể sử dụng @Autowiređể lấy đậu như bạn sẽ làm trong trường hợp @Component. @Beanchỉ cần thêm Bean vào Spring Container giống như @Componentvậy. Sự khác biệt là như sau. 1. Sử dụng @Bean, bạn có thể thêm Lớp bên thứ ba vào Spring Container. 2. Sử dụng @Bean, bạn có thể nhận được triển khai giao diện mong muốn vào thời gian chạy (Sử dụng mẫu thiết kế nhà máy)
Andy

20

Bạn có thể sử dụng @Beanđể cung cấp lớp bên thứ ba hiện có cho bối cảnh ứng dụng khung công tác Spring của bạn.

@Bean
public ViewResolver viewResolver() {

    InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();

    viewResolver.setPrefix("/WEB-INF/view/");
    viewResolver.setSuffix(".jsp");

    return viewResolver;
}

Bằng cách sử dụng @Beanchú thích, bạn có thể bọc một lớp bên thứ ba (nó có thể không có @Componentvà nó có thể không sử dụng Spring), như một hạt đậu mùa xuân. Và sau đó khi nó được gói bằng cách sử dụng @Bean, nó là một đối tượng đơn lẻ và có sẵn trong ngữ cảnh ứng dụng khung công tác Spring của bạn. Bây giờ bạn có thể dễ dàng chia sẻ / tái sử dụng loại đậu này trong ứng dụng của mình bằng cách sử dụng phép nội xạ phụ thuộc và @Autowired.

Vì vậy, hãy nghĩ rằng @Beanchú thích là một trình bao bọc / bộ chuyển đổi cho các lớp bên thứ ba. Bạn muốn làm cho các lớp bên thứ ba có sẵn cho bối cảnh ứng dụng khung công tác Spring của bạn.

Bằng cách sử dụng @Beanmã ở trên, tôi tuyên bố rõ ràng một bean duy nhất bởi vì bên trong phương thức, tôi rõ ràng đang tạo đối tượng bằng newtừ khóa. Tôi cũng đang gọi thủ công các phương thức setter của lớp đã cho. Vì vậy, tôi có thể thay đổi giá trị của trường tiền tố. Vì vậy, công việc thủ công này được gọi là sáng tạo rõ ràng. Nếu tôi sử dụng @Componentcho cùng một lớp, bean được đăng ký trong bộ chứa Spring sẽ có giá trị mặc định cho trường tiền tố.

Mặt khác, khi chúng tôi chú thích một lớp với @Component, chúng tôi không cần phải sử dụng newtừ khóa theo cách thủ công . Nó được xử lý tự động bởi Spring.


1
Sẽ rất tuyệt nếu câu trả lời này được cập nhật với một ví dụ về cách sử dụng hạt đậu đó
softarn

Làm thế nào bạn sẽ bọc một @Bean trên một lớp bên thứ ba nếu mã nguồn không cho phép sửa đổi?
veritas

16

Khi bạn sử dụng @Componentthẻ, nó giống như có POJO (Đối tượng Java thuần túy cũ) với phương thức khai báo hạt vani (được chú thích bằng @Bean). Ví dụ, phương pháp 1 và 2 sau đây sẽ cho kết quả tương tự.

Phương pháp 1

@Component
public class SomeClass {

    private int number;

    public SomeClass(Integer theNumber){
        this.number = theNumber.intValue();
    }

    public int getNumber(){
        return this.number;
    }
}

với một hạt cho 'theNumber':

@Bean
Integer theNumber(){
    return new Integer(3456);
}

Cách 2

//Note: no @Component tag
public class SomeClass {

    private int number;

    public SomeClass(Integer theNumber){
        this.number = theNumber.intValue();
    }

    public int getNumber(){
        return this.number;
    }
}

với đậu cho cả hai:

@Bean
Integer theNumber(){
    return new Integer(3456);
}

@Bean
SomeClass someClass(Integer theNumber){
    return new SomeClass(theNumber);
}

Phương pháp 2 cho phép bạn giữ các khai báo bean cùng nhau, nó linh hoạt hơn một chút, v.v. Thậm chí, bạn có thể muốn thêm một bean BeanClass khác không phải vanilla như sau:

@Bean
SomeClass strawberryClass(){
    return new SomeClass(new Integer(1));
}

10

Bạn có hai cách để tạo ra đậu. Một là tạo một lớp với một chú thích @Component. Cách khác là tạo một phương thức và chú thích nó với @Bean. Đối với các lớp chứa phương thức @Beannên được chú thích với @Configuration Khi bạn chạy dự án mùa xuân của mình, lớp có @ComponentScanchú thích sẽ quét mọi lớp với @Componentnó và khôi phục thể hiện của lớp này vào Container Ioc. Một điều khác @ComponentScansẽ làm là chạy các phương thức với @Beannó và khôi phục đối tượng trả về cho Ioc Container dưới dạng một bean. Vì vậy, khi bạn cần quyết định loại đậu nào bạn muốn tạo tùy thuộc vào trạng thái hiện tại, bạn cần sử dụng@Bean. Bạn có thể viết logic và trả về đối tượng bạn muốn. Một điều đáng nói nữa là tên của phương thức với @Beanlà tên mặc định của bean.


6
  • @component và các chuyên môn của nó (@Controll, @service, @reposeective) cho phép tự động phát hiện bằng cách sử dụng quét đường dẫn. Nếu chúng ta thấy lớp thành phần như @Controll, @service, @reposeective sẽ được quét tự động bởi khung công tác mùa xuân bằng cách quét thành phần.
  • Mặt khác, @Bean chỉ có thể được sử dụng để khai báo rõ ràng một bean duy nhất trong một lớp cấu hình.
  • @Bean được sử dụng để khai báo một cách rõ ràng một bean, thay vì để mùa xuân tự động làm điều đó. Nó làm cho khai báo kín của đậu từ định nghĩa lớp.
  • Trong ngắn @Controll, @service, @reposeective dành cho tự động phát hiện và @Bean để tạo bean tách biệt từ lớp
    - @Controll
    lớp công khai Đăng nhập 
    {--code--}

    - @Cấu hình
    lớp công khai AppConfig {
    @Hạt đậu
    phiên công khaiFactory sessionFactory () 
    {--code--}

3

@Bean được tạo để tránh khớp Spring và quy tắc kinh doanh của bạn trong thời gian biên dịch. Điều đó có nghĩa là bạn có thể sử dụng lại các quy tắc kinh doanh của mình trong các khung khác như PlayFramework hoặc JEE.

Hơn nữa, bạn có toàn quyền kiểm soát cách tạo hạt đậu, nơi nó không đủ khả năng khởi tạo Spring mặc định.

Tôi đã viết một bài nói về nó.

https://coderstower.com/2019/04/23/factory-methods-decoupling-ioc-container-abstraction/



1

1. Giới thiệu về @Component
@Component kết thúc tương tự như @Configuration.

Cả hai đều chỉ ra rằng lớp chú thích có một hoặc nhiều hạt cần phải được đăng ký Spring-IOC-Container.

Lớp được chú thích bởi @Component, chúng tôi gọi nó Component of Spring. Đó là một khái niệm có chứa một số đậu.

Component classcần được quét tự động bởi Spring để đăng ký những hạt đậu đó component class.

2. Giới thiệu về @Bean
@Bean được sử dụng để chú thích phương thức component-class(như đã đề cập ở trên). Nó chỉ ra thể hiện được giữ lại bằng phương thức chú thích cần phải được đăng ký Spring-IOC-Container.

3. Kết luận
Sự khác biệt giữa hai chúng là tương đối khó hiểu, chúng được sử dụng trong different circumstances. Cách sử dụng chung là:

    // @Configuration is implemented by @Component
    @Configuration
    public ComponentClass {

      @Bean
      public FirstBean FirstBeanMethod() {
        return new FirstBean();
      }

      @Bean
      public SecondBean SecondBeanMethod() {
        return new SecondBean();
      }
    }

0

Điểm bổ sung từ câu trả lời trên

Giả sử chúng ta có một mô-đun được chia sẻ trong nhiều ứng dụng và nó chứa một vài dịch vụ. Không phải tất cả đều cần thiết cho mỗi ứng dụng.

Nếu sử dụng @Component trên các lớp dịch vụ đó và quét thành phần trong ứng dụng,

cuối cùng chúng ta có thể phát hiện ra nhiều đậu hơn mức cần thiết

Trong trường hợp này, bạn phải điều chỉnh quá trình lọc thành phần quét hoặc cung cấp cấu hình mà ngay cả các hạt không sử dụng cũng có thể chạy. Nếu không, bối cảnh ứng dụng sẽ không bắt đầu.

Trong trường hợp này, tốt hơn là làm việc với chú thích @Bean và chỉ khởi tạo những hạt đậu đó,

được yêu cầu riêng trong mỗi ứng dụng

Vì vậy, về cơ bản, hãy sử dụng @Bean để thêm các lớp của bên thứ ba vào ngữ cảnh. Và @Component nếu nó chỉ nằm trong ứng dụng duy nhất của bạ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.