Sử dụng EJB 3.1 và CDI ở đâu?


120

Tôi đang tạo một sản phẩm dựa trên Java EE, trong đó tôi đang sử dụng GlassFish 3 và EJB 3.1.

Ứng dụng của tôi có phiên đậu , bộ lập lịch và sử dụng các dịch vụ web. Gần đây tôi đã biết về Apache TomEE , hỗ trợ Contexts và Dependency Injection (CDI) . Hộp chứa GlassFish cũng hỗ trợ CDI.

Tôi có thể thay thế session bean mà tôi không yêu cầu bất kỳ tính năng nào mà CDI cũng chưa cung cấp không? Và nếu sau đó, tôi có thể nhận được những lợi ích gì?

Câu trả lời:


408

Có, bạn có thể tự do kết hợp cả CDI và EJB và đạt được một số kết quả tuyệt vời. Có vẻ như bạn đang sử dụng @WebService@Scheduleđó là những lý do chính đáng để thêm EJB vào hỗn hợp.

Có rất nhiều sự nhầm lẫn ở đó, vì vậy đây là một số thông tin chung về EJB và CDI vì chúng liên quan đến nhau.

EJB> = CDI

Lưu ý rằng EJB hạt CDI và do đó có tất cả các lợi ích của CDI. Điều ngược lại là không đúng (chưa). Vì vậy, chắc chắn đừng có thói quen nghĩ "EJB vs CDI" vì logic đó thực sự chuyển thành "EJB + CDI vs CDI", đó là một phương trình kỳ quặc.

Trong các phiên bản Java EE trong tương lai, chúng tôi sẽ tiếp tục điều chỉnh chúng. Có gì sắp xếp phương tiện được cho phép mọi người làm những gì họ đã có thể làm được, chỉ cần không có @Stateful, @Statelesshoặc @Singletonchú thích ở đầu trang.

EJB và CDI trong Điều khoản triển khai

Cuối cùng, EJB và CDI có chung thiết kế cơ bản là các thành phần được ủy quyền. Khi bạn nhận được tham chiếu đến hạt đậu EJB hoặc CDI, nó không phải là hạt đậu thật. Thay vì đối tượng mà bạn được cung cấp là đồ giả (một proxy). Khi bạn gọi một phương thức trên đối tượng giả mạo này, cuộc gọi sẽ chuyển đến vùng chứa, người sẽ gửi cuộc gọi thông qua bộ đánh chặn, người trang trí, v.v. cũng như thực hiện bất kỳ giao dịch hoặc kiểm tra bảo mật nào. Khi tất cả những gì đã hoàn tất, cuộc gọi cuối cùng sẽ chuyển đến đối tượng thực và kết quả được chuyển trở lại thông qua proxy cho người gọi.

Sự khác biệt chỉ đến ở cách giải quyết đối tượng được gọi. Bằng cách "giải quyết", chúng tôi chỉ đơn giản có nghĩa là vùng chứa trông như thế nào và ở đâu đối với cá thể thực để gọi.

Trong CDI, vùng chứa sẽ nằm trong một "phạm vi", về cơ bản sẽ là một bản đồ băm tồn tại trong một khoảng thời gian cụ thể (theo yêu cầu @RequestScoped, mỗi phiên HTTP @SessionScoped, mỗi ứng dụng @ApplicationScoped, Cuộc hội thoại JSF @ConversationScopedhoặc mỗi triển khai phạm vi tùy chỉnh của bạn).

Trong EJB, vùng chứa cũng giống như một bản đồ băm nếu bean thuộc loại @Stateful. Một @Statefulhạt đậu cũng có thể sử dụng bất kỳ chú thích phạm vi nào ở trên khiến nó sống và chết với tất cả các hạt đậu khác trong phạm vi. Trong EJB @Statefulvề cơ bản là bean "bất kỳ phạm vi nào". Các @Statelesscơ bản là một hồ bơi dụ - bạn sẽ có được một thể hiện từ hồ bơi trong suốt thời gian của một sự thỉnh nguyện. Về @Singletoncơ bản là@ApplicationScoped

