Spring @Autowired การใช้งาน


218

ข้อดีและข้อเสียของการใช้@Autowiredในชั้นเรียนที่จะเชื่อมต่อกับ Spring คืออะไร

เพื่อชี้แจงฉันกำลังพูดถึงเฉพาะเกี่ยวกับคำอธิบายประกอบ@Autowiredไม่ใช่สายอัตโนมัติใน XML

ฉันอาจจะไม่เข้าใจ แต่สำหรับฉันมันเกือบจะดูเหมือนการต่อต้านรูปแบบ - ชั้นเรียนของคุณเริ่มตระหนักว่าพวกเขาเชื่อมโยงกับกรอบ DI แทนที่จะเป็นแค่ POJOs อาจจะเป็นคนตะกละสำหรับการลงโทษ แต่ฉันชอบที่จะมีการกำหนดค่า XML ภายนอกสำหรับถั่วและฉันชอบที่จะมีสายที่ชัดเจนดังนั้นฉันรู้ว่าสิ่งที่มีสาย


4
ฉันสนใจในหัวข้อนี้เช่นกัน - การกำหนดค่าแอป MVC ของคุณผ่านคำอธิบายประกอบแทนที่จะเป็น XML ดูเหมือนว่าจะนำไปสู่การค้นหาจำนวนมาก "คลาสใดที่ถูกแมปกับ URL นี้" ใครเป็นคนจัดการเรื่องนี้ ". ฉันชอบที่จะมีแหล่งกำหนดค่าเดียว
matt b

6
คำว่า "@Autowiring" ดูเหมือนจะทำให้เข้าใจผิดที่นี่ ในขณะที่คุณสามารถทำการลงทะเบียนอัตโนมัติด้วยการกำหนดค่า XML คำถามเดิมควรได้รับการ rephrased เป็น "ข้อดีข้อเสียของการใช้คำอธิบายประกอบของ Spring" คำตอบที่ให้ไว้จะเน้นเพิ่มเติมเกี่ยวกับแง่มุมของการบันทึกอัตโนมัติ
Neeme Praks

ข้อมูลซ้ำซ้อนที่เป็นไปได้ของการทำความเข้าใจกับ Spring
@Autowired

คำตอบ:


253

เป็นเวลานานที่ฉันเชื่อว่ามีค่าในการมี "การรวมศูนย์การประกาศการกำหนดค่า" เช่นไฟล์ xml ที่เราทุกคนเคยใช้ จากนั้นฉันก็ตระหนักว่าสิ่งต่าง ๆ ส่วนใหญ่ในไฟล์นั้นไม่ใช่การกำหนดค่า - มันไม่เคยเปลี่ยนแปลงที่ไหนเลยหลังจากการพัฒนามาตลอด แล้วฉันตระหนักว่า "ศูนย์" เท่านั้นที่มีค่าในระบบค่อนข้างเล็ก - เฉพาะในระบบขนาดเล็กที่คุณจะสามารถที่จะ grok แฟ้มการกำหนดค่าเป็นทั้ง และคุณค่าของการทำความเข้าใจการเดินสายโดยรวมคืออะไรเมื่อ "การเดินสาย" เดียวกันส่วนใหญ่จะถูกทำซ้ำโดยอ้างอิงในรหัส? ดังนั้นสิ่งเดียวที่ฉันเก็บไว้คือเมตาดาต้า (คำอธิบายประกอบ) ซึ่งยังคงเป็นชนิดของการประกาศ สิ่งเหล่านี้ไม่เคยเปลี่ยนแปลงที่รันไทม์และพวกเขาไม่เคย ข้อมูล "การกำหนดค่า" ที่ใครบางคนจะเปลี่ยนได้ทันที - ดังนั้นฉันคิดว่าการเก็บไว้ในรหัสเป็นสิ่งที่ดี

ฉันใช้การเดินสายอัตโนมัติเต็มรูปแบบมากที่สุดเท่าที่จะทำได้ ฉันรักมัน. ฉันจะไม่กลับไปที่ฤดูใบไม้ผลิแบบเก่าเว้นแต่จะถูกคุกคามที่จุดปืน เหตุผลในการเลือกของฉัน@Autowiredเปลี่ยนไปตลอดเวลา

