ถั่วสำรอง (@ManagedBean) หรือ CDI Beans (@Named)?


109

ฉันเพิ่งเริ่มอ่านผ่านCore JavaServer Faces, 3rd Ed และพวกเขาพูดแบบนี้ (เน้นของฉัน):

เป็นอุบัติเหตุทางประวัติศาสตร์ที่มีกลไกสองอย่างแยกกันคือถั่ว CDI และถั่วที่จัดการโดย JSF สำหรับถั่วที่สามารถใช้ในหน้า JSF ได้ เราขอแนะนำให้คุณใช้เมล็ดพันธุ์ CDIเว้นแต่ว่าแอปพลิเคชันของคุณจะต้องใช้งานกับ servlet runner ธรรมดาเช่น Tomcat

ทำไม? พวกเขาไม่ได้ให้เหตุผลใด ๆ ฉันใช้@ManagedBeanสำหรับถั่วทั้งหมดในแอปพลิเคชันต้นแบบที่ทำงานบน GlassFish 3 และฉันไม่ได้สังเกตเห็นปัญหาใด ๆ เกี่ยวกับสิ่งนี้เลย ฉันไม่ได้โดยเฉพาะอย่างยิ่งใจย้ายจาก@ManagedBeanไป@Namedแต่ฉันต้องการที่จะรู้ว่าทำไมฉันจึงควรรำคาญ



4
@Bozho: คำถามนั้นค่อนข้างคล้ายกัน แต่หลังจากอ่านคำตอบของ Pascal สองสามครั้งฉันก็ยังไม่เข้าใจว่าทำไม CDI ถึงเหนือกว่ามาก ฉันไม่รู้จัก CDIและฉันมีความสุขที่ได้เรียนรู้เพราะ "ดีกว่า" ทำไมถึงดีขึ้น?
Matt Ball

"เว้นแต่ว่าแอปพลิเคชันของคุณจะต้องใช้กับ servlet runner แบบธรรมดาเช่น Tomcat" ฉันใช้เฉพาะ tomcat และฉันขอแนะนำให้ใช้ CDI Tomcat สามารถรองรับได้ดี
Karl Kildén

1
@ KarlKildén "plain servlet runner" หมายถึงคอนเทนเนอร์ servlet ที่ไม่สามารถใช้ CDI ได้ ในขณะที่เขียน Tomcat ไม่สนับสนุน CDI ยกเว้นมีเวทมนตร์เล็กน้อย
Thorbjørn Ravn Andersen

คำตอบ:


64

CDI เป็นที่ต้องการมากกว่า JSF ธรรมดาเนื่องจาก CDI อนุญาตให้ใช้ JavaEE-wide dependency injection คุณยังสามารถฉีด POJO และปล่อยให้จัดการได้ ด้วย JSF คุณสามารถฉีดส่วนย่อยของสิ่งที่คุณสามารถทำได้ด้วย CDI เท่านั้น


โดยพื้นฐานแล้วฉันสามารถฉีดอินสแตนซ์ของเกือบทุกคลาส (หากมี "ของที่ถูกต้อง" - มันคืออะไรเป็นเพียงตัวสร้างที่ไม่มีอาร์กิวเมนต์? ) กับ CDI ในขณะที่ฉันต้องใช้@ManagedBeanถ้าฉันต้องการฉีดแบบธรรมดา JSF?
Matt Ball

3
@MattBall Matt หลังจากคุณหลายปีคุณสามารถแสดงความคิดเห็นเกี่ยวกับการย้ายข้อมูลนี้ได้หรือไม่?
Koray Tugay

5
@KorayTugay ฉันไม่ได้แตะรหัสนี้ตั้งแต่เดือนมิถุนายน 2554 แต่ฉันเปลี่ยนไปใช้ CDI และสิ่งต่างๆก็ใช้ได้ดี ฉันยินดีที่จะตอบคำถามใด ๆ เพื่อความทรงจำที่ดีที่สุดหากคุณมีคำถามเหล่านี้
Matt Ball

170

ใช้ CDI

