Sự khác biệt giữa @Inject và @Autowired trong Spring Framework là gì? Cái nào dùng trong điều kiện nào?


695

Tôi đang xem qua một số blog trên SpringSource và trong một trong những blog, tác giả đang sử dụng @Injectvà tôi cho rằng anh ta cũng có thể sử dụng @Autowired.

Đây là đoạn mã:

@Inject private CustomerOrderService customerOrderService;

Tôi không chắc chắn về sự khác biệt giữa @Inject@Autowiredsẽ đánh giá cao nếu ai đó giải thích sự khác biệt của họ và sử dụng cái nào trong tình huống nào?


3
Tôi không có câu trả lời, vì tôi cũng mới biết điều này, nhưng điều này có thể giúp sakaenakajima.wordpress.com/2010/08/10/ trên
Sagar V


2
Sự khác biệt giữa '@Inject' và '@Autowired' được giải thích rõ trong bài viết này alextheedom.wordpress.com/2016/02/13/ trên
Alex Theedom

Câu trả lời:


719

Giả sử ở đây bạn đang đề cập đến các javax.inject.Injectchú thích. @Injectlà một phần của tiêu chuẩn Java CDI ( Contexts and Dependency Injection ) được giới thiệu trong Java EE 6 (JSR-299), đọc thêm . Spring đã chọn hỗ trợ sử dụng @Injectđồng nghĩa với @Autowiredchú thích của riêng họ .

Vì vậy, để trả lời câu hỏi của bạn, @Autowiredlà chú thích riêng của Spring. @Injectlà một phần của công nghệ Java mới có tên CDI, định nghĩa một tiêu chuẩn cho phép tiêm phụ thuộc tương tự như Spring. Trong một ứng dụng Spring, hai chú thích hoạt động theo cùng một cách vì Spring đã quyết định hỗ trợ một số chú thích JSR-299 ngoài các chú thích của chúng.


115
Vì vậy, về mặt lý thuyết nếu bạn đã sử dụng @Inject, bạn có thể thay thế lò xo bằng một khung DI khác, ví dụ như Guice và thực hiện các phụ thuộc của bạn theo cùng một cách.
Alex Barnes

71
Có nguy cơ trở thành phạm vi: @Injectlà một JSR riêng biệt (JSR-330) từ CDI (JSR-299).
Brad Cupit

36
Nếu bạn chỉ dựa vào các chú thích JSR- *, bạn có thể thay thế khung DI của bạn. Nhưng bạn sẽ không Khi bạn đã bắt đầu sử dụng mùa xuân, rất có thể bạn đã sử dụng nó nhiều hơn là chỉ DI. Bạn sẽ không thay đổi; và ngay cả khi bạn làm thế, đó không phải là một vài tìm kiếm & thay thế mà sẽ thực hiện hoặc phá vỡ di chuyển. Mặt khác, các chú thích riêng của Spring cung cấp cho bạn nhiều chức năng hơn. Nắm vững một khuôn khổ tốt sẽ cung cấp cho bạn nhiều hơn là hầu như không sử dụng nhiều.
Agoston Horvath

18
Tôi đồng ý với bạn rằng chúng tôi không thay đổi khung DI thường xuyên. Tuy nhiên, nếu mã nguồn của chúng tôi có nhiều gói và nếu bạn muốn xây dựng một gói chung mà bạn muốn chia sẻ trên nhiều dự án và sau đó @Injectsử dụng chú thích JSR thì tốt hơn là sử dụng @Autowiredkhóa cơ sở mã của bạn với spring DI.
Aditya

3
Sử dụng @Injectmột mình sẽ không đảm bảo tính độc lập của khung. Bạn cũng cần khai báo các loại đậu tiêm mà không cần các cơ chế phụ thuộc khung như Spring, @Componenthoặc application.xmlsử dụng @Named@Singletonở cấp độ lớp. Không biết có dự án mùa xuân nào thực sự tuyên bố đậu như thế ngày hôm nay không - tôi thậm chí chưa bao giờ nghe về bất kỳ dự án nào đã di chuyển từ Spring sang JEE ...
Marcus K.

162

Đây là một bài viết trên blog rằng so sánh @Resource, @Inject@Autowired, và dường như làm một công việc khá toàn diện.

Từ liên kết:

Ngoại trừ thử nghiệm 2 & 7, cấu hình và kết quả là giống hệt nhau. Khi tôi nhìn dưới mui xe, tôi xác định rằng chú thích '@Autowired' và '@Inject' hoạt động giống hệt nhau. Cả hai chú thích này đều sử dụng 'AutowiredAnnotationBeanPostProcessor' để thêm các phụ thuộc. '@Autowired' và '@Inject' có thể được sử dụng thay thế cho nhau để tiêm đậu mùa xuân. Tuy nhiên, chú thích '@Resource' sử dụng 'CommonAnnotationBeanPostProcessor' để thêm các phụ thuộc. Mặc dù họ sử dụng các lớp xử lý bài khác nhau, tất cả chúng đều hoạt động gần như giống hệt nhau. Dưới đây là một bản tóm tắt các đường dẫn thực hiện của họ.

Các thử nghiệm 2 và 7 rằng các tham chiếu của tác giả lần lượt là 'tiêm theo tên trường' và 'một nỗ lực giải quyết một bean bằng cách sử dụng một vòng loại xấu'.

Kết luận sẽ cung cấp cho bạn tất cả các thông tin bạn cần.


4
Bài viết đó là một lời giải thích tuyệt vời của ba chú thích. Tôi đã phải đọc lại nó sau lần vuốt đầu tiên; Nhưng, một bài viết xuất sắc.
Thomas

1
Cảm ơn rất nhiều! Bài viết đã trả lời nhiều câu trả lời của tôi trong quá trình tìm kiếm sự khác biệt và tương đồng giữa Spring và JavaEE, cũng như một vài câu hỏi khác mà tôi có.
Kevin Cruijssen

36

Để xử lý tình huống không có hệ thống dây, đậu có sẵn với @Autowired requiredthuộc tính được đặt thành false.

Nhưng khi sử dụng @Inject, giao diện Nhà cung cấp hoạt động với bean, điều đó có nghĩa là bean không được tiêm trực tiếp mà với Nhà cung cấp.


8
Điều này rất quan trọng, và đã bị bỏ qua trong các câu trả lời được đánh giá cao nhất.
Igor Donin

Theo mặc định, tham số bắt buộc được đặt thành true cho Autowired. Ref: docs.spring.io/spring-framework/docs/current/javadoc-api/org/...
yên tĩnh

25

Tính đến mùa xuân 3,0, Spring cung cấp hỗ trợ cho JSR-330 chú thích dependency injection ( @Inject, @Named, @Singleton).

Có một phần riêng trong tài liệu về Mùa xuân về chúng, bao gồm các so sánh với các tương đương Mùa xuân của chúng.


Câu hỏi ở đây, ý của bạn là gì khi bạn nói Spring hỗ trợ JSR? Không phải container hỗ trợ JSR độc lập với Spring và yêu cầu cho container phải tuân thủ J2EE? Bạn có nghĩa là nó bao bọc các chức năng? Nếu Spring không "hỗ trợ" nó, thì chú thích từ javax vẫn hoạt động theo mặc định?
Dan Chase

Không nhất thiết phải chạy Spring trong một thùng chứa JEE, bạn cũng có thể sử dụng nó trong một thùng chứa servlet / JSP như Tomcat và vẫn có hỗ trợ JSR-330. Spring là một thùng chứa DI riêng biệt, nó không "trao đổi" các hạt CDI với máy chủ JEE lưu trữ nếu đó là ý bạn. Bạn có thể sử dụng CDI trong thùng chứa JEE hoặc Spring bean - nhưng bạn không thể sử dụng cả hai (ngoài hộp).
Andre Steingress

22

Sự khác biệt chính (được chú ý khi đọc Spring Docs ) giữa @Autowired@Injectđó là, @Autowiredcó thuộc tính 'bắt buộc' trong khi @Inject không có thuộc tính 'bắt buộc'.


bạn có ý nghĩa gì theo yêu cầu?
mattyman

2
@mattymanme Từ các tài liệu, "Theo mặc định, autowiring thất bại bất cứ khi nào không đậu ứng cử viên có sẵn; hành vi mặc định là để điều trị phương pháp chú giải, nhà thầu, và các lĩnh vực như chỉ phụ thuộc yêu cầu Hành vi này có thể được thay đổi bằng cách thiết lập thuộc tính cần thiết để sai. ". Ví dụ: @Autowired(required=false).Trong các thuật ngữ đơn giản, " requiredThuộc tính chỉ ra rằng thuộc tính không bắt buộc cho mục đích tự động, thuộc tính sẽ bị bỏ qua nếu không thể tự động."
May mắn