Vì vậy, ở cấp độ cơ bản, bất cứ điều gì bạn có thể làm với bean "EJB", bạn sẽ có thể làm với bean "CDI". Dưới lớp vỏ bọc thật khó để phân biệt chúng. Tất cả các hệ thống ống nước đều giống nhau, ngoại trừ cách giải quyết các trường hợp.

Chúng hiện không giống nhau về các dịch vụ mà vùng chứa sẽ cung cấp khi thực hiện ủy quyền này, nhưng như tôi đã nói, chúng tôi đang làm việc trên nó ở cấp thông số kỹ thuật Java EE.

Ghi chú hiệu suất

Bỏ qua mọi hình ảnh tinh thần "nhẹ" hoặc "nặng" mà bạn có thể có. Đó là tất cả tiếp thị. Chúng có thiết kế bên trong giống nhau cho hầu hết các phần. Độ phân giải phiên bản CDI có lẽ phức tạp hơn một chút vì nó hơi động hơn và theo ngữ cảnh. Độ phân giải phiên bản EJB là khá tĩnh, đơn giản và dễ so sánh.

Tôi có thể cho bạn biết từ góc độ triển khai trong TomEE, không có sự khác biệt về hiệu suất giữa việc gọi EJB và việc gọi một bean CDI.

Mặc định thành POJO, sau đó là CDI, sau đó là EJB

Tất nhiên không sử dụng CDI hoặc EJB khi không có lợi ích gì. Nộp CDI khi bạn bắt đầu muốn tiêm, sự kiện, bộ chặn, bộ trang trí, theo dõi vòng đời và những thứ tương tự. Đó là hầu hết thời gian.

Ngoài những vấn đề cơ bản, có một số dịch vụ container hữu ích mà bạn chỉ có tùy chọn để sử dụng nếu bạn thực hiện đậu CDI của bạn cũng là một EJB bằng cách thêm @Stateful, @Statelesshoặc @Singletontrên đó.

Đây là danh sách ngắn về thời điểm tôi phá vỡ các EJB.

Sử dụng JAX-WS

Hiển thị một JAX-WS @WebService. Tôi lười. Khi @WebServicenó cũng là một EJB, bạn không cần phải liệt kê nó và ánh xạ nó như một servlet trong web.xmltệp. Đó là công việc đối với tôi. Ngoài ra, tôi có tùy chọn sử dụng bất kỳ chức năng nào khác được đề cập bên dưới. Vì vậy, đó là không có trí tuệ đối với tôi.

Có sẵn cho @Stateless@Singletonchỉ.

Sử dụng JAX-RS

Hiển thị tài nguyên JAX-RS qua @Path. Tôi vẫn lười biếng. Khi dịch vụ RESTful cũng là một EJB, một lần nữa bạn sẽ có được khả năng khám phá tự động và không phải thêm nó vào Applicationlớp con JAX-RS hoặc bất cứ thứ gì tương tự. Thêm vào đó, tôi có thể hiển thị chính xác bean giống như một @WebServicenếu tôi muốn hoặc sử dụng bất kỳ chức năng tuyệt vời nào được đề cập bên dưới.

Có sẵn cho @Stateless@Singletonchỉ.

Logic khởi động

Tải khi khởi động qua @Startup. Hiện tại không có tương đương với điều này trong CDI. Bằng cách nào đó, chúng tôi đã bỏ lỡ thêm một cái gì đó như một AfterStartupsự kiện trong vòng đời của vùng chứa. Nếu chúng tôi làm điều này, bạn chỉ đơn giản có thể có một @ApplicationScopedhạt đậu lắng nghe nó và điều đó sẽ hiệu quả giống như @Singletonvới @Startup. Nó nằm trong danh sách cho CDI 1.1.

@SingletonChỉ có sẵn cho .

Làm việc song song

@Asynchronouslệnh gọi phương thức. Bắt đầu luồng là điều không nên trong bất kỳ môi trường phía máy chủ nào. Có quá nhiều chủ đề là một kẻ giết hiệu suất nghiêm trọng. Chú thích này cho phép bạn song song hóa những việc bạn làm bằng cách sử dụng nhóm luồng của vùng chứa. Điều này thật tuyệt.

Có sẵn cho @Stateful, @Stateless@Singleton.

Lên lịch làm việc

