คำนำ
ด้วยความนิยมที่เพิ่มขึ้นของการบูตฤดูใบไม้ผลิการกำหนดค่าส่วนใหญ่ในแอปพลิเคชันจะถูกซ่อนไว้ เราจำเป็นต้องใส่ใจเกี่ยวกับเนื้อหาธุรกิจจริงคอนโทรลเลอร์บริการที่เก็บและเมื่อคุณรับแป้นพิมพ์คุณสามารถใช้สำเนาของรหัสธุรกิจ การสแกนองค์ประกอบเฉพาะมุมมองตัวยึด ... สามารถทิ้งไว้ข้างหลังได้ แต่ในความเป็นจริงการกำหนดค่าศูนย์นี้ไม่นานในการพัฒนาแอปพลิเคชัน Java "มันยากที่จะได้รับจากฟุ่มเฟือยไปสู่ความตระหนี่" นักพัฒนาหลายคนมีประสบการณ์การกำหนดค่า Spring XML ที่ยาวนานและมันยากที่จะกลับไปที่การกำหนดค่านี้
แต่บางครั้งเนื่องจากเนื้อหาการกำหนดค่าไม่ได้ถูกนำไปใช้อย่างดีในการกำหนดค่าศูนย์เช่น Spring Boot เราจึงต้องใช้แบบฟอร์มการกำหนดค่า XML จากนั้นนำเข้าแหล่งที่มาหรือบางโครงการได้รับผลกระทบจากสภาพแวดล้อมและไม่ได้รับการพัฒนาโดยใช้การบูต
จากนั้นลองย้อนกลับไปดูเนื้อหาสคีมาที่กำหนดเองบางส่วนในการกำหนดค่า XML วิธีการที่เนื้อหาสคีมาที่กำหนดเองบางส่วนรวมเข้ากับฤดูใบไม้ผลิสำหรับการกำหนดค่า ตัวอย่างเช่น:
สปริงข้อมูล ES
เกี่ยวกับทูบโบ
มีตัวอย่างมากมายที่เราจะไม่แสดงรายการทีละรายการ แต่ผ่านตัวเลขสองตัวข้างต้นเราพบคุณลักษณะทั่วไป:
ดังนั้นการกำหนดค่าที่กำหนดเองเหล่านี้ทำงานเมื่อใด จะตรวจสอบได้อย่างไรว่าการกำหนดค่าถูกต้องหรือไม่?
มาดูสปริงที่มีไฟล์ชื่อ Spring.handlers ส่วนขยายที่กำหนดเองทั้งหมดมีผลผ่านไฟล์นี้ Spring Official AOP และ TX ก็มีหลักการนี้เช่นกัน
ไฟล์นี้อยู่ที่ไหน
ดังที่แสดงในรูปด้านบนมันเป็น meta-inf/spring.handlers เนื้อหาไฟล์นั้นง่ายมากเช่นกัน:
http/: //www.springframework.org/schema/data/elasticsearch=org.springframework.data.elasticsearch.config.elasticsearchnamespaceHandler
อย่างแรกคือคำนำหน้าของแต่ละสคีมาและถัดไปคือคลาสการแยกวิเคราะห์ที่สอดคล้องกับสคีมา ไฟล์ Spring.Handlers โหลดเมื่อใด
สิ่งนี้ยังเกิดขึ้นเมื่อแยกวิเคราะห์ไฟล์การกำหนดค่าที่กำหนดเอง มีกระบวนการแก้ไข ในเวลานี้ไฟล์ spring.handlers ทั้งหมดที่สอดคล้องกับ classloader ปัจจุบันจะถูกโหลด
มาดูคลาสการวิเคราะห์นี้อีกครั้งเนื้อหามีดังนี้:
ชั้นเรียนสาธารณะ ElasticSearchNamesPaceHandler ขยาย NamespaceHandlersupport {สาธารณะ ElasticSearchNamesPaceHandler () {} โมฆะสาธารณะเริ่มต้น () {repositoryConfigurationExtension Extension = ใหม่ ElasticSearchRepositoryConfigextension (); RepositoryBeanDefinitionParser Parser = ใหม่ RepositoryBeandEfinitionParser (ส่วนขยาย); this.registerbeandefinitionparser ("ที่เก็บ", parser); this.registerBeanDefinitionParser ("Node-client", ใหม่ nodeClientBeandEfinitionParser ()); this.registerBeandEfinitionParser ("การขนส่ง-ลูกค้า", TransportClientBeandEfinitionParser ()); - ก่อนอื่นมันได้รับการสืบทอดจาก NamesapceHandlersupport
จากนั้นชุดของตัวแยกวิเคราะห์จะลงทะเบียนในวิธีการที่เขียนใหม่ ตัวแยกวิเคราะห์แต่ละตัวสอดคล้องกับสตริงซึ่งเป็นเนื้อหาที่กำหนดเองที่เราใช้ในไฟล์กำหนดค่า XML เช่นการกำหนดค่า ES ด้านบน
<ElasticSearch: ID-Client ID = "ไคลเอนต์" คลัสเตอร์-Nodes = "192.168.73.186:9300" คลัสเตอร์
การกำหนดค่าที่นี่จะถูกแยกวิเคราะห์ผ่าน TransportClientBeandEfinitionParser ในที่สุด
ตัวแยกวิเคราะห์ที่กล่าวถึงข้างต้นจะถูกเก็บไว้ในแผนที่ในวิธีการเริ่มต้น
แผนที่สุดท้ายส่วนตัว <String, BeanDefinitionParser> parsers = new hashmap ();
การลงทะเบียนที่เรียกว่าการแยกวิเคราะห์คือการวางแผนที่ของตัวแยกวิเคราะห์นี้
เมื่อมองย้อนกลับไปเนื้อหาหลักที่สุดในฤดูใบไม้ผลิคืออะไร? มันคือถั่ว ในความเป็นจริงเนื้อหาที่เรากำหนดค่าใน XML ในที่สุดจะถูกสร้างขึ้นในถั่วที่สอดคล้องกัน การกำหนดค่าทั้งหมดเป็นเพียงการสร้างถั่ว การกำหนดค่าที่กำหนดเองเหล่านี้เรียกว่า BeanDefinition
ดังนั้นเมื่อสปริงแยกวิเคราะห์ไฟล์การกำหนดค่าจะมีการตัดสินดังต่อไปนี้: ไม่ว่าจะเป็น defaultNamespace หรือไม่ ถ้าไม่ไปที่ CustomElementParse
Void ParsebeanDefinitions (Element Root, BeanDefinitionParserDelegate Delegate) {ถ้า (Delegate.isdefaultNamespace (root)) {nodelist nl = root.getChildNodes (); สำหรับ (int i = 0; i <nl.getLength (); ++ i) {node node = nl.item (i); if (Node Instancef Element) {Element Ele = (Element) Node; if (delegate.isdefaultnamespace (ele)) {this.parsedefaultelement (ele, ผู้แทน); } else {Delegate.parSecustomelement (ELE); }}}} else {Delegate.parSecustomelement (root); - แต่การตัดสินที่ไม่ใช่ defaultnamespace นั้นโดยตรงมากขึ้น: Namespace URI มีเนื้อหาหรือไม่หรือเป็นคำสั่งของถั่วฤดูใบไม้ผลิ
บูลีนสาธารณะ isdefaultnamespace (สตริง namespaceuri) {return! stringutils.haslength (namespaceuri) || "http://www.springframework.org/schema/beans".equals(namespaceuri); - ดังนั้นคำขอทั้งหมดจึงไปที่ Parsecustomelement และการวิเคราะห์การกำหนดค่าเริ่มต้นขึ้น เมื่อแยกวิเคราะห์ตัวจัดการที่สอดคล้องกันถูกพบผ่าน uriresolver
PARSECUSTOMELEMENT สาธารณะ (Element Ele, BeanDefinition containsbd) {สตริง namespaceuri = this.getNamespaceuri (ELE); namespaceHandler handler = this.readerContext.getNamespaceHandlerresolver (). แก้ไข (namespaceuri); if (handler == null) {this.error ("ไม่สามารถค้นหาสปริง namespaceHandler สำหรับ xml schema namespace [" + namespaceuri + "]", ele); คืนค่า null; } else {return handler.parse (ele, parsercontext ใหม่ (this.readerContext, this, attainingbd)); - ในเวลานี้สิ่งเดียวที่ถูกส่งคืนคือตัวจัดการที่กำหนดค่าในฤดูใบไม้ผลิผู้ดูแลและตัวจัดการแต่ละคนลงทะเบียนการแยกวิเคราะห์จำนวนมากและกระบวนการของการได้รับการแยกวิเคราะห์เป็นสิ่งจำเป็น
Public BeanDefinition Parse (องค์ประกอบองค์ประกอบ, parsercontext parsercontext) {return this.findparserForElement (องค์ประกอบ, parsercontext) .parse (องค์ประกอบ, parsercontext); } ส่วนตัว beandefinitionparser findParserForElement (องค์ประกอบองค์ประกอบ, parsercontext parsercontext) {String localName = parsercontext.getDelegate (). getLocalName (องค์ประกอบ); BeanDefinitionParser Parser = (BeanDefinitionParser) this.parsers.get (ชื่อท้องถิ่น); if (parser == null) {parsercontext.getReaderContext (). fatal ("ไม่สามารถค้นหา beanDefinitionParser สำหรับองค์ประกอบ [" + localName + "]", องค์ประกอบ); } ส่งคืน parser; - กระบวนการของการได้รับสิ่งนี้คือการได้รับตัวแยกวิเคราะห์ที่สอดคล้องกันในแผนที่เราเริ่มประกาศผ่านสตริงที่ผ่านเข้ามาจากนั้นใช้สำหรับการแยกการกำหนดค่า
ด้วยตัวแยกวิเคราะห์กระบวนการสร้าง beandefinition จะถูกติดตาม
เราเห็นว่าตัวแยกวิเคราะห์เหล่านี้สืบทอดมาจาก AbstractBeandEfinitionParser หรือใช้อินเทอร์เฟซของ BeanDefinitionParser วิธีการแยกวิเคราะห์อินเตอร์เฟสคือทางเข้าสู่การแยกวิเคราะห์แบบครบวงจร
ระดับสาธารณะ TransportClientBeanDefinitionParser ขยาย AbstractBeanDefinitionParser {Public TransportClientBeanDefinitionParser () {} การป้องกันบทคัดย่อ AbstractBeandefinition ParseInternal (องค์ประกอบองค์ประกอบ, parsercontext parsercontext) beandefinitionbuilder.rootbeandefinition (TransportClientFactoryBean.class); this.setConfigurations (องค์ประกอบ, ผู้สร้าง); ส่งคืนสิ่งนี้ GetSourcedBeandEfinition (Builder, Element, ParserContext); - ในวิธี parseinternal ที่เขียนใหม่ให้ส่งคืน beandefinition ที่เกี่ยวข้องหลังจากแยกวิเคราะห์การกำหนดค่า นี่เป็นสถานที่ที่มีเฟรมเวิร์กต่าง ๆ เป็นบทสรุปได้อย่างอิสระ ตัวอย่างเช่นเฟรมเวิร์กบางอย่างง่ายและตรงไปตรงมาในขณะที่บางส่วนจะใช้รูปแบบการออกแบบบางอย่างเช่นกลยุทธ์และนักตกแต่งเพื่อให้มีความยืดหยุ่นมากขึ้น
หลังจากได้รับ beandefinition วางไว้ในบริบททั้งหมดเพื่อสร้างเนื้อหาของถั่วฤดูใบไม้ผลิและเราจะวิเคราะห์ในภายหลัง
สรุป
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่าเนื้อหาของบทความนี้จะมีค่าอ้างอิงบางอย่างสำหรับการศึกษาหรือที่ทำงานของทุกคน หากคุณมีคำถามใด ๆ คุณสามารถฝากข้อความไว้เพื่อสื่อสาร ขอบคุณสำหรับการสนับสนุน Wulin.com