nhìn vào giao diện mã nguồn công khai Tự động {/ ** * Khai báo xem có phụ thuộc chú thích không. * / boolean required () mặc định là true; } Public interface Tiêm {}
Tarn

15

Sử dụng tốt hơn @Inject mọi lúc. Bởi vì đó là cách tiếp cận cấu hình java (được cung cấp bởi mặt trời), điều này làm cho ứng dụng của chúng ta không biết đến khuôn khổ. Vì vậy, nếu bạn mùa xuân cũng các lớp học của bạn sẽ làm việc.

Nếu bạn sử dụng @Autowired, nó sẽ chỉ hoạt động với mùa xuân vì @Autowired là chú thích do mùa xuân cung cấp.


13
Mặt trời đã chết. Sống lâu nắng.
Amrinder Arora

6
bao lâu thì bạn sẽ thay đổi khuôn khổ? chỉ tò mò
Kay

Trên hầu hết các dự án tôi thấy Autowired thay vì Tiêm. Tôi hiểu lý do của câu trả lời nhưng tôi không thể nâng cao.
Witold Kaczurba 23/03/18

13

@Autowired chú thích được xác định trong khung Spring.

@Injectchú thích là một chú thích tiêu chuẩn, được định nghĩa trong tiêu chuẩn "Dependency Injection for Java" (JSR-330) . Spring (kể từ phiên bản 3.0) hỗ trợ mô hình tiêm phụ thuộc tổng quát được định nghĩa trong tiêu chuẩn JSR-330. ( Khung Google Guicekhung Picocontainer cũng hỗ trợ mô hình này).

Với @Injectcó thể được tiêm tham chiếu đến việc thực hiện Providergiao diện, cho phép tiêm các tham chiếu hoãn lại.

Chú thích @Inject@Autowired- gần như hoàn toàn tương tự. Cũng như @Autowiredchú thích, @Injectchú thích có thể được sử dụng cho các thuộc tính, phương thức và hàm tạo liên kết tự động.

Ngược lại với @Autowiredchú thích, @Injectchú thích không có requiredthuộc tính. Do đó, nếu không tìm thấy các phụ thuộc - sẽ bị ném ngoại lệ.

Cũng có sự khác biệt trong việc làm rõ các thuộc tính ràng buộc. Nếu có sự không rõ ràng trong việc lựa chọn các thành phần cho tiêm, @Namednên bổ sung vòng loại. Trong một tình huống tương tự cho @Autowiredchú thích sẽ được thêm vào @Qualifiervòng loại (JSR-330 định nghĩa @Qualifierchú thích riêng của nó và thông qua chú thích vòng loại @Namednày được xác định).


Mặc dù '@Inject' không có thuộc tính bắt buộc, trạng thái Tài liệu Java: Yêu cầu tiêm các thành viên được chú thích bằng '@Inject'. Điều này dường như ngụ ý rằng nếu một thành viên không được tìm thấy thì tiêm sẽ thất bại. Xem Tài liệu Java: docs.oracle.com/javaee/7/api/javax/inject/Inject.html
Alex Theedom


12

Ngoài những điều trên:

  1. Phạm vi mặc định cho các @Autowiredbean là Singleton trong khi sử dụng @Injectchú thích JSR 330, nó giống như nguyên mẫu của Spring .
  2. Không có tương đương với @Lazy trong JSR 330 sử dụng @Inject.
  3. Không có tương đương với @Value trong JSR 330 sử dụng @Inject.

0

Các @Injectchú thích là một trong những bộ sưu tập JSR-330 chú thích. Điều này có Đường dẫn thực hiện Khớp theo Loại, Khớp theo Vòng loại, Khớp theo Tên. Các đường dẫn thực thi này là hợp lệ cho cả setter và trường tiêm. Hành vi của @Autowiredchú thích giống như @Injectchú thích. Sự khác biệt duy nhất là @Autowiredchú thích là một phần của khung Spring. @Autowiredchú thích cũng có các đường dẫn thực hiện ở trên. Vì vậy, tôi đề nghị @Autowiredcâu trả lời 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.