Salom! JavaRush ma'muriyati yangi darajalarda ishlayotgan bir paytda, men Spring Framework bo'yicha bir qator o'quv maqolalarini boshlamoqchiman. Ha, men Internetda ushbu mavzu bo'yicha juda ko'p materiallar mavjudligini bilaman, ammo amaliyot shuni ko'rsatadiki, ularning barchasi Salom Dunyo darajasida. Men izohlarni qanday qilib to'g'ri joylashtirish haqida emas, balki barchasi "qopqoq ostida" qanday ishlashi haqida gapirmoqchiman. Maqola ushbu ramka bilan u yoki bu tarzda ishlagan va asosiy tushunchalar bilan tanish bo'lganlar uchun mo'ljallangan.
Kontekstni ishga tushirish.
Shunday qilib, keling, asosiy narsalardan boshlaylik. Menimcha, eng muhim nuqtalardan biri kontekst qanday tuzilganligini va loviya ishga tushirilishini tushunishdir. Ma'lumki, Spring ishlashni boshlashdan oldin uni sozlash kerak. Qadimgi davrlarda bu xml fayllari yordamida amalga oshirilgan (ba'zi loyihalarda, asosan eski loyihalarda, ular bugungi kungacha buni davom ettirmoqdalar). Mana shunday konfiguratsiya faylining kichik misoli:<?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>
Umuman olganda, bu bir nechta kontrollerlarni yaratish va startapni ishga tushirish uchun kifoya qiladi (ular chiqmaydi). Ammo bu konfiguratsiya Springni qanday ishlaydi? Va bu erda narsalar qiziqarli bo'ladi. Bizning konfiguratsiyamiz Bahor tomonidan tushunilishi uchun mavjud XmlBeanDefinitionReader
. Bu ichki Spring komponenti bo'lib, u xml ni skanerlaydi (tahlil qiladi) va u erda yozganimiz asosida BeanDefinition
's yaratadi. BeanDefinition
loviya haqidagi ma'lumotlarni saqlaydigan ob'ektdir. Bunga quyidagilar kiradi: u (loviya) qaysi sinfdan yaratilishi kerak; qamrovi; dangasa ishga tushirish o'rnatilganmi; Bu fasoldan oldin xml da tasvirlangan boshqa va boshqa xususiyatlarni ishga tushirish kerakmi. Barcha qabul qilinganlar BeanDefinition
ga qo'shiladi HashMap
, bunda identifikator loviya nomi (siz o'rnatgan yoki Bahor tomonidan tayinlangan) va BeanDefinition
ob'ektning o'zi hisoblanadi. Hamma narsa yaratilgandan so'ng BeanDefinition
, sahnada yangi qahramon paydo bo'ladi - BeanFactory
. Ushbu ob'ekt HashMap’e
s ustida takrorlanadi BeanDefinition
, ular asosida loviya yaratadi va ularni IoC konteyneriga joylashtiradi. Bu erda bir nuance bor, aslida, dastur ishga tushganda, IoC konteynerida Singleton miqyosi (sukut bo'yicha o'rnatilgan) bo'lgan loviyalar bo'ladi, qolganlari esa kerak bo'lganda yaratiladi (prototip, so'rov, seans). Va endi kichik bir chekinish, keling, boshqa xarakter bilan tanishaylik.
BeanPostProcessor bilan tanishing. (BPP)
Gap shundaki, loviya sizning ilovangiz uchun biznes mantiqiy sinfi bo'lishi shart emas. Fasol, shuningdek, infratuzilma loviya deb ataladi. Muxtasar qilib aytganda, infratuzilma loviya sizning biznes mantiq loviyalarini (ha, juda ko'p loviya) sozlaydigan sinfdir. Quyida men sizga bu haqda ko'proq aytib beraman, lekin BPP aynan nimani sozlashini biroz aniqroq qilish uchun men misol keltiraman. Xulosa bilan hamma tanishmi@Autowired
? Shunday qilib, siz AutowiredAnnotationBeanPostProcessor
barcha sinflaringiz bir-biriga o'rnatilganligini ta'minlash uchun javobgarsiz.
Keling, BeanFactory-ga qaytaylik
Endi BPP haqida bilgan holda, shuni aniqlashtirish kerakki, "overHashMap
" larni takrorlashda BeanDefinition
barcha 's birinchi navbatda yaratiladi va alohida joylashtiriladi (IoC konteynerida emas) BeanPostProcessor
. Shundan so'ng, bizning biznes mantiqimizning oddiy loviyalari yaratiladi, IoC konteyneriga joylashtiriladi va ularning konfiguratsiyasi alohida kechiktirilgan BPPlardan foydalanishni boshlaydi. Va bu shunday bo'ladi, har bir BPPning 2 usuli bor:
postProcessorBeforeInitialization(Object bean, String beanName);
postProcessorAfterInitialization(Object bean, String beanName);
Ikki marta qutilarimiz orqali takrorlanadi. Birinchi marta usul chaqiriladi postProcessorBeforeInitialization
, ikkinchi marta esa usul chaqiriladi postProcessorAfterInitialization
. Albatta, nima uchun ikkita usul kerak degan savol tug'ildi, men tushuntirib beraman. Gap shundaki, ba'zi izohlarni qayta ishlash uchun (masalan @Transactional
, ) bizning fasolimiz proksi-klass bilan almashtiriladi. Bu nima uchun amalga oshirilganligini tushunish uchun siz uning qanday ishlashini bilishingiz kerak @Transactional
va u qanday ishlaydi. Tezda ushbu izoh bilan belgilangan usulga yana bir necha qator kod qo'shishingiz kerak. Buni qanday qilish kerak? To'g'ri, proksi-klassni yaratish orqali, uning ichida kerakli kod kerakli usulga qo'shiladi. Endi bu vaziyatni tasavvur qiling, bizda sinf bor:
class A {
@Autowired
private SomeClass someClass;
@Transactional
public void method() {
// модификатор доступа обязательно public
}
}
Bu sinfda 2 ta izoh @Autowired
va @Transactional
. Ikkala izoh ham turli BPPlar tomonidan qayta ishlanadi. Agar u birinchi bo'lib ishlayotgan bo'lsa AutowiredBPP
, unda hamma narsa yaxshi bo'ladi, lekin agar bo'lmasa, biz bu muammoga duch kelamiz. Gap shundaki, proksi-klass yaratilganda barcha meta-ma'lumotlar yo'qoladi. @Autowired
Boshqacha qilib aytganda, proksi-sinfda annotatsiya haqida hech qanday ma'lumot bo'lmaydi va shuning uchun AutowiredBPP
u ishlamaydi, ya'ni bizning maydonimiz someClass
qiymatga ega bo'ladi null
, bu katta ehtimol bilan NPEga olib keladi. Shuni ham bilish kerakki, usul chaqiruvlari orasida, agar mavjud bo'lsa, -metod postProcessorBeforeInitialization
chaqiriladi . Bu asosan ikkinchi konstruktor, lekin farq shundaki, hozirda bizning barcha bog'liqliklarimiz allaqachon sinfga kiritilgan va biz ularga -metod orqali kirishimiz mumkin. Shunday qilib, yana bir bor kontekstni ishga tushirish algoritmi: postProcessorAfterInitialization
init
init
XmlBeanDefinitionReader
xml konfiguratsiya faylimizni skanerlaydi.- 's yaratadi
BeanDefinition
va ularni qo'yadiHashMap
. - Keladi
BeanFactory
va bundanHashMap
alohida barcha 'larni qo'shadiBeanPostProcessor
. - 's dan loviya yaratadi
BeanDefinition
va ularni IoC konteyneriga joylashtiradi. - Bu erda BPPlar keladi va bu loviyalarni 2 usuldan foydalanib sozlaydi.
- Tayyor.
GO TO FULL VERSION