ต้นแบบ Spring IOC
แกนหลักและจุดเริ่มต้นของกรอบฤดูใบไม้ผลินั้นไม่ต้องสงสัยเลยว่า IOC ในฐานะที่เป็นเทคโนโลยีหลักที่จัดทำโดยคอนเทนเนอร์ฤดูใบไม้ผลิ IOC ประสบความสำเร็จในการผกผันของการพึ่งพา: จากการจัดการที่ใช้งานอยู่ของคลาสหลักในการพึ่งพาการควบคุมทั่วโลกของการพึ่งพาโดยคอนเทนเนอร์ฤดูใบไม้ผลิ
ประโยชน์ของการทำสิ่งนี้คืออะไร?
แน่นอนว่ามันเป็นสิ่งที่เรียกว่า "decoupling" ซึ่งสามารถทำให้ความสัมพันธ์ระหว่างโมดูลของโปรแกรมเป็นอิสระมากขึ้น สปริงจำเป็นต้องควบคุมการพึ่งพาระหว่างโมดูลเหล่านี้และสร้างจัดการและบำรุงรักษาโมดูลเหล่านี้ตามการพึ่งพาเหล่านี้ในระหว่างการเริ่มต้นคอนเทนเนอร์และกระบวนการเริ่มต้น หากคุณต้องการเปลี่ยนการพึ่งพาระหว่างโมดูลคุณไม่จำเป็นต้องเปลี่ยนรหัสโปรแกรม คุณจะต้องแก้ไขการพึ่งพาที่เปลี่ยนแปลง สปริงจะสร้างการพึ่งพาใหม่เหล่านี้อีกครั้งในกระบวนการเริ่มต้นและเริ่มต้นคอนเทนเนอร์อีกครั้ง ในกระบวนการนี้มีความจำเป็นที่จะต้องทราบว่ารหัสนั้นไม่จำเป็นต้องสะท้อนการประกาศสถานการณ์การพึ่งพาเฉพาะของโมดูล แต่จำเป็นต้องกำหนดอินเทอร์เฟซของโมดูลที่ต้องการเท่านั้น ดังนั้นนี่เป็นแนวคิดที่มุ่งเน้นอินเทอร์เฟซทั่วไป ในขณะเดียวกันก็เป็นการดีที่สุดที่จะแสดงการพึ่งพาในรูปแบบของไฟล์การกำหนดค่าหรือคำอธิบายประกอบ คลาสการประมวลผลสปริงที่เกี่ยวข้องจะรวบรวมโมดูลตามไฟล์การกำหนดค่าภายนอกเหล่านี้หรือสแกนคำอธิบายประกอบเพื่อเรียกโปรเซสเซอร์คำอธิบายประกอบภายในเพื่อประกอบโมดูลเพื่อให้กระบวนการ IOC เสร็จสมบูรณ์
จุดประสงค์ของ IOC คือการฉีดพึ่งพาที่เรียกว่า DI ผ่านเทคโนโลยี IOC ตู้คอนเทนเนอร์ที่ดีที่สุดจะช่วยให้เราฉีดพึ่งพาได้อย่างสมบูรณ์ระหว่างโมดูล
นอกจากนี้จุดสุดท้ายคือในกระบวนการของฤดูใบไม้ผลิ IOC เราต้องชัดเจนเกี่ยวกับสายหลักด้านบนเสมอ ไม่ว่าโครงสร้างไวยากรณ์และคลาสแบบเรียลไทม์จะซับซ้อนเพียงใดฟังก์ชั่นและวัตถุประสงค์ของมันเหมือนกัน: มันคือการทำ "แอสเซมบลี" ของโมดูลโดยอาศัยไฟล์กำหนดค่าที่อธิบายไว้เป็น "การวาดภาพ" แอสเซมบลี ไวยากรณ์ที่ซับซ้อนเป็นเพียงวิธีการบรรลุวัตถุประสงค์นี้
ต้นแบบ IOC ที่เรียกว่าเพื่อแสดงแผนภาพ IOC Schematic ที่ง่ายที่สุดเราอาจสร้างต้นแบบที่เรียบง่ายอย่างสมบูรณ์เพื่อแสดงกระบวนการนี้:
ก่อนอื่นมีหลายโมดูลที่เรากำหนดรวมถึงโมดูลหลักและโมดูลการพึ่งพาที่กำหนดโดยอินเตอร์เฟสทั้งสอง:
คลาส MainModule {Private Indermodulea Modulea; Private Indermoduleb Moduleb; Public Public Modulea getModulea () {return modulea; } โมฆะสาธารณะ setModulea (ขึ้นอยู่กับ modulea) {this.modulea = modulea; } Public IndeperModuleB getModuleB () {return moduleB; } โมฆะสาธารณะ setModuleB (enderModuleB moduleB) {this.moduleB = moduleB; }} อินเตอร์เฟสขึ้นอยู่กับ {โมฆะสาธารณะ funcfroverulea ();} อินเตอร์เฟสขึ้นอยู่กับ {โมฆะสาธารณะ funcfromuleb ();} คลาสขึ้นอยู่กับการใช้งานการใช้งานขึ้นอยู่กับ {@Override public void funcfrultulea () {out.out.out. }} คลาส adpendModuleBimpl ใช้งาน ampendModuleB {@Override โมฆะสาธารณะ funcfroveruleb () {system.out.println ("นี่คือ func จากโมดูล B"); -หากเราไม่ใช้ IOC แต่พึ่งพาโมดูลหลักเองเพื่อควบคุมการสร้างโมดูลที่ขึ้นอยู่กับมันก็จะเป็นเช่นนี้:
คลาสสาธารณะ SimpleIocDemo {โมฆะสาธารณะคงที่หลัก (สตริง [] args) พ่น classnotFoundException {mainModule mainModule = new MainModule (); MainModule.SetModulea (ใหม่ขึ้นอยู่กับ ModuleAimpl ()); MainModule.SetModuleB (ใหม่ขึ้นอยู่กับ ModuleBimpl ()); MainModule.getModulea (). funcfromulea (); MainModule.getModuleb (). funcfrontuleb (); -นี่คือคำจำกัดความที่เรียบง่ายของเราของต้นแบบคอนเทนเนอร์ IOC เมื่อคอนเทนเนอร์เริ่มต้นหลังจากเริ่มต้นจะอ่านไฟล์กำหนดค่าที่เขียนโดยผู้ใช้ ที่นี่เราใช้ไฟล์การกำหนดค่าคุณสมบัติอย่างง่ายเป็นตัวอย่าง เฉพาะเมื่อผู้ใช้เรียกวิธีการ getBean ถั่วที่เกี่ยวข้องจะถูกรวบรวมและโหลดอย่างแท้จริงตามไฟล์การกำหนดค่า แผนที่ที่ใช้ในการบันทึกถั่วที่ประกอบอยู่ในต้นแบบคอนเทนเนอร์ที่เรากำหนดไว้ หากมีถั่วที่ตรงตามข้อกำหนดไม่จำเป็นต้องสร้างอีกครั้ง:
Class SimpleIocContainer {คุณสมบัติคุณสมบัติส่วนตัว = คุณสมบัติใหม่ (); แผนที่ส่วนตัว <สตริงวัตถุ> moduleMap = ใหม่ hashmap <> (); {ลอง {properties.load (ใหม่ FileInputStream (ไฟล์ใหม่ ("simpleioc.properties"))); } catch (exception e) {e.printstacktrace (); }} วัตถุสาธารณะ getBean (modulename สตริง) พ่น classnotFoundException {Object InstanceObj; if (moduleMap.get (modulename)! = null) {system.out.println ("return old bean"); return modulemap.get (modulename); } system.out.println ("สร้างถั่วใหม่"); String fullClassName = properties.getProperty (modulename); if (fullClassName == null) โยน classnotFoundException ใหม่ (); อื่น {คลาส <? ขยายวัตถุ> clazz = class.forName (fullClassName); ลอง {instanceObj = clazz.newinstance (); instanceObj = buildattachedModules (modulename, instanceObj); moduleMap.put (modulename, instanceObj); ส่งคืน InstanceObj; } catch (InstantiationException E) {E.printStackTrace (); } catch (unglegalAccessException e) {e.printStackTrace (); }} return null; } วัตถุส่วนตัว buildattachedModules (String modulename, Object InstanceObj) {set <String> propertiesKeys = properties.StringProperTyNames (); ฟิลด์ [] ฟิลด์ = instanceObj.getClass (). getDeclaredFields (); สำหรับ (คีย์สตริง: ProperTiesKeys) {if (key.contains (modulename) &&! key.equals (modulename)) {ลอง {class <? ขยายวัตถุ> clazz = class.forName (properties.getProperty (properties.getProperty (คีย์))); สำหรับ (ฟิลด์ฟิลด์: ฟิลด์) {ถ้า (field.getType (). isAssignablefrom (clazz)) field.set (instanceObj, clazz.newinstance ()); }} catch (exception e) {e.printstacktrace (); }}} return instanceObj; -นี่คือไฟล์กำหนดค่าการพึ่งพาที่เราเขียนโดยใช้ไฟล์กำหนดค่าคุณสมบัติ ไฟล์การกำหนดค่านี้เป็น "การวาด" ของโมดูลแอสเซมบลีของเรา ไวยากรณ์ที่นี่ถูกกำหนดโดยเราอย่างสมบูรณ์ ในคอนเทนเนอร์ IOC ของสปริงสปริงเพื่อแสดงตรรกะการพึ่งพาที่ซับซ้อนมากขึ้นไฟล์การกำหนดค่ารูปแบบ XML ที่พัฒนาขึ้นหรือการกำหนดค่าคำอธิบายประกอบใหม่จะถูกใช้และโปรเซสเซอร์คำอธิบายประกอบจะถูกใช้เพื่อทำการวิเคราะห์การวาดภาพ:
MainModule = com.rocking.demo.mainModulemainModule.modulea = moduleamainModule.moduleb = moduleBmodulea = com.rocking.demo.dependmoduleaimplmoduleb = com.rocking.demo.dependmodulebimpl
นี่คือรหัสทดสอบ จะเห็นได้ว่าเราสามารถรับโมดูลที่ตรงตามข้อกำหนดผ่านคอนเทนเนอร์ IOC ที่เรากำหนดไว้อย่างสมบูรณ์ ในเวลาเดียวกันเรายังสามารถพบว่าภาชนะที่เรากำหนดสามารถรักษาถั่วเหล่านี้ให้เราได้ เมื่อถั่วได้ถูกรวบรวมและสร้างขึ้นมันไม่จำเป็นต้องสร้างอีกครั้ง
คลาสสาธารณะ SimpleIocDemo {โมฆะคงที่สาธารณะหลัก (สตริง [] args) พ่น classnotfoundexception {simpleioccontainer คอนเทนเนอร์ = ใหม่ simpleioccontainer (); Contermodulea modulea = (ขึ้นอยู่กับ Modulea) container.getBean ("modulea"); modulea.funcfromulea (); INDERMODULEB MODULEB = (INDERMODULEB) container.getBean ("moduleB"); moduleb.funcfromuleb (); MainModule MainModule = (MainModule) container.getBean ("MainModule"); MainModule.getModulea (). funcfromulea (); MainModule.getModuleb (). funcfrontuleb (); container.getBean ("MainModule"); -นี่คือต้นแบบคอนเทนเนอร์ IOC ที่ฉันสร้างขึ้นตามแนวคิดพื้นฐานของ IOC แม้ว่า Spring IOC จะมีไวยากรณ์ที่ซับซ้อน แต่งานที่เสร็จสมบูรณ์ในที่สุดก็เหมือนกันที่แกนกลางซึ่งเรียกว่า "การเปลี่ยนแปลงทั้งหมดจะไม่ถูกแยกออกจากสาระสำคัญของพวกเขา"
กระบวนการเฉพาะของ IOC ในฤดูใบไม้ผลิ
ครั้งสุดท้ายที่ต้นแบบของการใช้งานทั่วไปของ IOC ถูกแสดง ดังนั้นวิธีการใช้กระบวนการโหลด pojos โดยเฉพาะในกรอบฤดูใบไม้ผลิของคอนเทนเนอร์นี้ตามการกำหนดค่าข้อมูลเมตาดาต้าเมตา? มีหลายสถานที่ในกระบวนการทำงานคอนเทนเนอร์ IOC ฤดูใบไม้ผลิทั้งหมดที่ออกแบบมาให้มีความยืดหยุ่นค่อนข้างมากทำให้ผู้ใช้มีพื้นที่จำนวนมากในการทำงานให้เสร็จสมบูรณ์แทนที่จะทำตามกระบวนการทางกลของภาชนะ
นี่คือไดอะแกรมกระบวนการของกระบวนการทำงานของคอนเทนเนอร์ IOC ทั้งหมด:
1. สเตจการเริ่มต้นคอนเทนเนอร์ (1) การโหลดข้อมูลไฟล์การกำหนดค่า (2) การวิเคราะห์ข้อมูลไฟล์กำหนดค่า (3) แอสเซมบลี beandefinition
(4) โพสต์การประมวลผลครั้งแรกข้อมูลเมตาเช่นไฟล์การกำหนดค่าหรือคำอธิบายประกอบและข้อมูลคลาส Javabean จะถูกโหลดลงในคอนเทนเนอร์ IOC คอนเทนเนอร์อ่านไฟล์กำหนดค่า XML-format ไฟล์การกำหนดค่านี้เป็นการพึ่งพาที่ประกาศโดยผู้ใช้และชุดประกอบที่ต้องการความสนใจเป็นพิเศษ มันเป็น "ภาพวาดภายนอก" ในช่วงต้นสำหรับการประกอบถั่ว เอ็นจิ้นการแยกวิเคราะห์ในคอนเทนเนอร์สามารถแยกวิเคราะห์ข้อมูลเมตาข้อมูลในรูปแบบข้อความที่เราเขียนลงใน beandefinition ที่สามารถรับรู้ได้ภายในภาชนะบรรจุซึ่งสามารถเข้าใจ beandefinition มันกลายเป็นโครงสร้างคลาสที่คล้ายกับกลไกการสะท้อน beandefinition นี้ได้รับจากการวิเคราะห์ Javabeans และไฟล์การกำหนดค่าได้รับโครงสร้างพื้นฐานของการประกอบ javabean ที่ตรงตามข้อกำหนด หากคุณต้องการแก้ไข beandefinition นอกเหนือจาก beandefinition แล้วการประมวลผลหลังนี้จะดำเนินการ การประมวลผลหลังการประมวลผลโดยทั่วไปจะถูกประมวลผลผ่าน beanfactorypostprocessor ในกรอบฤดูใบไม้ผลิ
เรายังคงใช้ตัวอย่างที่เราใช้เป็นครั้งสุดท้ายเพื่อแสดงหลักการปฏิบัติการของ beandefinition นี้: มีสามถั่ว, โมดูลหลัก mainmodule และโมดูลการพึ่งพาขึ้นอยู่กับ Modulea และ Indermoduleb อดีตขึ้นอยู่กับสองโมดูลหลัง ในไฟล์การกำหนดค่าเรามักจะประกาศการพึ่งพาเช่นนี้:
<? xml version = "1.0" การเข้ารหัส = "utf-8"?> <beans xmlns = "http://www.springframework.org/schema/beans" xmlns: xsi = "http://ww.w3.org/2001/xml XSI: schemalocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd" </perty> <property name = "moduleb"> <ref bean = "moduleb"/> </porement> </epean> <bean id = "modulea"> </ebean> <bean id = "moduleb"> </epean>
นี่คือโปรแกรมของเราที่แสดงให้เห็นถึงการประกอบของคอนเทนเนอร์ beanfactory มาตรฐาน (หนึ่งในการใช้งานของคอนเทนเนอร์ Spring IOC) ไปยังไฟล์การกำหนดค่าด้านบน:
คลาส MainModule {Private Indermodulea Modulea; Private Indermoduleb Moduleb; Public Public Modulea getModulea () {return modulea; } โมฆะสาธารณะ setModulea (ขึ้นอยู่กับ modulea) {this.modulea = modulea; } Public IndeperModuleB getModuleB () {return moduleB; } โมฆะสาธารณะ setModuleB (enderModuleB moduleB) {this.moduleB = moduleB; }} อินเตอร์เฟสขึ้นอยู่กับ {โมฆะสาธารณะ funcfroverulea ();} อินเตอร์เฟสขึ้นอยู่กับ {โมฆะสาธารณะ funcfromuleb ();} คลาสขึ้นอยู่กับการใช้งานการใช้งานขึ้นอยู่กับ {@Override public void funcfrultulea () {out.out.out. }} คลาส adpendModuleBimpl ใช้งาน ampendModuleB {@Override โมฆะสาธารณะ funcfroveruleb () {system.out.println ("นี่คือ func จากโมดูล B"); }} คลาสสาธารณะ SimpleIocDemo {โมฆะคงที่สาธารณะหลัก (สตริง [] args) พ่น classnotfoundexception {defaultlistablebeanfactory beanfactory = ใหม่ defaultlistablebeanfactory (); XMLBEANDEFINITIONREADER Reader = ใหม่ XMLBEANDEFINITIONREADER (BeanFactory); Reader.loadBeanDefinitions ("beans.xml"); MainModule MainModule = (MainModule) BeanFactory.getBean ("MainModule"); MainModule.getModulea (). funcfromulea (); MainModule.getModuleb (). funcfrontuleb (); -ที่นี่ไฟล์การกำหนดค่าของเราและ javabean ถูกโหลดและอ่านและแยกวิเคราะห์ ที่นี่กระบวนการสร้างและการใช้งาน beandefinition ถูกซ่อนไว้ในนั้น นี่คือกระบวนการทั่วไปที่เกิดขึ้นจริงภายใน IOC:
คลาสสาธารณะ SimpleIocDemo {โมฆะสาธารณะคงที่หลัก (สตริง [] args) พ่น classnotfoundexception {defaultlistablebeanfactory beanfactory = ใหม่ defaultListableBeanFactory (); AbstractBeanDefinition MainModule = ใหม่ RootBeanDefinition (MainModule.class); AbstractBeanDefinition Modulea = ใหม่ RootBeanDefinition (InderModuleAimpl.class); AbstractBeanDefinition ModuleB = ใหม่ RootBeanDefinition (ANDMODMODULEBIMPL.CLASS); beanfactory.registerbeandefinition ("MainModule", MainModule); beanfactory.registerbeandefinition ("modulea", modulea); beanfactory.registerbeandefinition ("moduleb", moduleb); MutablePropertyValues PropertyValues = ใหม่ MutablePropertyValues (); PropertyValues.add ("modulea", modulea); PropertyValues.add ("Moduleb", ModuleB); MainModule.SetPropertyValues (PropertyValues); MainModule โมดูล = (MainModule) BeanFactory.getBean ("MainModule"); module.getModulea (). funcfrultulea (); module.getModuleb (). funcfrontuleb (); -หลังจากโหลดและอ่านข้อมูลเมตาของ XML แล้วเอ็นจิ้นการแยกวิเคราะห์ IOC จะสร้างโมดูลที่กล่าวถึงในมันลงใน beandefinition ตามประเภทจริง beandefinition นี้ถือได้ว่าเป็นกระบวนการสะท้อนหรือกระบวนการพร็อกซี วัตถุประสงค์คือเพื่อให้คอนเทนเนอร์ IOC ชัดเจนโครงสร้างถั่วของวัตถุอินสแตนซ์ที่จะสร้างขึ้นในอนาคตจากนั้นลงทะเบียนโครงสร้างถั่วเหล่านี้ลงใน beanfactory จากนั้นเพิ่มการพึ่งพาของโมดูลหลักไปยังคุณสมบัติของโมดูลหลักในรูปแบบของการฉีดยา เป็นรูปเป็นร่างแล้ว หลังจากนั้นเพียงโทรหาวิธีการ GetBean เพื่อผลิตถั่วที่ตรงตามข้อกำหนด นี่คือขั้นตอนต่อไปของกระบวนการและเราจะพูดถึงมันในภายหลัง
หลังจากลงทะเบียนข้อมูลเกี่ยวกับ "การวาด" ของ beandefinition ไปยัง Beanfactory แล้วเรายังสามารถทำการเปลี่ยนแปลง beandefinition ที่ลงทะเบียนได้ นี่เป็นหนึ่งในแง่มุมที่ยืดหยุ่นของการออกแบบฤดูใบไม้ผลิสำหรับผู้ใช้ที่กล่าวถึงก่อนหน้านี้ ไม่ได้หมายความว่ากระบวนการทั้งหมดไม่สามารถควบคุมได้ แต่มีพื้นที่มากมายให้ผู้ใช้เล่นในหลาย ๆ ที่ วิธีการเฉพาะคือการใช้โปรเซสเซอร์ beanfactory beanfactorypostprocessor เพื่อแทรกแซงในการประมวลผลของ beanfactory เพื่อเขียนชิ้นส่วน beandefinition ที่เราต้องแก้ไขเพิ่มเติม กระบวนการนี้สอดคล้องกับกระบวนการ "หลังการประมวลผล" ในกระบวนการ
การใช้หนึ่งในโปรเซสเซอร์ทั่วไป: ตัวประมวลผลการกำหนดค่าตัวยึดตัวยึดตัวยึดเป็นตัวอย่างคือการประมวลผล beanfactory ที่ลงทะเบียนหลังจากที่มันถูกสร้างขึ้นเพื่อให้เนื้อหาในแอตทริบิวต์ beanDefinition ที่สอดคล้องกันได้รับการแก้ไขเป็นข้อมูลในไฟล์การกำหนดค่าการกำหนดค่าที่ระบุ:
DefaultListableBeanFactory beanfactory = ใหม่ defaultListableBeanFactory (); XMLBEANDEFINITIONREADER Reader = ใหม่ XMLBEANDEFINITIONREADER (beanFactory); reader.loadBeanDefinitions (ใหม่ classPathResource ("beans.xml")) PropertyPlaceHolderConfigurer (); configurer.setLocation (ใหม่ classpathresource ("เกี่ยวกับ. properties")); configurer.postProcessBeanFactory (beanfactory);beanfactorypostprocessor จะประมวลผล beanfactory ผลที่ได้คือการเปลี่ยนคุณลักษณะบางอย่างที่กำหนดไว้ใน beandefinition เป็นข้อมูลบางอย่างที่ตำแหน่งของ beanfactorypostprocessor
2. เวทีการสร้างอินสแตนซ์ถั่ว
ภายใต้คำแนะนำของ "ภาพวาดภายใน" ที่ประมวลผลของ beandefinition คอนเทนเนอร์สามารถแปลง beandefifnition ต่อไปเป็นวัตถุอินสแตนซ์ที่เปิดใช้งานที่มีอยู่ในหน่วยความจำผ่านการสะท้อนหรือการผลิตแบบไดนามิกแบบไดนามิกจากนั้นรวบรวมวัตถุการพึ่งพาที่ระบุโดย beandefinition ที่นี่การอ้างอิงของวัตถุการพึ่งพาถูกกำหนดให้กับแอตทริบิวต์วัตถุที่ต้องขึ้นอยู่กับ
แต่ควรสังเกตที่นี่ว่าอินสแตนซ์ที่สร้างขึ้นไม่ได้เป็นเพียงแค่อินสแตนซ์ง่ายๆของคำจำกัดความถั่ว แต่เป็นอินสแตนซ์ของ Beanwrapper ที่ห่อหุ้มด้วยฤดูใบไม้ผลิ เหตุใดจึงควรใช้ในการห่อถั่วในวิธี Beanwrapper? เนื่องจาก Beanwrapper จัดให้มีอินเทอร์เฟซเพื่อเข้าถึงคุณสมบัติถั่วอย่างสม่ำเสมอ หลังจากสร้างเฟรมเวิร์กพื้นฐานแล้วคุณสมบัติในนั้นจะต้องตั้งค่า วิธีการตั้งค่าของถั่วแต่ละตัวนั้นแตกต่างกันดังนั้นมันจะซับซ้อนมากหากคุณตั้งค่าโดยตรงด้วยการสะท้อนกลับ ดังนั้นสปริงจึงจัดให้มีเสื้อคลุมนี้เพื่อทำให้การตั้งค่าคุณสมบัติง่ายขึ้น:
beanwrapper beanwrapper = new beanwrapperimpl (class.forname ("com.rocking.demo.mainmodule")); beanwrapper.setPropertyValue ("modulea", class.forname ("com.demo.depmoduleaimpl") "moduleb", class.forname ("com.rocking.demo.depmodulebimpl") newinstance ()); mainmodule mainmodule = (mainmodule) beanwrapper.getwrappedinstance (); mainmodule.getModulea ()กระบวนการข้างต้นแสดงให้เห็นว่าในฤดูใบไม้ผลิคุณสามารถเข้าใจโครงสร้างของถั่วอินสแตนซ์ที่ห่อหุ้มในอนาคตโดยได้รับคอนเทนเนอร์สะท้อนแสงของชั้นเรียนและทำบรรจุภัณฑ์ ใช้วิธีการตั้งค่าคุณสมบัติ Unified SetProperTyValue เพื่อตั้งค่าคุณสมบัติสำหรับอินสแตนซ์ของแพ็คเกจนี้ อินสแตนซ์ถั่วสุดท้ายที่ได้รับผ่าน GetWrappedInstance และคุณสามารถพบว่าคุณลักษณะของมันได้รับการกำหนดเรียบร้อยแล้ว
ในเวลานี้อินสแตนซ์ถั่วนั้นสามารถใช้งานได้อย่างสมบูรณ์ แต่ฤดูใบไม้ผลิยังเตรียมกลยุทธ์ที่ยืดหยุ่นสำหรับเราในขั้นตอนการสร้างอินสแตนซ์เพื่อให้การแทรกแซงของผู้ใช้เสร็จสมบูรณ์ในขั้นตอนนี้ เช่นเดียวกับการควบคุม beanfactorypostprocessor beandefinition ในขั้นตอนการเริ่มต้นคอนเทนเนอร์ในระหว่างขั้นตอนการสร้างอินสแตนซ์สปริงให้โปรเซสเซอร์ BeanpostProcessor เพื่อทำงานบนอินสแตนซ์ที่ประกอบเพื่อให้การเปลี่ยนแปลงที่เป็นไปได้เสร็จสมบูรณ์:
นี่คือตัวอย่างที่แสดงให้เห็นว่าคุณกำหนดคลาสการใช้งาน beanpostprocessor โดยใช้วิธีการหลังโปรเจสเทอร์เทอร์เทอร์และโพสต์ postprocessbeforeinitialization เพื่อกำหนดการดำเนินการที่ดำเนินการแยกต่างหากหลังจากและก่อนการประกอบอินสแตนซ์ถั่ว หลังจากที่ beanfactory เพิ่มโปรเซสเซอร์นี้ทุกครั้งที่วิธีการ GetBean รวมตัวกันทั้งสองวิธีจะถูกเรียกในอินสแตนซ์ถั่วที่ประกอบขึ้นตาม "การวาด" (รวมถึงอินสแตนซ์ที่ขึ้นอยู่กับถั่วที่สร้างขึ้นระหว่างกระบวนการประกอบ) วิธีการเหล่านี้สามารถแก้ไขอินสแตนซ์ถั่วเหล่านี้ได้
นี่คือตัวอย่างเช่นนี้ (MainModule และการพึ่งพาของมันเหมือนกับที่ก่อนหน้านี้ในบทความนี้):
คลาส modulec {สตริงส่วนตัว x; สตริงสาธารณะ getx () {return x; } โมฆะสาธารณะ setx (สตริง x) {this.x = x; }} คลาส ModulePostProcessor ใช้ beanPostProcessor {@Override วัตถุสาธารณะ postprocessafterinitialization (วัตถุวัตถุสตริงสตริง) พ่น beansexception {system.out.println (สตริง); if (วัตถุอินสแตนซ์ของ modulec) {system.out.println (สตริง); ((modulec) วัตถุ) .setx ("หลังจาก"); } return object; } @Override วัตถุสาธารณะ PostprocessBeforeInitialization (วัตถุวัตถุ, สตริงสตริง) พ่น beansexception {if (วัตถุอินสแตนซ์ของ modulec) {((modulec) วัตถุ) .setx ("ก่อน"); } return object; }} ชั้นเรียนสาธารณะมาก SimpleIockernal {โมฆะคงที่สาธารณะหลัก (String [] args) พ่น classnotfoundexception, beansexception, instantiationexception, ungleclaccessexception {defaultlistablebeanfactory beanfactory = ใหม่ XMLBEANDEFINITIONREADER Reader = ใหม่ XMLBEANDEFINITIONREADER (BeanFactory); Reader.loadBeanDefinitions (ใหม่ classPathResource ("beans.xml")); modulePostProcessor postprocessor = ใหม่ modulePostProcessor (); beanfactory.addbeanpostprocessor (postprocessor); MainModule โมดูล = (MainModule) BeanFactory.getBean ("MainModule"); modulec modulec = (modulec) beanfactory.getBean ("modulec"); System.out.println (modulec.getx ()); -นี่คือไฟล์กำหนดค่าการพึ่งพาสำหรับถั่ว:
<? xml version = "1.0" การเข้ารหัส = "utf-8"?> <beans xmlns = "http://www.springframework.org/schema/beans" xmlns: xsi = "http://ww.w3.org/2001/xml XSI: schemalocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans http://www.springframework.org/schema/schema/schema <property name = "modulea"> <ref bean = "modulea"/> </property> <property name = "moduleb"> <ref bean = "moduleb"/> </property> </ebean> <bean id = "modulea"> <property name = "infoa"> <ค่า> $ {modulea <property name = "infob"> <value> ข้อมูลของ moduleb </alue> </porement> </ebean> <bean id = "modulec"> </ebean> </ebeans>จากผลลัพธ์สุดท้ายเราจะเห็นได้ว่าทุกครั้งที่อินสแตนซ์ของ GetBean (รวมถึงการขึ้นอยู่กับการพึ่งพา) ที่ได้รับจากการเรียกวิธี GetBean จะถูกเรียกคืนโดย BeanPostProcessor สำหรับการประมวลผลก่อนและหลังการประมวลผล
นอกเหนือจากการประมวลผลถั่วที่ประกอบคล้ายกับ beanpostprocessor ข้างต้นสปริงยังสามารถตั้งค่าฟังก์ชั่นการโทรกลับสำหรับการเริ่มต้นและกระบวนการทำลายล้างของถั่วโดยการกำหนดค่าวิธีการเริ่มต้นและการทำลายวิธีการ ฟังก์ชั่นการโทรกลับเหล่านี้ยังสามารถให้โอกาสในการเปลี่ยนอินสแตนซ์ถั่วได้อย่างยืดหยุ่น
กระบวนการ IOC ฤดูใบไม้ผลิทั้งหมดนั้นเป็นหลักเช่นเดียวกับต้นแบบ IOC ที่เราเขียนเองยกเว้นว่าการออกแบบที่ซับซ้อนช่วยให้กระบวนการ IOC สามารถให้ผู้ใช้มีพื้นที่ได้อย่างยืดหยุ่นและมีประสิทธิภาพมากขึ้น นอกจากนี้ IOC ของฤดูใบไม้ผลิยังได้รับการออกแบบที่ยอดเยี่ยมในแง่ของความปลอดภัยเสถียรภาพของภาชนะและข้อมูลเมตาเพื่อการแปลงถั่วทำให้รากฐานของ IOC, ภาชนะสปริง, เสถียร