เป็นต่อ JSF 2.3 @ManagedBeanจะเลิก โปรดดูปัญหาข้อมูลจำเพาะ 1417ด้วย ซึ่งหมายความว่ามีไม่ได้อีกต่อเหตุผลที่จะเลือกมากกว่า@ManagedBean @Namedสิ่งนี้ถูกนำมาใช้ครั้งแรกใน Mojarra 2.3.0 เบต้าเวอร์ชัน m06

ใส่คำอธิบายภาพที่นี่


ประวัติศาสตร์

ความแตกต่างที่สำคัญ@ManagedBeanคือได้รับการจัดการโดยเฟรมเวิร์ก JSF และ@ManagedPropertyสามารถใช้ได้กับถั่วที่มีการจัดการ JSF อื่นเท่านั้น @Namedมีการจัดการโดยแอพพลิเคชันเซิร์ฟเวอร์ (คอนเทนเนอร์) ผ่านกรอบ CDI และผ่านทาง@Injectที่มีอยู่กับชนิดของภาชนะสิ่งประดิษฐ์ที่มีการจัดการเช่นใด@WebListener, @WebFilter, @WebServlet, @Path, @Statelessฯลฯ และแม้กระทั่ง @ManagedBeanJSF จากด้านอื่น ๆ ที่@ManagedPropertyไม่ได้ทำงานอยู่ภายใน@Namedหรืออื่น ๆ ใด ๆ สิ่งประดิษฐ์ภาชนะที่มีการจัดการ ใช้งานได้จริงเฉพาะภายใน@ManagedBeanจริงๆมันทำงานเฉพาะภายใน

ความแตกต่างอีกประการหนึ่งคือจริงๆแล้ว CDI จะฉีดพร็อกซีที่มอบหมายให้กับอินสแตนซ์ปัจจุบันในขอบเขตเป้าหมายตามคำขอ / เธรด (เช่นเดียวกับวิธีการฉีด EJB) กลไกนี้จะช่วยให้การฉีดถั่วขอบเขตแคบในถั่วของขอบเขตที่กว้างขึ้นซึ่งเป็นไปไม่ได้กับ @ManagedPropertyJSF JSF "ฉีด" อินสแตนซ์จริงที่นี่โดยตรงโดยเรียกใช้ตัวตั้งค่า (นั่นคือเหตุผลที่ต้องใช้ตัวตั้งค่าในขณะที่ไม่จำเป็นต้องใช้ด้วย@Inject)

แม้ว่าจะไม่เสียเปรียบโดยตรง แต่ก็มีวิธีอื่น - ขอบเขตของ@ManagedBeanมันมี จำกัด จากมุมมองอื่น ๆ หากคุณไม่ต้องการเปิดเผย "มากเกินไป" @Injectคุณสามารถเก็บถั่วที่มีการจัดการ@ManagedBeanไว้ได้ มันเหมือนเมื่อเทียบกับprotected publicแต่นั่นไม่นับจริงๆ

อย่างน้อยใน JSF 2.0 / 2.1 ข้อเสียที่สำคัญของการจัดการถั่วสำรอง JSF โดย CDI คือไม่มี CDI เทียบเท่ากับ@ViewScopedไฟล์. เข้า@ConversationScopedมาใกล้ แต่ยังคงต้องเริ่มต้นและหยุดด้วยตนเองและต่อท้ายcidพารามิเตอร์คำขอที่น่าเกลียดเพื่อผลลัพธ์ URL MyFaces CODI ช่วยให้ง่ายขึ้นโดยการเชื่อม JSF javax.faces.bean.ViewScopedกับ CDI อย่างโปร่งใสเต็มที่เพื่อให้คุณสามารถทำได้@Named @ViewScopedแต่จะต่อท้ายwindowIdพารามิเตอร์คำขอที่น่าเกลียดเพื่อผลลัพธ์ URL รวมทั้งในการนำทางแบบหน้าต่อหน้าของวานิลลาธรรมดา OmniFacesแก้ไขทั้งหมดนี้ด้วย CDI จริง@ViewScopedซึ่งเชื่อมโยงขอบเขตของ bean กับสถานะมุมมอง JSF แทนที่จะเป็นพารามิเตอร์การร้องขอโดยพลการ