@Schedulehoặc ScheduleExpressionvề cơ bản là một cron hoặc Quartzchức năng. Cũng rất tuyệt vời. Hầu hết các hộp đựng chỉ sử dụng Thạch anh dưới nắp cho việc này. Tuy nhiên, hầu hết mọi người không biết rằng công việc lên lịch trong Java EE là giao dịch! Nếu bạn cập nhật cơ sở dữ liệu sau đó lên lịch một số công việc và một trong số chúng không thành công, cả hai sẽ tự động được dọn dẹp. Nếu EntityManagercuộc gọi liên tục không thành công hoặc có sự cố xả nước, không cần phải hủy lên lịch công việc. Yay, giao dịch.

Có sẵn cho @Stateless@Singletonchỉ.

Sử dụng EntityManagers trong giao dịch JTA

Lưu ý ở trên về các giao dịch tất nhiên yêu cầu bạn sử dụng một JTAquản lý EntityManager. Bạn có thể sử dụng chúng với "CDI" đơn giản, nhưng nếu không có các giao dịch được quản lý bởi vùng chứa, nó có thể thực sự đơn điệu sao chép UserTransactionlogic cam kết / khôi phục.

Dành cho tất cả các thành phần Java EE bao gồm CDI, JSF @ManagedBean, @WebServlet, @WebListener, @WebFilter, vv @TransactionAttributechú thích, tuy nhiên, hiện có sẵn để @Stateful, @Stateless@Singletonduy nhất.

Giữ JTA được quản lý EntityManager

Được EXTENDEDquản lý EntityManagercho phép bạn giữ sự EntityManagermở giữa JTAcác giao dịch và không làm mất dữ liệu đã lưu trong bộ nhớ cache. Tính năng tốt cho đúng thời gian và địa điểm. Sử dụng có trách nhiệm :)

@StatefulChỉ có sẵn cho .

Đồng bộ hóa dễ dàng

Khi bạn cần đồng bộ hóa, chú thích @Lock(READ)@Lock(WRITE)chú thích khá tuyệt vời. Nó cho phép bạn quản lý truy cập đồng thời miễn phí. Bỏ qua tất cả các đường ống dẫn nước ReentrantReadWriteLock. Trong cùng một nhóm @AccessTimeout, cho phép bạn nói một luồng sẽ đợi bao lâu để có quyền truy cập vào cá thể bean trước khi từ bỏ.

Chỉ dành cho @Singletonđậu.


32
Chúa ơi, David :) Tôi nghĩ bạn đã che nó.
LightGuard

7
Cảm ơn bạn vì câu trả lời này. Bạn đã thông tắc nghẽn trong đầu tôi và kết nối rất nhiều dấu chấm.
Thupten

7
Đây là lời giải thích tốt nhất về chủ đề đó mà tôi từng đọc. Nó cũng bao gồm gần như tất cả các khía cạnh quan trọng của EJB trong sử dụng Đời thực. Công việc tuyệt vời !!
nanoquack

3
Rất dễ hiểu và Adam không sai trong các điều khoản pháp lý nghiêm ngặt, nhưng sự khác biệt là tranh luận. Thông số kỹ thuật cho biết cá thể EJB không theo ngữ cảnh, nhưng sau đó nói rằng tham chiếu (proxy) đến EJB là theo ngữ cảnh. Vòng đời của Stateful bean được kiểm soát hoàn toàn thông qua tham chiếu (proxy), vì vậy khi vùng chứa CDI đang kiểm soát tham chiếu (proxy) đó, phép toán sẽ xuất hiện giống nhau - Stateful EJB có thể thực sự theo ngữ cảnh.
David Blevins

3
Bạn đã viết điều này vào giờ nghỉ trưa của bạn tại TESLA?
Edison

2

nếu bạn thực sự không sử dụng bất kỳ tính năng nào của ejb 3.1 thì câu trả lời rất đơn giản. nhưng đoán câu hỏi của bạn cho thấy bạn nghi ngờ có những khái niệm ejb 3.1 mà bạn đang hưởng lợi mà không biết về chúng. một ví dụ có thể là vùng chứa có thể giữ cho một nhóm slsb sẵn sàng được sử dụng, để các kết nối jms và cơ sở dữ liệu không cần phải đưa vào như một phần của yêu cầu

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.