ตอนนี้ฉันคิดว่าเหตุผลที่สำคัญที่สุดสำหรับการใช้การลงทะเบียนอัตโนมัติคือระบบของคุณมีสิ่งที่เป็นนามธรรมน้อยกว่าในการติดตาม "ชื่อถั่ว" หายไปอย่างมีประสิทธิภาพ เปลี่ยนเป็นชื่อถั่วเท่านั้นที่มีอยู่เนื่องจาก xml ดังนั้นความไม่สมบูรณ์ของเลเยอร์ทางอ้อม (ซึ่งคุณจะใช้ชื่อถั่ว "foo" ใน bean "bar") ตอนนี้ฉันเชื่อมต่ออินเทอร์เฟซ "Foo" ลงใน bean ของฉันโดยตรงและการนำไปใช้งานถูกเลือกโดยโปรไฟล์รันไทม์ สิ่งนี้ทำให้ฉันสามารถทำงานกับรหัสเมื่อติดตามการอ้างอิงและการใช้งาน เมื่อฉันเห็นการพึ่งพา autowired ในรหัสของฉันฉันก็สามารถกดปุ่ม "ไปสู่การใช้งาน" ใน IDE ของฉันและรายการของการใช้งานที่รู้จักขึ้นมา ในกรณีส่วนใหญ่มีการนำไปใช้เพียงครั้งเดียวและฉันเข้าเรียนได้โดยตรง สามารถ' การนำไปใช้งานแบบใด (ฉันอ้างว่าสิ่งที่ตรงกันข้ามนั้นใกล้เคียงกับความจริงด้วยการเดินสาย xml - ตลกว่ามุมมองของคุณเปลี่ยนไปอย่างไร)

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

ระบบส่วนใหญ่ที่ฉันเคยทำงานด้วยมีเพียงหนึ่งการกำหนดค่าของสภาพแวดล้อมรันไทม์ที่ใช้งานจริง อาจมีการกำหนดค่าอื่น ๆ สำหรับการทดสอบเป็นต้น

ฉันจะบอกว่า autowiring เต็มรูปแบบคือ ruby-on-rails ของฤดูใบไม้ผลิ: มันรวบรวมความคิดว่ามีรูปแบบการใช้งานปกติและทั่วไปที่กรณีส่วนใหญ่ใช้ตาม ด้วยการกำหนดค่า XML คุณอนุญาตให้มีการใช้การกำหนดค่าที่สอดคล้อง / ไม่สอดคล้องกันจำนวนมากซึ่งอาจ / ไม่ได้ตั้งใจ ฉันเคยเห็นการกำหนดค่า xml จำนวนมากไปลงน้ำด้วยความไม่สอดคล้องกัน - มันได้รับการปรับปรุงใหม่พร้อมกับรหัสหรือไม่ ไม่คิด รูปแบบเหล่านั้นมีเหตุผลหรือไม่? มักจะไม่

เราใช้ตัวระบุในการกำหนดค่าของเราและหาวิธีอื่น ๆ ในการแก้ไขสถานการณ์เหล่านี้ นี้เป็นที่ชัดเจน "ข้อเสีย" เราพบ: เราได้เปลี่ยนไปเล็กน้อยรหัสทางที่เราจะทำให้มันเรียบโต้ตอบกับ autowiring: ลูกค้าพื้นที่เก็บข้อมูลการดำเนินการไม่ทั่วไปRepository<Customer>อินเตอร์เฟซ แต่เราทำให้อินเตอร์เฟซที่ขยายCustomerRepository Repository<Customer>บางครั้งก็มีกลอุบายหรือสองเมื่อมันมาถึง subclassing แต่มันมักจะชี้ให้เราไปในทิศทางของการพิมพ์ที่แข็งแกร่งซึ่งฉันพบว่าเกือบจะเป็นทางออกที่ดีกว่าเสมอ

แต่ใช่คุณกำลังผูกมัดกับสไตล์เฉพาะของ DI ที่สปริงส่วนใหญ่ทำ เราไม่ได้ทำให้ setters สาธารณะสำหรับการอ้างอิงใด ๆ เพิ่มเติม (ดังนั้นคุณจึงสามารถยืนยันว่าเรากำลัง 1 ในแผนก encapsulation / ซ่อนข้อมูล) เรายังคงมีบาง XML ในระบบของเรา แต่ XML โดยทั่วไปเพียง แต่มีความผิดปกติ การบันทึกอัตโนมัติเต็มรูปแบบทำงานร่วมกับ xml ได้ดี

