Trước hết, hãy để tôi làm rõ một số điều:
Định nghĩa bean được quản lý : nói chung bean được quản lý là một đối tượng mà vòng đời của nó (xây dựng, phá hủy, v.v.) được quản lý bởi một vùng chứa.
Trong Java ee, chúng ta có nhiều vùng chứa quản lý vòng đời của các đối tượng của chúng, như vùng chứa JSF, vùng chứa EJB, vùng chứa CDI, vùng chứa Servlet, v.v.
Tất cả các vùng chứa này hoạt động độc lập, chúng khởi động trong quá trình khởi tạo máy chủ ứng dụng và quét các lớp của tất cả các hiện vật bao gồm tệp jar, ejb-jar, war và ear trong thời gian triển khai, đồng thời thu thập và lưu trữ một số siêu dữ liệu về chúng, sau đó khi bạn cần một đối tượng của một lớp trong thời gian chạy, họ sẽ cung cấp cho bạn các cá thể của các lớp đó và sau khi hoàn thành công việc, họ sẽ hủy chúng.
Vì vậy, chúng ta có thể nói rằng chúng ta có:
- Đậu được quản lý JSF
- CDI quản lý đậu
- EJB quản lý đậu
- Và ngay cả Servlet cũng được quản lý bean vì chúng được khởi tạo và phá hủy bởi một container, đó là một thùng chứa servlet.
Vì vậy, khi bạn nhìn thấy từ Managed Bean, bạn nên hỏi về ngữ cảnh hoặc loại của nó. (JSF, CDI, EJB, v.v.)
Sau đó, bạn có thể hỏi tại sao chúng tôi có nhiều vùng chứa này: AFAIK, Java EE guys muốn có một khung phụ thuộc chèn ép, nhưng họ không thể tập hợp tất cả các yêu cầu trong một đặc điểm kỹ thuật vì họ không thể dự đoán các yêu cầu trong tương lai và họ đã tạo ra EJB 1.0 và sau đó 2.0, sau đó là 3.0 và bây giờ là 3.1 nhưng mục tiêu của EJB chỉ dành cho một số yêu cầu (giao dịch, mô hình thành phần phân tán, v.v.).
Đồng thời (song song) họ nhận ra rằng họ cũng cần hỗ trợ JSF, sau đó họ tạo các bean được quản lý JSF và một vùng chứa khác cho các hạt JSF và họ coi đó là một vùng chứa DI trưởng thành, nhưng nó vẫn chưa phải là vùng chứa hoàn chỉnh và trưởng thành.
Sau đó Gavin King và một số anh chàng tốt bụng khác;) đã tạo ra CDI, đây là bộ chứa DI trưởng thành nhất mà tôi từng thấy. CDI (lấy cảm hứng từ Seam2, Guice và Spring) được tạo ra để lấp đầy khoảng cách giữa JSF và EJB và rất nhiều thứ hữu ích khác như pojo injection, producer method, interceptors, decorator, tích hợp SPI, rất linh hoạt, v.v. và nó thậm chí có thể làm được những gì các bean được quản lý bởi EJB và JSF đang làm thì chúng ta có thể chỉ có một vùng chứa DI trưởng thành và mạnh mẽ. Nhưng vì một số lý do tương thích ngược và lý do chính trị nên các chàng trai Java EE muốn giữ chúng !!!
Tại đây, bạn có thể tìm thấy sự khác biệt và các trường hợp sử dụng cho từng loại này:
Đậu được quản lý JSF, Đậu CDI và EJB
JSF ban đầu được phát triển với cơ chế tiêm phụ thuộc và bean được quản lý của riêng nó, cơ chế này đã được cải tiến cho JSF 2.0 để bao gồm các bean dựa trên chú thích. Khi CDI được phát hành cùng với Java EE 6, nó được coi là khung bean được quản lý cho nền tảng đó và tất nhiên, các EJB đã lỗi thời tất cả chúng đã tồn tại hơn một thập kỷ.
Tất nhiên, vấn đề là biết sử dụng cái nào và khi nào thì sử dụng chúng.
Hãy bắt đầu với các bean được quản lý JSF đơn giản nhất.
Đậu được quản lý JSF
Tóm lại, không sử dụng chúng nếu bạn đang phát triển cho Java EE 6 và sử dụng CDI. Chúng cung cấp một cơ chế đơn giản để tiêm phụ thuộc và xác định các hạt hỗ trợ cho các trang web, nhưng chúng kém mạnh hơn nhiều so với các hạt CDI.
Chúng có thể được xác định bằng cách sử dụng @javax.faces.bean.ManagedBean
chú thích có tham số tên tùy chọn. Tên này có thể được sử dụng để tham chiếu bean từ các trang JSF.
Phạm vi có thể được áp dụng cho bean bằng cách sử dụng một trong các phạm vi khác nhau được xác định trong javax.faces.bean
gói bao gồm phạm vi yêu cầu, phiên, ứng dụng, chế độ xem và tùy chỉnh.
@ManagedBean(name="someBean")
@RequestScoped
public class SomeBean {
....
....
}
Không thể trộn đậu JSF với các loại đậu khác nếu không có một số loại mã hóa thủ công.
CDI đậu
CDI là framework quản lý bean và phụ thuộc được phát hành như một phần của Java EE 6 và nó bao gồm một cơ sở bean được quản lý toàn diện, hoàn chỉnh. Các hạt CDI tiên tiến và linh hoạt hơn nhiều so với các hạt được quản lý JSF đơn giản. Họ có thể sử dụng các thiết bị đánh chặn, phạm vi hội thoại, Sự kiện, kiểu tiêm an toàn, người trang trí, khuôn mẫu và phương pháp của nhà sản xuất.
Để triển khai các bean CDI, bạn phải đặt một tệp có tên là bean.xml trong thư mục META-INF trên classpath. Khi bạn làm điều này, thì mỗi hạt đậu trong gói sẽ trở thành hạt đậu CDI. Có rất nhiều tính năng trong CDI, quá nhiều tính năng cần trình bày ở đây, nhưng để tham khảo nhanh các tính năng giống JSF, bạn có thể xác định phạm vi của bean CDI bằng cách sử dụng một trong các phạm vi được xác định trong javax.enterprise.context
gói (cụ thể là yêu cầu, hội thoại , phạm vi phiên và ứng dụng). Nếu bạn muốn sử dụng bean CDI từ trang JSF, bạn có thể đặt tên cho nó bằng cách sử dụng javax.inject.Named
chú thích. Để chèn một hạt đậu vào một hạt đậu khác, bạn chú thích trường bằng javax.inject.Inject
chú thích.
@Named("someBean")
@RequestScoped
public class SomeBean {
@Inject
private SomeService someService;
}
Việc tiêm tự động như được định nghĩa ở trên có thể được kiểm soát thông qua việc sử dụng Bộ định lượng có thể giúp khớp với lớp cụ thể mà bạn muốn tiêm. Nếu bạn có nhiều hình thức thanh toán, bạn có thể thêm bộ định lượng để xem nó có phải là không đồng bộ hay không. Mặc dù bạn có thể sử dụng @Named
chú thích như một định nghĩa, nhưng bạn không nên sử dụng chú thích vì nó được cung cấp để hiển thị các hạt đậu trong EL.
CDI xử lý việc tiêm hạt đậu với phạm vi không khớp thông qua việc sử dụng proxy. Do đó, bạn có thể đưa một bean phạm vi yêu cầu vào một bean phạm vi phiên và tham chiếu sẽ vẫn hợp lệ trên mỗi yêu cầu vì đối với mỗi yêu cầu, proxy lại kết nối với một phiên bản trực tiếp của bean phạm vi yêu cầu.
CDI cũng có hỗ trợ cho các trình đánh chặn, sự kiện, phạm vi hội thoại mới và nhiều tính năng khác khiến nó trở thành một lựa chọn tốt hơn nhiều so với các hạt được quản lý JSF.
EJB
EJB có trước đậu CDI và về mặt nào đó tương tự như đậu CDI và theo những cách khác thì rất khác. Về cơ bản, sự khác biệt giữa các hạt CDI và EJB là các EJB là:
- Giao dịch
- Từ xa hoặc cục bộ
- Có thể thụ động đậu trạng thái giải phóng tài nguyên
- Có thể sử dụng bộ hẹn giờ
- Có thể không đồng bộ
Hai loại EJB được gọi là không trạng thái và trạng thái. Các EJB không trạng thái có thể được coi là các hạt đậu sử dụng một lần an toàn cho luồng không duy trì bất kỳ trạng thái nào giữa hai yêu cầu web. Các EJB trạng thái có trạng thái lưu giữ và có thể được tạo và ngồi xung quanh miễn là chúng cần thiết cho đến khi chúng được xử lý.
Định nghĩa một EJB rất đơn giản, bạn chỉ cần thêm một javax.ejb.Stateless
hoặc javax.ejb.Stateful
chú thích vào lớp.
@Stateless
public class BookingService {
public String makeReservation(Item Item, Customer customer) {
...
...
}
}
Đậu không trạng thái phải có phạm vi phụ thuộc trong khi đậu phiên trạng thái có thể có bất kỳ phạm vi nào. Theo mặc định, chúng là giao dịch, nhưng bạn có thể sử dụng chú thích thuộc tính giao dịch.
Trong khi các EJB và CDI đậu rất khác nhau về các tính năng, việc viết mã để tích hợp chúng rất giống nhau vì các hạt CDI có thể được tiêm vào EJB và các EJB có thể được tiêm vào các hạt CDI. Không cần phân biệt khi tiêm cái này vào cái kia. Một lần nữa, các phạm vi khác nhau được CDI xử lý thông qua việc sử dụng proxy. Một ngoại lệ cho điều này là CDI không hỗ trợ việc đưa vào các EJB từ xa nhưng điều đó có thể được thực hiện bằng cách viết một phương thức nhà sản xuất đơn giản cho nó.
Các javax.inject.Named
chú thích cũng như bất kỳ Qualifiers có thể được sử dụng trên một EJB để phù hợp với nó vào một điểm tiêm.
Khi nào dùng đậu nào
Làm thế nào để bạn biết khi sử dụng đậu? Đơn giản.
Không bao giờ sử dụng các bean được quản lý JSF trừ khi bạn đang làm việc trong một thùng chứa servlet và không muốn thử và bắt CDI hoạt động trong Tomcat (mặc dù có một số nguyên mẫu của Maven cho điều đó nên không có lý do gì).
Nói chung, bạn nên sử dụng các hạt CDI trừ khi bạn cần chức năng nâng cao có sẵn trong EJB, chẳng hạn như các chức năng giao dịch. Bạn có thể viết bộ đánh chặn của riêng mình để thực hiện giao dịch các hạt CDI, nhưng hiện tại, việc sử dụng EJB đơn giản hơn cho đến khi CDI nhận được các hạt CDI giao dịch đang ở gần. Nếu bạn bị mắc kẹt trong vùng chứa servlet và đang sử dụng CDI, thì giao dịch viết tay hoặc công cụ chặn giao dịch của riêng bạn là lựa chọn duy nhất không có EJB.
Nếu bạn cần sử dụng @ViewScoped
trong CDI, bạn nên
- sử dụng mặt đường may hoặc mô-đun MyFaces CODI . chỉ cần thêm một trong số chúng vào classpath của bạn và
@ViewScoped
sẽ hoạt động trong CDI. MyFaces CODI có sự hỗ trợ vững chắc hơn của @ViewScoped
- sử dụng MyFaces CODI's
@ViewAccessScoped
, nó là một phần mở rộng được Apache viết trên CDI, chỉ cần tải xuống và sử dụng @ViewAccessScoped
chú thích thay vì @ViewScoped
.
- Sử dụng CDI
@ConversationScoped
và làm cho nó hoạt động lâu dài. Xem ở đây để biết thêm thông tin .
- Sử dụng Omnifaces @ViewScoped chú thích
Một số phần bị ăn cắp từ đây .