Làm thế nào để so sánh CDI và EJB? tương tác?


106

Tôi đang rất khó hiểu cách cả hai tương tác và ranh giới giữa chúng nằm ở đâu. Chúng có trùng nhau không? Có dư thừa giữa chúng không?

Tôi biết có các chú thích được liên kết với cả hai, nhưng tôi không thể tìm thấy danh sách đầy đủ cho cả hai với mô tả ngắn gọn. Không chắc liệu điều này có giúp làm rõ chúng khác nhau như thế nào hoặc chúng trùng lặp ở đâu.

Thực sự chỉ là bối rối. Tôi (nghĩ rằng tôi) hiểu EJB một cách hợp lý, tôi đoán tôi đang gặp khó khăn để hiểu chính xác những gì CDI mang lại cho bảng và cách nó bổ sung hoặc nâng cao những gì EJB đã cung cấp.


3
Câu hỏi này phân loại hàng đầu trên tìm kiếm "EJB CDI khác biệt" của Google, nhưng tôi tìm thấy câu trả lời ở stackoverflow.com/questions/13487987/... rõ ràng hơn
mờ freake

Câu trả lời:


50

CDI: đó là về tiêm phụ thuộc. Nó có nghĩa là bạn có thể thực hiện giao diện ở bất cứ đâu. Đối tượng này có thể là bất cứ thứ gì, nó có thể không liên quan đến EJB. Đây là một ví dụ về cách đưa bộ tạo ngẫu nhiên bằng CDI. Không có gì về EJB. Bạn sẽ sử dụng CDI khi bạn muốn đưa vào các dịch vụ không phải EJB, các triển khai hoặc thuật toán khác nhau (vì vậy bạn không cần EJB ở đó).
EJB: bạn hiểu, và có thể bạn đang bối rối bởi @EJBchú thích - nó cho phép bạn đưa việc triển khai vào dịch vụ của mình hoặc bất cứ điều gì. Ý tưởng chính là lớp, nơi bạn tiêm, nên được quản lý bởi vùng chứa EJB. Có vẻ như CDI hiểu EJB là gì, vì vậy trong máy chủ tuân thủ Java EE 6, trong servlet của bạn, bạn có thể viết cả hai

@EJB EJBService ejbService;

@Inject EJBService ejbService;

đó là điều có thể khiến bạn khó hiểu, nhưng đó có lẽ là thứ duy nhất là cầu nối giữa EJB và CDI.

Khi chúng ta đang nói về CDI, bạn có thể đưa các đối tượng khác vào các lớp được quản lý bởi CDI (chúng chỉ nên được tạo bởi các khung nhận biết CDI).

CDI cung cấp những gì khác ... Ví dụ: bạn sử dụng Struts 2 làm khuôn khổ MVC (chỉ là ví dụ) và bạn bị giới hạn ở đây, ngay cả khi sử dụng EJB 3.1 - bạn không thể sử dụng @EJBchú thích trong hành động Struts, nó không được quản lý bởi vùng chứa. Nhưng khi bạn thêm plugin Struts2-CDI, bạn có thể viết @Injectchú thích ở đó cho điều tương tự (vì vậy không cần tra cứu JNDI nữa). Bằng cách này, nó tăng cường sức mạnh EJB, nhưng như tôi đã đề cập trước đây, những gì bạn tiêm với CDI - không quan trọng nó có liên quan đến EJB hay không, và đó là sức mạnh của nó.

Tái bút. liên kết cập nhật đến ví dụ


@EJB và @Inject có thực sự tương đương về chức năng không? Tôi nghĩ rằng đó là sự chồng chéo của các phương pháp tiêm giữa CDI và một số phần còn lại của từ viết tắt Java EE đã làm tôi bối rối. Đọc nhiều hơn dường như cho thấy rằng có hy vọng để sắp xếp các chú thích.
Tim

@Maxym Khi bạn sử dụng @ Inject, làm thế nào bạn có thể đảm bảo rằng @ Stateless hoặc bất kỳ thành phần phía máy chủ nào khác của EJB vẫn sử dụng các tính năng như Pooling hoặc đồng thời được cung cấp bởi vùng chứa. Tôi hy vọng điều này không được cung cấp bởi CDI phải không?
Bala

1
@Bala: CDI không cung cấp tính năng gộp ... hãy xem CDI có hoặc không có EJB3.1 , hy vọng nó trả lời câu hỏi của bạn ..
Maxym

@KorayTugay: CDI là một tính năng Java EE, vì vậy bất kỳ máy chủ nào tuân thủ Java EE 6 đều có nó (không nhầm là Glassfish 3.0.1+, JBoss 6+, v.v.) Bạn có thể xem qua JBoss Weld, một triển khai CDI tham khảo mà bạn có thể sử dụng trong ví dụ Tomcat ...
Maxym

191

Hiện tại nó thực sự là một chút khó hiểu vì hiện nay có nhiều mô hình thành phần trong Java EE. Đó là các loại Đậu được quản lý CDI , EJB3JSF .

CDI là đứa trẻ mới trong khối. Tính năng đậu CDI dependency injection, scopingvà một event bus. Đậu CDI là loại đậu linh hoạt nhất đối với việc tiêm và xác định phạm vi. Bus sự kiện rất nhẹ và rất phù hợp cho ngay cả những ứng dụng web đơn giản nhất. Ngoài ra, CDI cũng giới thiệu một tính năng rất nâng cao được gọi là portable extensions, đây là một loại cơ chế trình cắm thêm cho các nhà cung cấp để cung cấp chức năng bổ sung cho Java EE có thể được cung cấp trên tất cả các triển khai (Glassfish, JBoss AS, Websphere, v.v.) .

Các bean EJB3 đã được trang bị thêm từ mô hình thành phần EJB2 cũ * và là các bean đầu tiên trong Java EE được quản lý các bean thông qua một chú thích. Đậu EJB3 tính năng dependency injection, declarative transactions, declarative security, pooling, concurrency control, asynchronous executionremoting.

Việc tiêm phụ thuộc vào đậu EJB3 không linh hoạt như trong đậu CDI và đậu EJB3 không có khái niệm xác định phạm vi. Tuy nhiên, các bean EJB3 được giao dịch và gộp theo mặc định ** , hai thứ rất hữu dụng mà CDI đã chọn để lại trong miền của EJB3. Các mục khác được đề cập cũng không có sẵn trong CDI. EJB3 không có bus sự kiện của riêng nó, nhưng nó có một loại bean đặc biệt để nghe thông báo; đậu điều khiển thông điệp. Điều này có thể được sử dụng để nhận tin nhắn từ Hệ thống nhắn tin Java hoặc từ bất kỳ hệ thống nào khác có bộ điều hợp tài nguyên JCA. Việc sử dụng thông báo đầy đủ cho các sự kiện đơn giản nặng hơn nhiều so với bus sự kiện CDI và EJB3 chỉ xác định trình nghe, không phải API của nhà sản xuất.

JSF Managed Beans đã tồn tại trong Java EE kể từ khi JSF được đưa vào. Họ cũng có tính năng dependency injectionscoping. JSF Managed Beans đã giới thiệu khái niệm về phạm vi khai báo. Ban đầu các phạm vi khá hạn chế và trong cùng một phiên bản Java EE, nơi các đậu EJB3 đã có thể được khai báo thông qua chú thích, các Đậu được quản lý JSF vẫn phải được khai báo bằng XML. Phiên bản hiện tại của JSF Managed Beans cuối cùng cũng được khai báo thông qua một chú thích và các phạm vi được mở rộng với một phạm vi xem và khả năng tạo phạm vi tùy chỉnh. Phạm vi chế độ xem, ghi nhớ dữ liệu giữa các yêu cầu đến cùng một trang là một tính năng độc đáo của JSF Managed Beans.

Ngoài phạm vi chế độ xem, vẫn còn rất ít thông tin về JSF Managed Beans trong Java EE 6. Thật không may, việc thiếu phạm vi xem trong CDI, vì nếu không CDI sẽ là một bộ siêu hoàn hảo của những gì JSF Managed Beans cung cấp. Cập nhật : Trong Java EE 7 / JSF 2.2, @ViewScoped tương thích với CDI đã được thêm vào, khiến CDI thực sự trở thành bộ siêu hoàn hảo. Cập nhật 2 : Trong JSF2.3, các bean được quản lý JSF đã không được dùng nữa để thay thế cho các bean được quản lý bằng CDI.

Với EJB3 và CDI, tình hình không rõ ràng như vậy. Mô hình thành phần EJB3 và API cung cấp rất nhiều dịch vụ mà CDI không cung cấp, do đó, thường không thể thay thế EJB3 bằng CDI. Mặt khác, CDI có thể được sử dụng kết hợp với EJB3 - ví dụ như thêm hỗ trợ phạm vi cho EJB.

Reza Rahman, thành viên nhóm chuyên gia và người triển khai triển khai CDI có tên là CanDI, đã thường xuyên gợi ý rằng các dịch vụ liên quan đến mô hình thành phần EJB3 có thể được trang bị thêm dưới dạng một tập hợp các chú thích CDI. Nếu điều đó xảy ra, tất cả các bean được quản lý trong Java EE đều có thể trở thành các bean CDI. Điều này không có nghĩa là EJB3 biến mất hoặc trở nên lỗi thời, mà chỉ là chức năng của nó sẽ được hiển thị thông qua CDI thay vì thông qua các chú thích riêng của EJB như @Stateless và @EJB.

Cập nhật

David Blevins của TomEE và OpenEJB nổi tiếng giải thích rất rõ về sự khác biệt và tương đồng giữa CDI và EJB trên blog của anh ấy: CDI, khi nào thì phá vỡ EJB

