ก่อนอื่นให้ฉันอธิบายบางอย่าง:
คำจำกัดความของถั่วที่มีการจัดการ : โดยทั่วไปถั่วที่ได้รับการจัดการเป็นวัตถุที่วงจรชีวิตของมัน (การก่อสร้างการทำลาย ฯลฯ ) ถูกจัดการโดยคอนเทนเนอร์
ใน Java ee เรามีคอนเทนเนอร์มากมายที่จัดการวงจรชีวิตของอ็อบเจ็กต์เช่น JSF container, EJB container, CDI container, Servlet container เป็นต้น
คอนเทนเนอร์เหล่านี้ทั้งหมดทำงานแบบอิสระโดยจะบูตในการเริ่มต้นแอ็พพลิเคชันเซิร์ฟเวอร์และสแกนคลาสของอาร์ติแฟกต์ทั้งหมดรวมถึง jar, ejb-jar, war และ ear files ในเวลาการปรับใช้และรวบรวมและจัดเก็บข้อมูลเมตาบางอย่างเกี่ยวกับพวกเขาจากนั้นเมื่อคุณต้องการอ็อบเจ็กต์ ของคลาสที่รันไทม์พวกเขาจะให้อินสแตนซ์ของคลาสเหล่านั้นแก่คุณและหลังจากจบงานแล้วพวกเขาจะทำลายมัน
ดังนั้นเราสามารถพูดได้ว่าเรามี:
- JSF จัดการถั่ว
- ถั่วจัดการ CDI
- ถั่วจัดการ EJB
- และแม้แต่ Servlets ก็เป็นถั่วที่ได้รับการจัดการเพราะมันถูกสร้างอินสแตนซ์และทำลายโดยคอนเทนเนอร์ซึ่งเป็นคอนเทนเนอร์ของ servlet
ดังนั้นเมื่อคุณเห็นคำ Managed Bean คุณควรถามเกี่ยวกับบริบทหรือประเภทของมัน (JSF, CDI, EJB ฯลฯ )
จากนั้นคุณอาจถามว่าทำไมเราถึงมีคอนเทนเนอร์เหล่านี้มากมาย: พวก AFAIK, Java EE ต้องการมีเฟรมเวิร์กการฉีดพึ่งพา แต่ไม่สามารถรวบรวมข้อกำหนดทั้งหมดในข้อกำหนดเดียวได้เนื่องจากไม่สามารถคาดเดาข้อกำหนดในอนาคตได้และพวกเขาสร้าง EJB 1.0 ขึ้นมา 2.0 และ 3.0 และตอนนี้ 3.1 แต่เป้าหมายของ EJB เป็นเพียงข้อกำหนดบางอย่าง (ธุรกรรมโมเดลส่วนประกอบแบบกระจาย ฯลฯ )
ในเวลาเดียวกัน (ควบคู่กัน) พวกเขาตระหนักว่าพวกเขาจำเป็นต้องสนับสนุน JSF ด้วยจากนั้นพวกเขาก็สร้างถั่วที่มีการจัดการ JSF และภาชนะอื่นสำหรับถั่ว JSF และพวกเขาคิดว่ามันเป็นคอนเทนเนอร์ DI ที่โตเต็มที่ แต่ก็ยังไม่สมบูรณ์และเป็นภาชนะที่โตเต็มที่
หลังจากนั้น Gavin King และคนดีคนอื่น ๆ ;) สร้าง CDI ซึ่งเป็นคอนเทนเนอร์ DI ที่โตเต็มที่ที่สุดเท่าที่ฉันเคยเห็นมา CDI (ได้รับแรงบันดาลใจจาก Seam2, Guice และ Spring) ถูกสร้างขึ้นเพื่อเติมเต็มช่องว่างระหว่าง JSF และ EJB และสิ่งที่มีประโยชน์อื่น ๆ อีกมากมายเช่นการฉีดโพโจวิธีการของผู้ผลิตเครื่องสกัดกั้นผู้ตกแต่ง SPI การรวมความยืดหยุ่นมาก ฯลฯ และยังสามารถทำได้ ถั่วที่จัดการของ EJB และ JSF กำลังทำอะไรอยู่เราสามารถมีคอนเทนเนอร์ DI ที่โตเต็มที่และทรงพลังเพียงอันเดียว แต่ด้วยความเข้ากันได้ที่ล้าหลังและเหตุผลทางการเมืองพวก Java EE ต้องการรักษาไว้ !!!
คุณจะพบความแตกต่างและกรณีการใช้งานสำหรับแต่ละประเภทเหล่านี้ได้ที่นี่:
JSF Managed Beans, CDI Beans และ EJBs
JSF ได้รับการพัฒนาในขั้นต้นด้วย bean ที่มีการจัดการและกลไกการฉีดพึ่งพาซึ่งได้รับการปรับปรุงสำหรับ JSF 2.0 เพื่อรวมถั่วที่ใช้คำอธิบายประกอบ เมื่อ CDI เปิดตัวพร้อมกับ Java EE 6 ถือได้ว่าเป็นเฟรมเวิร์กถั่วที่มีการจัดการสำหรับแพลตฟอร์มนั้นและแน่นอนว่า EJB ล้าสมัยพวกเขาทั้งหมดที่มีมานานกว่าทศวรรษ
ปัญหาแน่นอนคือการรู้ว่าควรใช้อันไหนและใช้เมื่อใด
เริ่มต้นด้วยถั่วที่จัดการโดย JSF ที่ง่ายที่สุด
ถั่วจัดการ JSF
กล่าวโดยย่ออย่าใช้หากคุณกำลังพัฒนาสำหรับ Java EE 6 และใช้ CDI พวกเขามีกลไกง่ายๆสำหรับการฉีดพึ่งพาและกำหนดถั่วสำรองสำหรับหน้าเว็บ แต่มีประสิทธิภาพน้อยกว่าถั่ว CDI
สามารถกำหนดได้โดยใช้@javax.faces.bean.ManagedBean
คำอธิบายประกอบซึ่งใช้พารามิเตอร์ชื่อทางเลือก ชื่อนี้สามารถใช้เพื่ออ้างอิง bean จากเพจ JSF
ขอบเขตสามารถใช้กับ bean ได้โดยใช้หนึ่งในขอบเขตที่แตกต่างกันที่กำหนดไว้ในjavax.faces.bean
แพ็คเกจซึ่งรวมถึงคำขอเซสชันแอปพลิเคชันมุมมองและขอบเขตที่กำหนดเอง
@ManagedBean(name="someBean")
@RequestScoped
public class SomeBean {
....
....
}
ถั่ว JSF ไม่สามารถผสมกับถั่วชนิดอื่นได้หากไม่มีการเข้ารหัสด้วยตนเอง
ถั่ว CDI
CDI คือเฟรมเวิร์กการจัดการ bean และการพึ่งพาการฉีดที่เผยแพร่โดยเป็นส่วนหนึ่งของ Java EE 6 และรวมถึงสิ่งอำนวยความสะดวก bean ที่มีการจัดการที่สมบูรณ์และครอบคลุม ถั่ว CDI มีความก้าวหน้าและยืดหยุ่นมากกว่าถั่วที่จัดการโดย JSF พวกเขาสามารถใช้ประโยชน์จากตัวสกัดกั้นขอบเขตการสนทนาเหตุการณ์ประเภทการฉีดแบบปลอดภัยมัณฑนากรแบบแผนและวิธีการผลิต
ในการปรับใช้ CDI beans คุณต้องวางไฟล์ชื่อ beans.xml ในโฟลเดอร์ META-INF บน classpath เมื่อคุณทำเช่นนี้ทุก bean ในแพ็คเกจจะกลายเป็น CDI bean มีคุณสมบัติมากมายใน CDI ซึ่งมีมากเกินไปที่จะกล่าวถึงที่นี่ แต่เพื่อเป็นการอ้างอิงอย่างรวดเร็วสำหรับคุณลักษณะที่คล้าย JSF คุณสามารถกำหนดขอบเขตของ CDI bean โดยใช้ขอบเขตใดขอบเขตหนึ่งที่กำหนดไว้ในjavax.enterprise.context
แพ็คเกจ (ได้แก่ คำขอการสนทนา ขอบเขตเซสชันและแอปพลิเคชัน) หากคุณต้องการใช้ CDI bean จากเพจ JSF คุณสามารถตั้งชื่อโดยใช้javax.inject.Named
คำอธิบายประกอบ ในการฉีดถั่วลงในถั่วอื่นคุณต้องใส่คำอธิบายประกอบฟิลด์ด้วยjavax.inject.Inject
คำอธิบายประกอบ
@Named("someBean")
@RequestScoped
public class SomeBean {
@Inject
private SomeService someService;
}
การฉีดอัตโนมัติตามที่กำหนดไว้ข้างต้นสามารถควบคุมได้โดยใช้ Qualifiers ที่ช่วยจับคู่คลาสเฉพาะที่คุณต้องการฉีด หากคุณมีประเภทการชำระเงินหลายประเภทคุณอาจเพิ่มตัวระบุว่าเป็นแบบอะซิงโครนัสหรือไม่ แม้ว่าคุณจะสามารถใช้@Named
คำอธิบายประกอบเป็นตัวกำหนดคุณสมบัติได้ แต่คุณไม่ควรมีไว้สำหรับการเปิดเผยถั่วใน EL
CDI จัดการการฉีดถั่วที่มีขอบเขตที่ไม่ตรงกันผ่านการใช้พร็อกซี ด้วยเหตุนี้คุณจึงสามารถฉีด scoped bean ลงใน session scoped bean ได้และการอ้างอิงจะยังคงใช้ได้ในแต่ละคำขอเนื่องจากแต่ละคำขอพร็อกซีจะเชื่อมต่อกับอินสแตนซ์ที่ใช้งานจริงของสโคปที่ร้องขออีกครั้ง
CDI ยังรองรับผู้สกัดกั้นเหตุการณ์ขอบเขตการสนทนาใหม่และคุณสมบัติอื่น ๆ อีกมากมายซึ่งทำให้เป็นตัวเลือกที่ดีกว่าถั่วที่จัดการโดย JSF
EJB
EJBs มีเมล็ด CDI ก่อนหน้านี้และอยู่ในบางวันคล้ายกับถั่ว CDI และในลักษณะอื่น ๆ ที่แตกต่างกันมาก โดยพื้นฐานแล้วความแตกต่างระหว่างถั่ว CDI และ EJB คือ EJB คือ:
- การทำธุรกรรม
- ระยะไกลหรือในพื้นที่
- สามารถส่งเมล็ดถั่วที่มีสถานะว่างได้โดยไม่ต้องใช้ทรัพยากร
- สามารถใช้ตัวจับเวลาได้
- สามารถเป็นแบบอะซิงโครนัสได้
EJB สองประเภทเรียกว่าไร้สัญชาติและไร้สัญชาติ EJB แบบไร้สถานะอาจถือได้ว่าเป็นเธรดแบบใช้ครั้งเดียวที่ปลอดภัยซึ่งไม่คงสถานะใด ๆ ระหว่างคำขอเว็บสองรายการ EJB ที่มีสถานะเป็นสถานะและสามารถสร้างและนั่งเฉยๆได้ตราบเท่าที่จำเป็นจนกว่าจะถูกกำจัดทิ้ง
การกำหนด EJB นั้นง่ายมากเพียงแค่เพิ่ม a javax.ejb.Stateless
หรือjavax.ejb.Stateful
คำอธิบายประกอบลงในคลาส
@Stateless
public class BookingService {
public String makeReservation(Item Item, Customer customer) {
...
...
}
}
ถั่วไร้สัญชาติต้องมีขอบเขตที่พึ่งพาในขณะที่ถั่วเซสชันที่มีสถานะสามารถมีขอบเขตใดก็ได้ โดยค่าเริ่มต้นจะเป็นธุรกรรม แต่คุณสามารถใช้คำอธิบายประกอบแอตทริบิวต์ธุรกรรมได้
ในขณะที่ EJB และถั่ว CDI มีความแตกต่างกันมากในแง่ของคุณสมบัติการเขียนโค้ดเพื่อรวมเข้าด้วยกันนั้นคล้ายกันมากเนื่องจากสามารถฉีดถั่ว CDI ลงใน EJBs และ EJBs สามารถฉีดเข้าไปในเมล็ด CDI ได้ ไม่จำเป็นต้องสร้างความแตกต่างใด ๆ เมื่อฉีดเข้าไปในอีกอัน อีกครั้งขอบเขตที่แตกต่างกันได้รับการจัดการโดย CDI ผ่านการใช้พร็อกซี ข้อยกเว้นประการหนึ่งคือ CDI ไม่สนับสนุนการฉีด EJB ระยะไกล แต่สามารถใช้งานได้โดยการเขียนวิธีการผลิตอย่างง่ายสำหรับมัน
javax.inject.Named
คำอธิบายประกอบเช่นเดียวกับบ่นใด ๆ ที่สามารถนำมาใช้ใน EJB เพื่อให้ตรงกับมันไปยังจุดฉีด
ควรใช้ถั่วเมื่อใด
คุณรู้ได้อย่างไรว่าเมื่อใดควรใช้ถั่วชนิดใด? เรียบง่าย
อย่าใช้ถั่วที่มีการจัดการ JSF เว้นแต่คุณจะทำงานในคอนเทนเนอร์ servlet และไม่ต้องการลองให้ CDI ทำงานใน Tomcat (แม้ว่าจะมีแม่แบบ Maven อยู่บ้างก็ตามดังนั้นจึงไม่มีข้อแก้ตัว)
โดยทั่วไปคุณควรใช้ถั่ว CDI เว้นแต่คุณต้องการฟังก์ชันขั้นสูงที่มีอยู่ใน EJB เช่นฟังก์ชันการทำธุรกรรม คุณสามารถเขียน interceptor ของคุณเองเพื่อทำธุรกรรม CDI beans ได้ แต่สำหรับตอนนี้การใช้ EJB จะง่ายกว่าจนกว่า CDI จะได้รับ CDI beans ที่ทำธุรกรรมซึ่งอยู่ใกล้ ๆ หากคุณติดอยู่ในคอนเทนเนอร์ servlet และกำลังใช้ CDI ธุรกรรมที่เขียนด้วยมือหรือตัวสกัดกั้นธุรกรรมของคุณเองจะเป็นทางเลือกเดียวที่ไม่มี EJB
หากคุณจำเป็นต้องใช้@ViewScoped
ใน CDI คุณควร
- ใช้ตะเข็บหน้าหรือMyFaces CODIโมดูลเพียงเพิ่มหนึ่งในนั้นใน classpath ของคุณและ
@ViewScoped
จะทำงานใน CDI MyFaces CODI รองรับ @ViewScoped ที่มั่นคงยิ่งขึ้น
- ใช้ MyFaces CODI
@ViewAccessScoped
ซึ่งเป็นส่วนขยายที่เขียนไว้ด้านบนของ CDI โดย Apache เพียงดาวน์โหลดและใช้@ViewAccessScoped
คำอธิบายประกอบแทน@ViewScoped
คำอธิบายประกอบแทน
- ใช้ CDI
@ConversationScoped
และทำให้ใช้งานได้นาน ดูข้อมูลเพิ่มเติมได้ที่นี่ได้ที่นี่
- ใช้Omnifaces @ViewScoped คำอธิบายประกอบ
บางส่วนเบอร์เบิ้นจากที่นี่