JavaRush /จาวาบล็อก /Random-TH /กรอบสปริง การแนะนำ
Marchello
ระดับ
Санкт-Петербург

กรอบสปริง การแนะนำ

เผยแพร่ในกลุ่ม
สวัสดี! ในขณะที่การดูแลระบบ JavaRush กำลังทำงานในระดับใหม่ ฉันต้องการเริ่มบทความการฝึกอบรมเกี่ยวกับ Spring Framework ใช่ ฉันรู้ว่ามีเนื้อหามากมายในหัวข้อนี้บนอินเทอร์เน็ต แต่ดังที่แสดงให้เห็นในทางปฏิบัติ เนื้อหาทั้งหมดอยู่ในระดับ Hello World ฉันต้องการพูดไม่เกี่ยวกับวิธีการวางคำอธิบายประกอบอย่างถูกต้อง แต่เกี่ยวกับวิธีการทำงานทั้งหมด "ภายใต้ประทุน" บทความนี้มีไว้สำหรับผู้ที่เคยทำงานกับกรอบงานนี้ไม่ทางใดก็ทางหนึ่งและคุ้นเคยกับแนวคิดพื้นฐาน กรอบสปริง  บทนำ - 1

การเริ่มต้นบริบท

เริ่มจากพื้นฐานกันก่อน ในความคิดของฉัน หนึ่งในประเด็นที่สำคัญที่สุดคือการทำความเข้าใจวิธีการตั้งค่าบริบทและการเริ่มต้น bean อย่างที่คุณทราบ ก่อนที่Springจะเริ่มทำงาน จะต้องได้รับการกำหนดค่าก่อน ในสมัยโบราณ สิ่งนี้ทำได้โดยใช้ไฟล์ xml (ในบางโปรเจ็กต์ ซึ่งส่วนใหญ่เป็นโปรเจ็กต์เก่า พวกเขายังคงทำเช่นนี้มาจนถึงทุกวันนี้) นี่เป็นตัวอย่างเล็กๆ ของไฟล์การกำหนดค่าดังกล่าว:
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

   <bean id="helloWorld" class="ru.javarush.HelloWorld">
       <property name="message" value="Hello World!"/>
   </bean>

</beans>
โดยทั่วไปแล้วนี่ก็เพียงพอที่จะสร้างคอนโทรลเลอร์สองสามตัวและเริ่มต้นการเริ่มต้น (ซึ่งจะไม่เกิดขึ้น) แต่การกำหนดค่านี้จะทำให้ Spring ทำงานอย่างไร และนี่คือสิ่งที่น่าสนใจ เพื่อให้ Spring เข้าใจการกำหนดค่าของเรา มีไฟล์XmlBeanDefinitionReader. นี่คือองค์ประกอบ Spring ภายในที่สแกน (แยกวิเคราะห์) xml และสร้าง ตามสิ่งที่เราเขียนไว้ที่BeanDefinitionนั่น BeanDefinitionเป็นวัตถุที่เก็บข้อมูลเกี่ยวกับถั่ว ซึ่งรวมถึง: ควรสร้างคลาส (bean) จากคลาสใด; ขอบเขต; ไม่ว่าจะติดตั้งการเริ่มต้นแบบขี้เกียจหรือไม่ จำเป็นต้องเริ่มต้นก่อน bean นี้หรือไม่ และคุณสมบัติอื่น ๆ ที่อธิบายไว้ใน xml ที่ได้รับทั้งหมดBeanDefinitionจะถูกเพิ่มเข้าไปHashMapใน โดยที่ตัวระบุคือชื่อของ bean (ตั้งค่าโดยคุณหรือกำหนดโดย Spring) และBeanDefinitionตัววัตถุเอง หลังจากที่ทุกอย่างBeanDefinitionถูกสร้างขึ้น ฮีโร่คนใหม่ก็ปรากฏตัวบนเวที - BeanFactory. วัตถุนี้วนซ้ำHashMap’es BeanDefinitionสร้าง bean ตามพวกมันและวางลงในคอนเทนเนอร์ IoC ในความเป็นจริงมีความแตกต่างเล็กน้อยที่นี่ เมื่อแอปพลิเคชันเริ่มต้น คอนเทนเนอร์ IoC จะมี bean ที่มีขอบเขต Singleton (ตั้งค่าตามค่าเริ่มต้น) ในขณะที่ส่วนที่เหลือจะถูกสร้างขึ้นเมื่อจำเป็น (ต้นแบบ คำขอ เซสชัน) และตอนนี้เป็นการพูดนอกเรื่องเล็ก ๆ มาทำความรู้จักกับตัวละครอื่นกันดีกว่า

พบกับ BeanPostProcessor (บีพีพี)

โปรเซสเซอร์โพสต์ถั่วความจริงก็คือ bean ไม่จำเป็นต้องเป็นคลาสของตรรกะทางธุรกิจสำหรับแอปพลิเคชันของคุณ ถั่วเรียกอีกอย่างว่าถั่วโครงสร้างพื้นฐาน กล่าวโดยสรุปคือ Infrastructure bean คือคลาสที่กำหนดค่า Bean ตรรกะทางธุรกิจของคุณ (ใช่ มี Bean มากเกินไป) ฉันจะบอกคุณเพิ่มเติมเกี่ยวกับเรื่องนี้ด้านล่าง แต่เพื่อให้ชัดเจนขึ้นเล็กน้อยว่าการกำหนดค่า BPP ที่แน่นอนคืออะไร ฉันจะยกตัวอย่าง ทุกคนคุ้นเคยกับบทสรุปหรือไม่@Autowired? ดังนั้นคุณAutowiredAnnotationBeanPostProcessorมีหน้าที่รับผิดชอบในการดูแลให้ชั้นเรียนทั้งหมดของคุณฝังอยู่ในกันและกัน ไม่รู้ความหมาย

กลับไปที่ BeanFactory กันดีกว่า

เมื่อทราบเกี่ยวกับ BPP แล้ว คุณต้องชี้แจงว่าเมื่อวนซ้ำHashMap's BeanDefinitionทั้งหมด ' จะถูกสร้างและวางแยกกันก่อน (ไม่ใช่ในคอนเทนเนอร์ IoC BeanPostProcessor) หลังจากนี้ Bean ปกติของตรรกะทางธุรกิจของเราจะถูกสร้างขึ้น ใส่ลงในคอนเทนเนอร์ IoC และการกำหนดค่าจะเริ่มโดยใช้ BPP ที่เลื่อนออกไปแยกกัน และนี่คือสิ่งที่เกิดขึ้น แต่ละ BPP มี 2 วิธี:
postProcessorBeforeInitialization(Object bean, String beanName);
postProcessorAfterInitialization(Object bean, String beanName);
วนซ้ำผ่านถังขยะของเราสองครั้ง ครั้งแรกที่เรียกเมธอด และครั้งที่สองที่ เรียกpostProcessorBeforeInitializationเมธอด postProcessorAfterInitializationแน่นอนว่ามีคำถามเกิดขึ้นว่าทำไมต้องใช้สองวิธี ให้ฉันอธิบาย ความจริงก็คือในการประมวลผลคำอธิบายประกอบบางอย่าง (เช่น เป็นต้น@Transactional) bean ของเราถูกแทนที่ด้วยคลาสพร็อกซี เพื่อทำความเข้าใจว่าเหตุใดจึงทำเช่นนี้ คุณจำเป็นต้องทราบวิธีการทำงาน@Transactionalและนี่คือวิธีการทำงาน คุณต้องเพิ่มโค้ดอีกสองสามบรรทัดให้กับวิธีการที่ทำเครื่องหมายด้วยคำอธิบายประกอบนี้ทันที ทำอย่างไร? ถูกต้องโดยการสร้างคลาสพร็อกซีซึ่งภายในโค้ดที่จำเป็นจะถูกเพิ่มลงในวิธีการที่ต้องการ ลองจินตนาการถึงสถานการณ์นี้ เรามีชั้นเรียน:
class A {
    @Autowired
    private SomeClass someClass;

    @Transactional
    public void method() {
        // модификатор доступа обязательно public
    }
}
คลาสนี้มีคำอธิบายประกอบ 2 รายการ@Autowiredและ@Transactional. คำอธิบายประกอบทั้งสองได้รับการประมวลผลโดย BPP ที่ต่างกัน ถ้ามันได้ผลก่อนAutowiredBPPทุกอย่างจะดี แต่ถ้าไม่ได้เราก็จะเจอปัญหานี้ ความจริงก็คือเมื่อมีการสร้างคลาสพร็อกซี ข้อมูลเมตาทั้งหมดจะสูญหายไป กล่าวอีกนัยหนึ่ง จะไม่มีข้อมูลเกี่ยวกับคำอธิบายประกอบ@Autowiredในคลาสพร็อกซี ดังนั้นจึงAutowiredBPPไม่ทำงาน ซึ่งหมายความว่าฟิลด์ของเราsomeClassจะมีค่าnullซึ่งมักจะนำไปสู่ ​​NPE นอกจากนี้ยังควรรู้ด้วยว่าระหว่างการเรียกใช้เมธอดนั้นpostProcessorBeforeInitializationจะpostProcessorAfterInitializationมีการเรียก เมธอด init- ถ้ามี โดยพื้นฐานแล้วนี่คือ Constructor ตัวที่สอง แต่ความแตกต่างก็คือ ในขณะนี้ การขึ้นต่อกันทั้งหมดของเราได้ถูกฝังอยู่ในคลาสแล้ว และเราสามารถเข้าถึงได้จากinitเมธอด - ดังนั้น อัลกอริธึมการเริ่มต้นบริบทอีกครั้ง:
  1. XmlBeanDefinitionReaderสแกนไฟล์การกำหนดค่า xml ของเรา
  2. สร้างBeanDefinition's และใส่ไว้ในHashMap.
  3. มาBeanFactoryและจากนี้HashMapแยกกันเพิ่มทั้งหมดBeanPostProcessor's
  4. สร้างBeanDefinitionbean จาก 's และวางไว้ในคอนเทนเนอร์ IoC
  5. ที่นี่ BPP มาและกำหนดค่า bean เหล่านี้โดยใช้ 2 วิธี
  6. พร้อม.
จริงๆ แล้ว นั่นคือทั้งหมด เขียนหากคุณชอบบทความนี้ และคุ้มค่าที่จะเขียนบทช่วยสอนดังกล่าวต่อไปหรือไม่
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION