JavaRush /مدونة جافا /Random-AR /إطار الربيع. مقدمة
Marchello
مستوى
Санкт-Петербург

إطار الربيع. مقدمة

نشرت في المجموعة
مرحبًا! بينما تعمل إدارة JavaRush على مستويات جديدة، أريد أن أبدأ سلسلة من المقالات التدريبية حول Spring Framework. نعم، أعلم أن هناك بالفعل الكثير من المواد حول هذا الموضوع على الإنترنت، ولكن، كما تظهر الممارسة، فهي جميعا على مستوى Hello World. لا أريد أن أتحدث عن كيفية وضع التعليقات التوضيحية بشكل صحيح، ولكن عن كيفية عمل كل شيء "تحت الغطاء". هذه المقالة مخصصة لأولئك الذين عملوا بالفعل مع هذا الإطار بطريقة أو بأخرى وهم على دراية بالمفاهيم الأساسية. إطار الربيع.  مقدمة - 1

تهيئة السياق.

لذلك دعونا نبدأ بالأساسيات. في رأيي، إحدى أهم النقاط هي فهم كيفية إعداد السياق وتهيئة الفاصوليا. كما تعلم، قبل أن يبدأ الربيع في العمل، يجب تكوينه. في أوقات ما قبل الطوفان، تم ذلك باستخدام ملفات 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 تكويننا، هناك XmlBeanDefinitionReader. BeanDefinitionهذا هو مكون Spring الداخلي الذي يقوم بمسح (توزيع) ملف XML وإنشاء ملف 's بناءً على ما كتبناه هناك . BeanDefinitionهو كائن يقوم بتخزين معلومات حول الحبة. وهذا يشمل: من أي فئة يجب أن يتم إنشاؤها (الفاصوليا)؛ نِطَاق؛ ما إذا كان قد تم تثبيت التهيئة البطيئة؛ هل من الضروري التهيئة قبل هذه الحبة بخصائص أخرى وأخرى موصوفة في ملف XML. تتم إضافة جميع BeanDefinitionالعناصر المستلمة إلى HashMap، حيث يكون المعرف هو اسم الحبة (التي قمت بتعيينها أو تم تعيينها بواسطة Spring) والكائن BeanDefinitionنفسه. بعد BeanDefinitionإنشاء كل شيء، يظهر بطل جديد على المسرح - BeanFactory. يتكرر هذا الكائن عبر HashMap’es BeanDefinitionوينشئ حبوبًا بناءً عليها ويضعها في حاوية IoC. هناك فارق بسيط هنا، في الواقع، عند بدء التطبيق، ستحتوي حاوية IoC على حبوب تحتوي على نطاق Singleton (يتم تعيينه افتراضيًا)، بينما يتم إنشاء الباقي عند الحاجة (النموذج الأولي، الطلب، الجلسة). والآن استطرادا صغيرا، دعونا نتعرف على شخصية أخرى.

تعرف على BeanPostProcessor. (بب)

معالج آخر الفولالحقيقة هي أن الفول ليس بالضرورة فئة من منطق الأعمال لتطبيقك. تُسمى الفاصوليا أيضًا بفاصوليا البنية التحتية. باختصار، وحدة البنية التحتية هي فئة تقوم بتكوين وحدات منطق الأعمال الخاصة بك (نعم، هناك عدد كبير جدًا من الوحدات). سأخبرك بالمزيد حول هذا الموضوع أدناه، ولكن لكي يكون الأمر أكثر وضوحًا قليلاً، ما هي تكوينات BPP بالضبط، سأقدم مثالاً. هل الجميع على دراية بالملخص @Autowired؟ لذلك، أنت AutowiredAnnotationBeanPostProcessorمسؤول عن ضمان دمج جميع فصولك الدراسية مع بعضها البعض. uknowimean

دعنا نعود إلى BeanFactory

بعد أن عرفنا الآن عن BPP، من الضروري توضيح أنه عند التكرار عبر HashMap's، BeanDefinitionيتم أولاً إنشاء الكل ووضعه بشكل منفصل (ليس في حاوية IoC) BeanPostProcessor. بعد ذلك، يتم إنشاء الفاصوليا العادية لمنطق أعمالنا، ووضعها في حاوية IoC، ويبدأ تكوينها باستخدام BPPs المؤجلة بشكل منفصل. وهذه هي الطريقة التي يحدث بها كل BPP له طريقتان:
postProcessorBeforeInitialization(Object bean, String beanName);
postProcessorAfterInitialization(Object bean, String beanName);
يتكرر من خلال صناديقنا مرتين. في المرة الأولى يتم استدعاء الطريقة postProcessorBeforeInitialization، وفي المرة الثانية يتم استدعاء الطريقة postProcessorAfterInitialization. من المؤكد أن السؤال المطروح هو سبب الحاجة إلى طريقتين، اسمحوا لي أن أشرح ذلك. الحقيقة هي أنه لمعالجة بعض التعليقات التوضيحية (مثل @Transactional، على سبيل المثال)، يتم استبدال الفول الخاص بنا بفئة الوكيل. لفهم سبب القيام بذلك، عليك أن تعرف كيف يعمل @Transactional، وهذه هي الطريقة التي يعمل بها. تحتاج إلى إضافة سطرين آخرين من التعليمات البرمجية إلى الطريقة المميزة بهذا التعليق التوضيحي أثناء التنقل. كيف افعلها؟ هذا صحيح، عن طريق إنشاء فئة وكيل، والتي سيتم من خلالها إضافة الكود الضروري إلى الطريقة المطلوبة. الآن تخيل هذا الوضع، لدينا فئة:
class A {
    @Autowired
    private SomeClass someClass;

    @Transactional
    public void method() {
        // модификатор доступа обязательно public
    }
}
يحتوي هذا الفصل على شروحتين @Autowiredو @Transactional. تتم معالجة كلا التعليقين التوضيحيين بواسطة BPPs مختلفة. إذا نجح أولاً AutowiredBPP، فسيكون كل شيء على ما يرام، ولكن إذا لم يكن كذلك، فسنواجه هذه المشكلة. والحقيقة هي أنه عند إنشاء فئة الوكيل، يتم فقدان كافة المعلومات التعريفية. بمعنى آخر، لن تكون هناك معلومات حول التعليق التوضيحي @Autowiredفي فئة الوكيل، وبالتالي AutowiredBPPلن يعمل، مما يعني أن حقلنا someClassسيكون له القيمة null، والتي ستؤدي على الأرجح إلى NPE. ومن الجدير أيضًا معرفة أنه بين استدعاءات الطريقة، postProcessorBeforeInitializationيتم postProcessorAfterInitializationاستدعاء الأسلوب init- إذا كان هناك واحد. هذا هو في الأساس المُنشئ الثاني، لكن الفرق هو أنه في هذه اللحظة تكون جميع تبعياتنا مضمنة بالفعل في الفصل ويمكننا الوصول إليها من خلال initالطريقة. لذلك، مرة أخرى خوارزمية تهيئة السياق:
  1. XmlBeanDefinitionReaderيقوم بمسح ملف تكوين XML الخاص بنا.
  2. ينشئ BeanDefinitionويضعها في HashMap.
  3. يأتي BeanFactoryومن هذا HashMapبشكل منفصل يضيف كل ما في BeanPostProcessorالأمر.
  4. يقوم بإنشاء BeanDefinitionالحبوب من 's ويضعها في حاوية IoC.
  5. هنا تأتي BPPs وتقوم بتكوين هذه الحبوب باستخدام طريقتين.
  6. مستعد.
في الواقع، هذا كل شيء، اكتب إذا أعجبك المقال وما إذا كان الأمر يستحق الاستمرار في كتابة مثل هذه البرامج التعليمية.
تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION