จะใช้ EJB 3.1 และ CDI ได้ที่ไหน?


120

ฉันกำลังสร้างผลิตภัณฑ์ที่ใช้ Java EE ซึ่งฉันใช้GlassFish 3 และ EJB 3.1

แอปพลิเคชันของฉันมีเซสชั่นบีนตัวกำหนดตารางเวลาและใช้บริการเว็บ ฉันเพิ่งมารู้เกี่ยวกับApache TomEEซึ่งสนับสนุนบริบทและพึ่งพาการฉีด (CDI) คอนเทนเนอร์ GlassFish ยังรองรับ CDI

ฉันสามารถเปลี่ยนถั่วเซสชั่นโดยที่ฉันไม่ต้องการคุณสมบัติใด ๆ ที่ CDI ยังไม่มีให้ได้หรือไม่? แล้วถ้าอย่างนั้นฉันจะได้รับประโยชน์อะไรบ้าง?

คำตอบ:


409

ใช่คุณสามารถผสมทั้ง CDI และ EJB ได้อย่างอิสระและได้ผลลัพธ์ที่ยอดเยี่ยม ดูเหมือนว่าคุณกำลังใช้@WebServiceและ@Scheduleซึ่งเป็นเหตุผลที่ดีในการเพิ่ม EJB ลงในมิกซ์

มีความสับสนมากมายดังนั้นนี่คือข้อมูลทั่วไปเกี่ยวกับ EJB และ CDI ที่เกี่ยวข้องกัน

EJB> = CDI

โปรดทราบว่า EJB เป็นถั่ว CDI ดังนั้นจึงมีประโยชน์ทั้งหมดของ CDI การย้อนกลับไม่เป็นความจริง (ยัง) ดังนั้นอย่าติดนิสัยคิดว่า "EJB vs CDI" เพราะตรรกะนั้นแปลเป็น "EJB + CDI vs CDI" ซึ่งเป็นสมการที่แปลก

ในอนาคตของ Java EE เราจะดำเนินการจัดแนวต่อไป สิ่งที่สอดคล้องวิธีคือการอนุญาตให้คนที่จะทำสิ่งที่พวกเขาอยู่แล้วสามารถทำได้เพียงโดยไม่ต้อง@Stateful, @Statelessหรือ@Singletonคำอธิบายประกอบที่ด้านบน

EJB และ CDI ในเงื่อนไขการใช้งาน

ในที่สุด EJB และ CDI ก็มีการออกแบบพื้นฐานเดียวกันในการเป็นส่วนประกอบพร็อกซี เมื่อคุณได้รับการอ้างอิงถึง EJB หรือ CDI bean นั่นไม่ใช่ถั่วจริง แต่วัตถุที่คุณได้รับนั้นเป็นของปลอม (พร็อกซี) เมื่อคุณเรียกใช้เมธอดในวัตถุปลอมนี้สายจะไปที่คอนเทนเนอร์ซึ่งจะส่งการโทรผ่านผู้สกัดกั้นผู้ตกแต่ง ฯลฯ รวมทั้งดูแลธุรกรรมหรือการตรวจสอบความปลอดภัย เมื่อทุกอย่างเสร็จสิ้นการโทรจะไปที่วัตถุจริงในที่สุดและผลลัพธ์จะถูกส่งกลับผ่านพร็อกซีไปยังผู้โทร

ความแตกต่างมาจากวิธีการแก้ไขวัตถุที่จะเรียกใช้เท่านั้น โดยการ "แก้ไขแล้ว" เราหมายถึงว่าคอนเทนเนอร์มองหาอินสแตนซ์จริงที่จะเรียกใช้ที่ไหนและอย่างไร

ใน CDI คอนเทนเนอร์จะมีลักษณะเป็น "ขอบเขต" ซึ่งโดยพื้นฐานแล้วจะเป็นแฮชแมปที่อยู่ในช่วงเวลาหนึ่ง (ตามคำขอ@RequestScopedต่อเซสชัน HTTP @SessionScopedต่อแอปพลิเคชัน@ApplicationScopedการสนทนา JSF @ConversationScopedหรือตามการใช้งานขอบเขตที่คุณกำหนดเอง)

ใน EJB ภาชนะที่มีลักษณะยังเข้า HashMap @Statefulถ้าถั่วเป็นประเภท @Statefulถั่วนอกจากนี้ยังสามารถใช้ใด ๆ ของคำอธิบายประกอบขอบเขตข้างต้นทำให้มันมีชีวิตอยู่และตายกับทุกถั่วอื่น ๆ ในขอบเขต ใน EJB @Statefulนั้นโดยพื้นฐานแล้วถั่ว "ขอบเขตใด ๆ " @Statelessเป็นพื้นสระว่ายน้ำเช่น - คุณจะได้รับตัวอย่างจากสระว่ายน้ำในช่วงระยะเวลาหนึ่งการภาวนา @Singletonเป็นหลัก@ApplicationScoped

ดังนั้นในระดับพื้นฐานสิ่งที่คุณสามารถทำได้กับถั่ว "EJB" คุณควรจะทำได้ด้วยถั่ว "CDI" ภายใต้ผ้าคลุมมันยากมากที่จะแยกออกจากกัน ท่อประปาทั้งหมดจะเหมือนกันยกเว้นวิธีการแก้ไขอินสแตนซ์

ขณะนี้พวกเขาไม่เหมือนกันในแง่ของบริการที่คอนเทนเนอร์จะเสนอเมื่อทำพร็อกซีนี้ แต่อย่างที่ฉันบอกว่าเรากำลังดำเนินการอยู่ในระดับข้อมูลจำเพาะ Java EE

หมายเหตุประสิทธิภาพ

อย่ามองข้ามภาพจิตที่ "เบา" หรือ "หนัก" ที่คุณอาจมี นั่นคือการตลาดทั้งหมด พวกเขามีการออกแบบภายในที่เหมือนกันเป็นส่วนใหญ่ ความละเอียดของอินสแตนซ์ CDI อาจซับซ้อนกว่าเล็กน้อยเนื่องจากมีความไดนามิกและบริบทมากกว่าเล็กน้อย ความละเอียดของอินสแตนซ์ EJB ค่อนข้างคงที่เป็นใบ้และง่ายเมื่อเปรียบเทียบ

ฉันสามารถบอกคุณได้จากมุมมองการใช้งานใน TomEE มีความแตกต่างของประสิทธิภาพเป็นศูนย์ระหว่างการเรียกใช้ EJB กับการเรียกใช้ CDI bean

ค่าดีฟอลต์คือ POJO ตามด้วย CDI ตามด้วย EJB

แน่นอนอย่าใช้ CDI หรือ EJB เมื่อไม่มีประโยชน์ โยน CDI เมื่อคุณเริ่มต้องการการฉีดยาเหตุการณ์ตัวสกัดกั้นนักตกแต่งการติดตามอายุการใช้งานและสิ่งต่างๆเช่นนั้น นั่นคือเวลาส่วนใหญ่

เกินพื้นฐานเหล่านั้นมีจำนวนของบริการภาชนะที่มีประโยชน์ที่คุณมีตัวเลือกที่จะใช้ถ้าคุณทำถั่ว CDI ของคุณยังมี EJB โดยการเพิ่ม@Stateful, @Statelessหรือ@Singletonเกี่ยวกับมัน

นี่คือรายการสั้น ๆ ของเวลาที่ฉันแยก EJB ออกมา

ใช้ JAX-WS

เปิดเผย @WebServiceJAX-WS ฉันขี้เกียจ. เมื่อ@WebServiceเป็น EJB ด้วยคุณไม่จำเป็นต้องแสดงรายการและแมปเป็น servlet ในweb.xmlไฟล์ นั่นได้ผลสำหรับฉัน นอกจากนี้ฉันยังได้รับตัวเลือกในการใช้ฟังก์ชันอื่น ๆ ที่กล่าวถึงด้านล่าง ดังนั้นมันจึงไม่ใช่เรื่องง่ายสำหรับฉัน

มีให้@Statelessและ@Singletonเท่านั้น

ใช้ JAX-RS

การเปิดเผยทรัพยากร JAX-RS ผ่าน@Path. ฉันยังคงขี้เกียจ เมื่อบริการ RESTful เป็น EJB คุณจะได้รับการค้นหาอัตโนมัติอีกครั้งและไม่ต้องเพิ่มลงในApplicationคลาสย่อยJAX-RS หรืออะไรทำนองนั้น นอกจากนี้ฉันยังสามารถเปิดเผยถั่วชนิดเดียวกันกับที่@WebServiceฉันต้องการหรือใช้ฟังก์ชันที่ยอดเยี่ยมใด ๆ ที่กล่าวถึงด้านล่าง

มีให้@Statelessและ@Singletonเท่านั้น

ตรรกะการเริ่มต้น

โหลดเมื่อเริ่มต้นผ่าน@Startup. ขณะนี้ไม่มีสิ่งนี้เทียบเท่าใน CDI เราพลาดการเพิ่มบางอย่างเช่นAfterStartupเหตุการณ์ในวงจรชีวิตคอนเทนเนอร์ ได้เราทำแบบนี้คุณก็จะได้มี@ApplicationScopedถั่วที่ฟังมันและที่จะได้อย่างมีประสิทธิภาพเช่นเดียวกับกับ@Singleton @Startupอยู่ในรายชื่อ CDI 1.1

มีให้@Singletonเฉพาะ

ทำงานแบบขนาน

@Asynchronousการเรียกใช้วิธีการ เธรดเริ่มต้นเป็น no-no ในสภาพแวดล้อมฝั่งเซิร์ฟเวอร์ใด ๆ การมีเธรดมากเกินไปเป็นตัวทำลายประสิทธิภาพที่ร้ายแรง คำอธิบายประกอบนี้ช่วยให้คุณสามารถขนานสิ่งที่คุณทำโดยใช้เธรดพูลของคอนเทนเนอร์ นี่มันเจ๋งมาก.

พร้อมใช้งาน@Stateful, และ@Stateless@Singleton

กำหนดเวลาการทำงาน

@ScheduleหรือScheduleExpressionโดยพื้นฐานแล้วเป็น cron หรือQuartzฟังก์ชันการทำงาน ยังยอดเยี่ยมมาก ภาชนะส่วนใหญ่ใช้ควอตซ์ใต้ฝาปิดสำหรับสิ่งนี้ อย่างไรก็ตามคนส่วนใหญ่ไม่รู้ว่าการจัดตารางการทำงานใน Java EE นั้นเป็นการทำธุรกรรม! หากคุณอัปเดตฐานข้อมูลแล้วกำหนดเวลางานบางส่วนและหนึ่งในนั้นล้มเหลวทั้งสองอย่างจะถูกล้างโดยอัตโนมัติ หากการEntityManagerโทรที่ยังคงอยู่ล้มเหลวหรือมีปัญหาในการล้างก็ไม่จำเป็นต้องยกเลิกการกำหนดเวลาการทำงาน ใช่การทำธุรกรรม

มีให้@Statelessและ@Singletonเท่านั้น

การใช้ EntityManagers ในธุรกรรม JTA

หมายเหตุข้างต้นในการทำธุรกรรมแน่นอนคุณจะต้องใช้การบริหารจัดการJTA EntityManagerคุณสามารถใช้มันกับ "CDI" ธรรมดา แต่ถ้าไม่มีธุรกรรมที่จัดการกับคอนเทนเนอร์ก็จะได้รับUserTransactionตรรกะการคอมมิต / ย้อนกลับซ้ำซากจำเจ

สามารถใช้ได้กับทุกส่วนประกอบ Java EE รวมทั้ง CDI, JSF @ManagedBean, @WebServlet, @WebListener, @WebFilterฯลฯ@TransactionAttributeคำอธิบายประกอบ แต่สามารถใช้ได้กับ@Stateful, @Statelessและ@Singletonเพียง

การจัดการ JTA EntityManager

การEXTENDEDจัดการEntityManagerช่วยให้คุณสามารถEntityManagerเปิดระหว่างJTAธุรกรรมและไม่สูญเสียข้อมูลแคช คุณลักษณะที่ดีสำหรับเวลาและสถานที่ที่เหมาะสม ใช้อย่างมีความรับผิดชอบ :)

มีให้@Statefulเฉพาะ

ซิงโครไนซ์ง่าย

เมื่อคุณต้องการซิงโครไนซ์คำอธิบายประกอบ@Lock(READ)และ@Lock(WRITE)คำอธิบายประกอบก็ค่อนข้างยอดเยี่ยม ช่วยให้คุณได้รับการจัดการการเข้าถึงพร้อมกันได้ฟรี ข้ามท่อประปา ReentrantReadWriteLock ทั้งหมด ในที่เก็บข้อมูลเดียวกันคือ@AccessTimeoutซึ่งช่วยให้คุณสามารถบอกได้ว่าเธรดควรรอนานแค่ไหนเพื่อเข้าถึงอินสแตนซ์ bean ก่อนที่จะยอมแพ้

ใช้ได้กับ@Singletonถั่วเท่านั้น


32
สวรรค์ที่ดีดาวิด :) ฉันคิดว่าคุณครอบคลุมมัน
LightGuard

7
ขอบคุณสำหรับคำตอบนี้ คุณล้างสิ่งอุดตันในหัวของฉันและเชื่อมต่อจุดต่างๆมากมาย
พฤหัสบดี

7
นี่เป็นคำอธิบายที่ดีที่สุดในหัวข้อนั้นที่ฉันเคยอ่าน นอกจากนี้ยังครอบคลุมประเด็นสำคัญเกือบทั้งหมดของ EJB ในการใช้งานจริงอีกด้วย การทำงานที่ดี!!
nanoquack

3
เข้าใจได้มากและอดัมไม่ผิดในแง่กฎหมายที่เข้มงวด แต่ความแตกต่างคือการสงสัย ข้อมูลจำเพาะระบุว่าอินสแตนซ์ EJB ไม่ใช่บริบท แต่ต่อมาการอ้างอิง (พร็อกซี) ไปยัง EJB เป็นบริบท วงจรชีวิตของ Stateful bean ถูกควบคุมทั้งหมดผ่านการอ้างอิง (พร็อกซี) ดังนั้นเมื่อคอนเทนเนอร์ CDI ควบคุมการอ้างอิงนั้น (พร็อกซี) คณิตศาสตร์จะออกมาเหมือนกัน - Stateful EJBs สามารถเป็นบริบทได้อย่างมีประสิทธิภาพ
David Blevins

4
คำตอบนี้มาจากปี 2012 เรามีการอัปเดตล่าสุดหรือไม่?
อับบาส

2

หากคุณไม่ได้ใช้คุณสมบัติใด ๆ ของ ejb 3.1 คำตอบนั้นง่ายมาก แต่เดาว่าการสืบเสาะของคุณบ่งชี้ว่าคุณสงสัยว่ามีแนวคิด ejb 3.1 ที่คุณได้รับประโยชน์จากโดยที่คุณไม่รู้ตัว ตัวอย่างหนึ่งอาจเป็นไปได้ว่าคอนเทนเนอร์สามารถเก็บพูลของ slsb ไว้พร้อมใช้งานเพื่อให้ jms และการเชื่อมต่อฐานข้อมูลไม่ต้องฉีดเป็นส่วนหนึ่งของคำขอ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.