JSF 2.2 (ซึ่งเผยแพร่ 3 ปีหลังจากคำถาม / คำตอบนี้) นำเสนอ@ViewScopedคำอธิบายประกอบใหม่ที่เข้ากันได้กับ CDI ในรูปแบบjavax.faces.view.ViewScoped. JSF 2.2 ยังมาพร้อมกับ CDI เท่านั้น@FlowScopedซึ่งไม่มี@ManagedBeanเทียบเท่าดังนั้นจึงผลักผู้ใช้ JSF ไปสู่ ​​CDI ความคาดหวังคือ@ManagedBeanและเพื่อน ๆ จะเลิกใช้งานตาม Java EE 8 หากคุณยังคงใช้@ManagedBeanงานอยู่ขอแนะนำอย่างยิ่งให้เปลี่ยนไปใช้ CDI เพื่อเตรียมพร้อมสำหรับเส้นทางการอัปเกรดในอนาคต CDI พร้อมใช้งานในคอนเทนเนอร์ที่เข้ากันได้กับ Java EE Web Profile เช่น WildFly, TomEE และ GlassFish สำหรับ Tomcat คุณต้องติดตั้งแยกต่างหากเหมือนกับที่คุณทำกับ JSF ดูวิธีการติดตั้ง CDI ใน Tomcat


4
ฉันได้สร้างbeans.xmlแปลง@ManagedBeanถั่วสำรองเป็น@Namedและแปลง@ManagedPropertyเป็น@Injectไฟล์. ทั้งหมดเป็นสิ่งที่ดีกับโลก แต่ถ้าฉันแก้ไข@EJBคำอธิบายประกอบเพื่อ@Injectการใช้งานที่ล้มเหลว ( org.jboss.weld.exceptions.DeploymentException) WELD-001408 Injection point has unsatisfied dependenciesพร้อมกับข้อความ ฉันควรใช้@Injectเพื่อฉีด EJB แบบไม่มีอินเทอร์เฟซลงใน@Namedถั่วจริง ๆ หรือฉันควรติดด้วย@EJB? EJB ถูกบรรจุใน EJB JAR ใน EAR เดียวกับ WAR ที่มีถั่ว CDI ของฉัน
Matt Ball

มันควรจะทำงาน คุณยังประสบปัญหานี้กับ Weld เวอร์ชันปัจจุบันหรือไม่?
BalusC

อนิจจาฉันไม่สามารถพูดได้ คำถามนี้มาจากนายจ้าง 2 รายและ> 2 ปีที่แล้ว ขึ้นอยู่กับความคิดเห็นเก่าของฉันกับคำตอบ Bozho ของฉันจะต้องมีเปลี่ยนไป CDI @Named/
Matt Ball

"MyFaces CODI ช่วยให้ง่ายขึ้นโดยการเชื่อม javax.faces.bean.bean.ViewScoped ของ JSF กับ CDI อย่างโปร่งใสเพื่อให้คุณสามารถทำได้@Named @ViewScopedแต่จะเพิ่มพารามิเตอร์คำขอ windowId ที่น่าเกลียดเพื่อผลลัพธ์ URL รวมทั้งในการนำทางแบบทีละหน้าของวานิลลาด้วย" โปรดทราบว่าด้วย DeltaSpike สิ่งนี้จะไม่เป็นจริงอีกต่อไป คุณสามารถปิดใช้งานทั้งพารามิเตอร์ dsId และ windowId URL หากคุณไม่ต้องการ Window Scope
JanM

1
@Jan: และในขณะเดียวกัน OmniFaces ยังมี JSF 2.2 เหมือน@ViewScopedสำหรับ JSF 2.0 / 2.1: showcase.omnifaces.org/cdi/ViewScoped
BalusC

16

ด้วย Java EE 6 และ CDI คุณมีตัวเลือกอื่นสำหรับ Managed Beans

  • @javax.faces.bean.ManagedBeanหมายถึง JSR 314 และได้รับการแนะนำให้รู้จักกับ JSF 2.0 เป้าหมายหลักคือการหลีกเลี่ยงการกำหนดค่าในไฟล์ faces-config.xml เพื่อใช้ bean ภายใน JSF Page
  • @javax.annotation.ManagedBean(“myBean”) ถูกกำหนดโดย JSR 316 โดยทั่วไปถั่วที่มีการจัดการ JSF สำหรับใช้ที่อื่นใน Java EE
  • @javax.inject.Named(“myBean”) เกือบจะเหมือนกันกับข้างบนยกเว้นว่าคุณต้องการไฟล์ beans.xml ในเว็บ / WEB-INF Folder เพื่อเปิดใช้งาน CDI

1
ข้อแตกต่างระหว่างสองข้อแรกคืออะไร?
Matt Ball

เป้าหมายของคำอธิบายประกอบแรกคือ / คือการแทนที่การกำหนดค่า bean ใน faces-config.xml สำหรับการใช้งานใน JSF อันที่สองคัดลอกแนวคิดลงใน "java ee 6 container" มีฟังก์ชันเพิ่มเติม (เช่นคำอธิบายประกอบ @PostConstruct และ @PreDestroy) แต่ยังสามารถเข้าถึงได้โดยหน้า JSF (ด้วยภาษานิพจน์)
h2mch

1
ทำไมคุณถึงต้องการbeans.xmlไฟล์? ทุกวันนี้ยังมีอยู่จริงหรือไม่?
Thufir

2
ไม่ด้วย JavaEE7 คุณไม่จำเป็นต้องใช้ beans.xml อีกต่อไป ดูdocs.oracle.com/javaee/7/tutorial/doc/cdi-adv001.htm
h2mch

1
ด้วย JavaEE7 คุณไม่จำเป็นต้องใช้ beans.xml: docs.oracle.com/javaee/7/tutorial/cdi-adv001.htm (ลิงก์ที่ถูกต้อง) blogs.oracle.com/theaquarium/entry/… (การเปิดใช้งาน CDI เริ่มต้นใน Java ศ. 7)
M. Atif Riaz

2

ฉันใช้ CDI ใน GlassFish 3.0.1 แต่เพื่อให้ใช้งานได้ฉันต้องนำเข้าเฟรมเวิร์ก Seam 3 (Weld) ที่ได้ผลดี

ใน GlassFish 3.1 CDI หยุดทำงานและ Seam Weld หยุดทำงานกับมัน ฉันเปิดข้อบกพร่องในเรื่องนี้แต่ยังไม่ได้รับการแก้ไข ฉันต้องแปลงรหัสทั้งหมดของฉันเพื่อใช้คำอธิบายประกอบ javax.faces * แต่ฉันวางแผนที่จะย้ายกลับไปที่ CDI เมื่อมันใช้งานได้

ฉันยอมรับว่าคุณควรใช้ CDI แต่ปัญหาหนึ่งที่ฉันยังไม่ได้รับการแก้ไขคือจะทำอย่างไรกับคำอธิบายประกอบ @ViewScoped ฉันมีรหัสจำนวนมากที่ขึ้นอยู่กับมัน ไม่ชัดเจนว่า @ViewScoped ใช้งานได้หรือไม่หากคุณไม่ได้ใช้ @ManagedBean กับมัน หากใครสามารถชี้แจงเรื่องนี้ได้ฉันจะขอบคุณ


-1

เหตุผลที่ดีอย่างหนึ่งในการย้ายไปที่ CDI: คุณสามารถมีทรัพยากรที่กำหนดขอบเขตเซสชันทั่วไปได้ (เช่นโปรไฟล์ผู้ใช้) @Inject'ในถั่วที่มีการจัดการ JSF และบริการ REST (เช่น Jersey / JAX-RS)

ในทางกลับกัน@ViewScopedเป็นเหตุผลที่น่าสนใจที่จะยึดติดกับ JSF @ManagedBean- โดยเฉพาะอย่างยิ่งสำหรับสิ่งที่มี AJAX ที่สำคัญ ไม่มีการแทนที่มาตรฐานสำหรับสิ่งนี้ใน CDI

ดูเหมือนว่ามันอาจมีการรองรับ@ViewScopedคำอธิบายประกอบที่คล้ายกับถั่ว CDI แต่ฉันไม่ได้เล่นด้วยเป็นการส่วนตัว

http://seamframework.org/Seam3/FacesModule

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