สิ่งเดียวที่เราต้องการตอนนี้คือสำหรับ@Component, @Autowiredและส่วนที่เหลือจะถูกรวมอยู่ใน JSR (เช่นJSR-250 ) ดังนั้นเราจึงไม่จำเป็นต้องผูกกับฤดูใบไม้ผลิ นี่คือวิธีที่สิ่งต่าง ๆ เกิดขึ้นในอดีต ( java.util.concurrentสิ่งที่ทำให้ใจ) ดังนั้นฉันจะไม่แปลกใจเลยถ้าสิ่งนี้เกิดขึ้นอีกครั้ง


5
javax.annotation / javax.inject รองรับโดย spring ดังนั้นคุณไม่จำเป็นต้องใช้โค้ดใน Spring
Michael Wiles

26

สำหรับฉันนี่คือสิ่งที่ฉันชอบ / ไม่ชอบเกี่ยวกับ Spring และ auto-wiring

ข้อดี:

  • การเดินสายไฟอัตโนมัติกำจัดการกำหนดค่า XML ที่น่ารังเกียจ
  • ง่ายกว่ามากในการใช้คำอธิบายประกอบที่ช่วยให้คุณสามารถฉีดโดยตรงโดยใช้ฟิลด์วิธีตั้งค่าหรือตัวสร้าง นอกจากนี้ยังช่วยให้คุณสามารถใส่คำอธิบายประกอบและ 'มีคุณสมบัติ' ถั่วฉีดของคุณ

จุดด้อย:

  • การใช้การเดินสายไฟอัตโนมัติและการเพิ่มความคิดเห็นทำให้คุณขึ้นอยู่กับไลบรารีของสปริงที่เหมือนกับการกำหนดค่า XML คุณสามารถเลือกที่จะรันด้วยหรือไม่ใช้สปริง อย่างที่คุณพูดคุณจะผูกติดกับกรอบ DI
  • ในขณะเดียวกันฉันชอบที่จะสามารถ 'คัดเลือก' ถั่วให้ฉันนี้ทำให้รหัสยุ่งจริงๆ หากคุณต้องการฉีด bean เดียวกันในหลาย ๆ ที่ฉันได้เห็นชื่อสตริงซ้ำกันทั่ว สำหรับฉันแล้วดูเหมือนว่าจะมีข้อผิดพลาดเกิดขึ้น

ฉันเริ่มใช้การเดินสายอัตโนมัติในที่ทำงานโดยเฉพาะอย่างยิ่งเพราะเราพึ่งพาการบูรณาการ Spring มากอยู่แล้วว่าปัญหาการพึ่งพานั้นเป็นสิ่งที่สงสัย ฉันทำงานในโครงการ Spring MVC ที่ใช้การเดินสายอัตโนมัติอย่างกว้างขวางและค่อนข้างยากที่จะคาดศีรษะ

ฉันคิดว่าการเดินสายไฟอัตโนมัติเป็นรสชาติที่ได้มาเมื่อคุณชินกับมันแล้วคุณจะรู้ว่ามันทรงพลังง่ายและปวดหัวน้อยเพียงใดเมื่อใช้งานมากกว่าการกำหนดค่า XML


3
การกำหนดค่า XML ได้รับสิ่งที่น่ารังเกียจน้อยลงหากคุณใช้ชุดเครื่องมือสปริงซอร์สฟรีซึ่งมีการเติมข้อความอัตโนมัติ, กราฟถั่ว ฯลฯ
Sean Patrick Floyd

ฉันเห็นด้วยกับคุณในเรื่องการเดินสายอัตโนมัติที่ยุ่งเหยิงและพึ่งพาห้องสมุดฤดูใบไม้ผลิ! ฉันไม่เคยใช้การกำหนดค่า XML และฉันคิดว่าฉันควรจะมุ่งหน้าไปยังเส้นทางนั้นหรือไม่?
James111

15

เราเปลี่ยนจาก @Autowire กลับไปเป็นการกำหนดค่า XML ในโครงการขนาดใหญ่ของเรา ปัญหาคือประสิทธิภาพการบูตที่ต่ำมาก สแกนเนอร์การป้อนอัตโนมัติโหลดคลาสทั้งหมดจากการค้นหาพา ธ การค้นหาอัตโนมัติดังนั้นคลาสจำนวนมากจะถูกโหลดอย่างกระตือรือร้นระหว่างการเตรียมใช้งาน Spring


1
ฉันได้พบว่า javaconfig อาจเป็นทางออกที่ดีกว่าสำหรับการเริ่มต้นบริบทบางส่วนซึ่งเป็นชัยชนะครั้งใหญ่ แต่คุณสามารถรวมสิ่งเหล่านี้ได้อย่างง่ายดายโดยใช้ @ Autowired / @ Inject บนคอนสตรัคเตอร์ (ในคำอื่น ๆ
krosenvold

6

มีการอภิปรายน้อยมากเกี่ยวกับสภาพแวดล้อมการสลับ โครงการส่วนใหญ่ที่ฉันเคยทำมันเป็นปัญหาที่แท้จริงในการฉีดการพึ่งพาขึ้นอยู่กับสภาพแวดล้อมที่เรากำลังทำอยู่ ด้วยการตั้งค่า xml มันค่อนข้างตรงไปตรงมากับ Spring EL และฉันไม่ทราบวิธีแก้ปัญหาที่ดีกับคำอธิบายประกอบ ฉันเพิ่งค้นพบหนึ่ง:

    @Value("#{${env} == "production" ? realService : dummyService}")
    private SomeService service;

มันควรจะทำงานได้ แต่ไม่ใช่วิธีการแก้ปัญหาที่ดีเลย


ฉันเปิดเธรดแยกต่างหากเกี่ยวกับสิ่งนี้และมีวิธีแก้ปัญหาด้วย Spring @Profilesและ@Configuration: blog.springsource.org/2011/02/14/ … ดูเธรดอื่น ๆ : stackoverflow.com/questions/13490393/ …
BTakacs

4

ฉันเปลี่ยนเป็น @Autowire แล้ว การบำรุงรักษาการกำหนดค่า XML ในสิ่งอื่นนอกเหนือจากโครงการขนาดเล็กกลายเป็นงานที่ถูกต้องและความเข้าใจลดลงอย่างรวดเร็ว

IntelliJ ให้การสนับสนุนที่ดี (ไม่สมบูรณ์) สำหรับคำอธิบายประกอบในฤดูใบไม้ผลิ


3

เรื่องของฉันในเรื่องนี้คือการกำหนดค่า xml ลดความชัดเจนของรหัสโดยเฉพาะในระบบขนาดใหญ่

คำอธิบายประกอบเช่น @Component ทำให้สิ่งต่าง ๆ แย่ลงไปอีก มันบังคับให้นักพัฒนาสร้างวัตถุที่ไม่แน่นอนเนื่องจากการขึ้นต่อกันไม่สามารถทำให้เกิดขึ้นได้อีกต่อไปเนื่องจากต้องมีการกำหนดค่าเริ่มต้น การพึ่งพาต้องถูกฉีดผ่าน setter สาธารณะหรือไม่สามารถควบคุมได้ผ่าน @Autowired [การฉีดการพึ่งพาที่แย่ยิ่งกว่านั้นถูกทำลายด้วยคลาสที่ยกระดับการพึ่งพาของพวกเขาฉันยังเห็นสิ่งนี้ในโค้ดที่เขียนขึ้นใหม่!] โดยไม่มีการควบคุมฉันหมายถึงในระบบขนาดใหญ่เมื่อมีการใช้งานหลายประเภท (หรือเด็ก ๆ ) มันมีส่วนเกี่ยวข้องมากขึ้นในการทำความเข้าใจว่าการใช้งานแบบใดที่ @Autowired ความซับซ้อนที่ทำให้การตรวจสอบข้อบกพร่องนั้นยากขึ้นมาก นอกจากนี้ยังหมายความว่าคุณมีโปรไฟล์สำหรับสภาพแวดล้อมการทดสอบและอีกรายการสำหรับการผลิต

ฉันติดกับพื้นกลางที่ฉันประกาศ class configuration (es) ของฉัน, (Java based Spring configuration โดยใช้ @Configuration)

ฉันประกาศถั่วทั้งหมดของฉันอย่างชัดเจนในคลาสการกำหนดค่า (es) ฉันใช้ @Autowired เฉพาะในคลาสการกำหนดค่า (es) วัตถุประสงค์คือเพื่อ จำกัด การพึ่งพา Spring ในคลาสการตั้งค่า (es)

@Configuration ตั้งอยู่ในแพคเกจเฉพาะซึ่งเป็นที่เดียวที่สปริงสแกนทำงาน (นั่นช่วยเร่งเวลาเริ่มต้นอย่างมากในโครงการขนาดใหญ่)

ฉันพยายามทำให้คลาสของฉันไม่เปลี่ยนรูปโดยเฉพาะอย่างยิ่ง data object, JPA, Hibernate และ Spring รวมถึงไลบรารี่ที่ทำให้เป็นอนุกรมมากมายดูเหมือนจะบ่อนทำลายสิ่งนี้ ฉันหลีกเลี่ยงสิ่งใดก็ตามที่บังคับให้ฉันจัดหาผู้ตั้งค่าหรือลบคำหลักสุดท้ายออกจากการประกาศคุณสมบัติของฉัน

การลดความเป็นไปได้ของการเปลี่ยนแปลงวัตถุหลังจากที่พวกมันถูกสร้างขึ้นลดข้อผิดพลาดอย่างมากในระบบขนาดใหญ่รวมทั้งลดเวลาในการค้นหาข้อบกพร่องเมื่อมีอยู่

ดูเหมือนว่ามันจะบังคับให้นักพัฒนาออกแบบการโต้ตอบระหว่างส่วนต่าง ๆ ของระบบได้ดีขึ้น ปัญหาและข้อบกพร่องกลายเป็นข้อผิดพลาดในการรวบรวมมากขึ้นเรื่อย ๆ ซึ่งจะช่วยลดเวลาที่สูญเปล่าและปรับปรุงประสิทธิภาพการผลิต


1

นี่คือบางส่วนของประสบการณ์
ข้อดี

  • ทำให้การกำหนดค่าง่ายขึ้นเพราะเราสามารถใช้คำอธิบายประกอบ @Autowire ได้
  • ไม่ต้องการใช้วิธีตั้งค่าดังนั้นคลาสจะสะอาดขึ้น

จุดด้อย

  • เชื่อมไฟล์ xml ให้แน่นแม้เราใช้ DI
  • หายากการนำไปใช้ (แต่ถ้าคุณใช้ไอดีที่ดีอย่าง Intellij คุณจะกำจัดมันได้)

จากประสบการณ์ส่วนตัวของฉันฉันไม่ได้ใช้คำอธิบายประกอบ @AutoWire มาก แต่ในกรณีทดสอบ


1

ฉันชอบเขียนด้วยคำอธิบายประกอบแทนที่จะเป็น XML ตามคู่มือฤดูใบไม้ผลิและรุ่นล่าสุด XML และคำอธิบายประกอบบรรลุผลลัพธ์เดียวกัน

นี่คือรายการของฉัน

มือโปร:

  • ลบบรรทัดที่ไม่มีประโยชน์ออกจาก xml
  • ลดความซับซ้อนของการดีบักรหัส: เมื่อคุณเปิดชั้นเรียนคุณสามารถอ่านสิ่งที่คุณมีในชั้นเรียนได้
  • การพัฒนาที่รวดเร็วยิ่งขึ้นสามารถอ่านโครงการที่มี XML อย่างน้อย 400 บรรทัด?

จุดด้อย:

  • ไม่ใช่การนำ Java มาตรฐานมาใช้ แต่คุณสามารถสลับไปใช้ @Inject ซึ่งเป็น Java Standard Api ดังนั้น bean จะยังคงเป็น Pojo
  • คุณไม่สามารถใช้ทุกที่ได้อย่างง่ายดายการเชื่อมต่อฐานข้อมูลและอื่น ๆ แต่เป็นเพียงความเห็นฉันชอบมีสถานที่ที่อ่านการกำหนดค่าทั้งหมด

0

สำหรับความเข้าใจของฉัน @Autowired เป็นวิธีที่ดีที่สุดที่จะใช้ในขณะที่อ้างถึงการอ้างอิงอินเทอร์เฟซและใช้ฟังก์ชั่นการแทนที่ของมัน แต่ฉันก็พบปัญหากับเรื่องนี้ก็คือ

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