* Mặc dù nó chỉ là sự gia tăng về số phiên bản, nhưng đậu EJB3 phần lớn là một loại đậu hoàn toàn khác: một pojo đơn giản trở thành một "đậu được quản lý" bằng cách áp dụng một chú thích đơn giản, so với mô hình trong EJB2, nơi nặng và Bộ mô tả triển khai XML quá dài dòng được yêu cầu cho mỗi và mọi bean, ngoài ra bean còn được yêu cầu triển khai các giao diện thành phần cực kỳ nặng và đối với hầu hết các giao diện thành phần vô nghĩa.

** Các đậu phiên không trạng thái thường được gộp chung, các đậu phiên trạng thái thường không (nhưng có thể như vậy). Vì vậy, việc gộp chung cả hai loại là tùy chọn và thông số kỹ thuật EJB không bắt buộc theo cách nào đó.


3
Tôi hơi bối rối trước tuyên bố của bạn rằng "Đậu EJB3 không có khái niệm về phạm vi" và "EJB3 không có bus sự kiện của riêng nó". Làm thế nào điều này phù hợp với tuyên bố của David Blevin rằng "EJB hạt CDI và do đó có tất cả các lợi ích của CDI"? Có điều gì thay đổi về mặt này giữa thời điểm bạn viết câu trả lời của mình và khi David viết bài đăng trên Blog của mình không?
Chris

5
Đó là do khái niệm có lẽ hơi khó hiểu rằng thực sự không có "CDI bean", nhưng có những dịch vụ được áp dụng cho các bean được quản lý. Để tiện cho việc thảo luận, mọi người (và bản thân tôi do đó) gọi chúng là "CDI bean". Trước CDI, EJB bean không có phạm vi rõ ràng. Như David giải thích, Stateful mặc nhiên là bất kỳ phạm vi nào (và do đó không có phạm vi cụ thể). Bây giờ . với CDI có sẵn, đậu EJB có thể tận dụng lợi thế của CDI cung cấp phạm vi Nếu không có spec CDI, vì vậy khi chỉ nhìn vào spec EJB, không có phạm vi rõ ràng.
Arjan Tijms

1
Bạn có thể giải thích rõ hơn về ý của bạn khi "có những dịch vụ được áp dụng cho đậu được quản lý" không? Nó có nghĩa là thực sự không có cái gọi là đậu CDI? Nó chỉ là một số cung cấp các tính năng bổ sung trên POJO - EJB - hoặc JSF Managed Bean? Bạn muốn sử dụng chú thích Inject trong JSF Managed Bean?
Koray Tugay

3
@Chris để làm rõ thêm từ góc độ thông số kỹ thuật của EJB, chúng tôi đã đưa ra quyết định có chủ ý ngay từ đầu CDI là yêu cầu triển khai EJB phải hỗ trợ 100% bộ tính năng CDI trên EJB. Mọi khía cạnh của CDI đều hoạt động trên các EJB, ngoại trừ các phạm vi mà chúng tôi phải giới hạn ở các đậu Trạng thái.
David Blevins

1
Lưu ý rằng JSF 2.2 hiện cung cấp javax.faces.view.ViewScoped, một phần mở rộng CDI về cơ bản là một cổng của phạm vi xem JSF tới CDI. Với điều này, CDI là một sự thay thế đầy đủ cho JSF Managed Beans.
jdessey

-1

Albert Einstein: If you can't explain it simply, you don't understand it well enough

Ejbs và CDI khá đơn giản để hiểu.

Ejbs:

  1. Sẽ luôn được chú thích bởi các bộ định lượng phạm vi, ví dụ: @Stateless, @Stateful, @Request, v.v.
  2. Các phiên bản của Ejbs được kiểm soát bởi khung Java EE và được gộp chung. Khung EE có nhiệm vụ cung cấp các phiên bản cho người tiêu dùng.

@Stateless

 public class CarMaker(){
    public void createCar(Specification specs){
        Car car = new Car(specs);
    }
}

CarMaker được chú thích với phạm vi Ejbs cụ thể, do đó, nó là Ejb

CDI:

  1. Không được quản lý hoàn toàn bởi khung EE, các phiên bản phải được tạo bởi chính bạn.
  2. Nó luôn luôn bị phụ thuộc. hãy để tôi giải thích "Phụ thuộc" với ví dụ:

    class Specification { private String color; private String model; //- Getter and Setter }

Các Specificationlớp học là CDI, vì nó không được chú thích với EJB phạm vi và điều này cũng đã để khởi tạo bởi mã của bạn không khuôn khổ EE. Một điểm cần lưu ý ở đây là vì chúng tôi không chú thích Specificationlớp, nên theo mặc định, nó được chú thích bằng @Dependentchú thích.

@Dependent  <- By default added 
class Specification { ... }

Further reading: Bạn cần nghiên cứu thêm giữa chú thích phạm vi Ejbs và chú thích phạm vi CDI, điều đó sẽ làm rõ hơn khái niệm


Einstein cũng nói: "Mọi thứ nên trở nên đơn giản nhất có thể, nhưng không đơn giản hơn" bạn có thể (nên) thay thế "made" bằng "giải thích" ở đây.
Kukeltje
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.