JavaRush /Kurslar /All lectures for UZ purposes /Binning hayotiy tsikli, hayotiy tsikl qayta chaqirishlar

Binning hayotiy tsikli, hayotiy tsikl qayta chaqirishlar

All lectures for UZ purposes
Daraja, Dars
Mavjud

Spring ichida binning hayotiy tsiklini boshqarish mexanizmi bilan ishlash uchun InitializingBean va DisposableBean interfeyslarini amalga oshirish mumkin. Spring konteyneri birinchi uchun afterPropertiesSet() va ikkinchisi uchun destroy() chaqirib, biningizni tashkillashtirish va yo'q qilish paytida ma'lum bir harakatlarni bajaradigan imkon beradi.

JSR-250 bilan standartlashtirilgan @PostConstruct va @PreDestroy annotatsiyalari, zamonaviy Spring ilovasida hayotiy tsiklni qayta chaqirishni olishning eng yaxshi usuli hisoblanadi. Bu annotatsiyalarni ishlatish bilan, binlaringiz Spring-ga xos interfeyslarga bog'lanmagan bo'ladi.

JSR-250 annotatsiyalarini ishlatishni xohlamasangiz, lekin bog'lanishni kamaytirishni xohlasangiz, bin definitsiyasi uchun init-method va destroy-method metama'lumotlarini ko'ring.

Spring Framework ichida BeanPostProcessor amalga oshirilmoqda, buning uchun u topishi mumkin bo'lgan qayta chaqirish interfeyslarini ishlov berish va tegishli metodlarni chaqirish uchun. Agar sizga Spring standart ravishda taklif qilmaydigan maxsus funksiya yoki boshqa hayotiy tsikl mantiqi kerak bo'lsa, siz o'zingiz BeanPostProcessor ni amalga oshirishingiz mumkin.

Tashkillashtirish va yo'q qilish qayta chaqiruvlariga qo'shimcha ravishda, Spring tomonidan boshqariladigan obyektlar o'z hayotiy tsiklining boshlash va tugatish jarayonida ishtirok etishlari uchun Lifecycle interfeysini ham amalga oshirishi mumkin.

Hayotiy tsikl qayta chaqiruv interfeyslari ushbu bo'limda tavsiflangan.

Tashkillashtirish qayta chaqiruvlari

org.springframework.beans.factory.InitializingBean interfeysi, binga barcha kerakli xususiyatlari konteyner tomonidan o'rnatilgandan so'ng tashkillashtirishni bajarish imkonini beradi. InitializingBean interfeysi yagona metodni belgilaydi:

void afterPropertiesSet() throws Exception;

InitializingBean interfeysini ishlatishni tavsiya etmaymiz, chunki u kodni Spring bilan ortiqcha bog'laydi. Buning o'rniga @PostConstruct annotatsiyasidan foydalanishni yoki POJO tashkillashtirish metodini ko'rsatishni tavsiya qilamiz. Agar XML asosidagi konfiguratsiya metama'lumotlarini ishlatadigan bo'lsangiz, qaytarmaydigan va argumentlari bo'lmagan metod nomini ko'rsatish uchun init-method atributidan foydalanishingiz mumkin. Java konfiguratsiyasida @Bean ichida initMethod atributini ishlatishingiz mumkin. Quyidagi misolni ko'rib chiqing:

<bean id="exampleInitBean" class="examples.ExampleBean" init-method="init"/>
Java
public class ExampleBean {
    public void init() {
        // biroz tashkillashtirishni bajaramiz
    }
}
Kotlin
class ExampleBean {
    fun init() {
        // biroz tashkillashtirishni bajaramiz
    }
}

Oldingi misol deyarli quyidagi misoldagi kabi natija beradi (ikki listingdan iborat):

<bean id="exampleInitBean" class="examples.AnotherExampleBean"/>
Java
public class AnotherExampleBean implements InitializingBean {
    @Override
    public void afterPropertiesSet() {
        // biroz tashkillashtirishni bajaramiz
    }
}
Kotlin
class AnotherExampleBean : InitializingBean {
    override fun afterPropertiesSet() {
        // biroz tashkillashtirishni bajaramiz
    }
}

Biroq, birinchi ikkita misoldan iborati bo'lgan kod Spring bilan bog'liqlikdan xoli.

Yo'q qilish qayta chaqiruvlari

org.springframework.beans.factory.DisposableBean interfeysi amalga oshirilishi bilan, binda o'zini o'z ichiga olgan konteyner yo'q qilinayotganida qayta chaqiruvni oladi. DisposableBean interfeysi yagona metodni belgilaydi:

void destroy() throws Exception;

DisposableBean qayta chaqiruv interfeysini ishlatishni tavsiya etmaymiz, chunki u kodni Spring bilan ortiqcha bog'laydi. Buning o'rniga @PreDestroy annotatsiyasidan foydalanishni yoki umumiy metodni ko'rsatishni tavsiya qilamiz, uni bin ta'riflari qo'llab-quvvatlaydi. XML asosidagi konfiguratsiya metama'lumotlarini ishlatish orqali <bean/> elementidagi destroy-method atributidan foydalanishingiz mumkin. Java konfiguratsiyasida @Bean ichida destroyMethod atributidan foydalanishingiz mumkin. Quyidagi ta'rifni ko'rib chiqing:

<bean id="exampleInitBean" class="examples.ExampleBean" destroy-method="cleanup"/>
Java
public class ExampleBean {
    public void cleanup() {
        // biroz yo'q qilish ishlarini bajaramiz (masalan, ulanish pullarini bo'shatamiz)
    }
}
Kotlin
class ExampleBean {
    fun cleanup() {
        // biroz yo'q qilish ishlarini bajaramiz (masalan, ulanish pullarini bo'shatamiz)
    }
}

Oldingi ta'rif quyidagiga deyarli o'xshash natijani beradi:

<bean id="exampleInitBean" class="examples.AnotherExampleBean"/>
Java
public class AnotherExampleBean implements DisposableBean {
    @Override
    public void destroy() {
        // biroz yo'q qilish ishlarini bajaramiz (masalan, ulanish pullarini bo'shatamiz)
    }
}
Kotlin
class AnotherExampleBean : DisposableBean {
    override fun destroy() {
        // biroz yo'q qilish ishlarini bajaramiz (masalan, ulanish pullarini bo'shatamiz)
    }
}

Biroq, birinchi ikkita ta'rif Spring bilan bog'liq emas.

Siz <bean> elementining destroy-method atributiga (inferred) maxsus qiymatni berishingiz mumkin, bu Spring ga avtomatik ravishda benning konkret sinf uchun mavjud close yoki shutdown metodini topishga imkon beradi. (Shuning uchun, java.lang.AutoCloseable yoki java.io.Closeable ni amalga oshiradigan har qanday sinf mos keladi). Shuningdek, ushbu maxsus qiymatni default-destroy-method atributi yordamida barcha binlar to'plamini boshqarish uchun <beans> elementida ham o'rnatishingiz mumkin. Java konfiguratsiyasi ishlatilganda bu standart mantiqdir.

Tashkillashtirish va yo'q qilish uchun standart metodlar

Agar siz Spring ga xos bo'lmagan InitializingBean va DisposableBean interfeyslari haqida qayta chaqirish metodlarini yozmasangiz, u holda odatda siz init(), initialize(), dispose() va hokazo kabi nomlarga ega metodlar yozasiz. Ideal holda, bunday qayta chaqirish metodlari nomlari loyihaning doirasida standartlashtirilgan bo'ladi, shunda barcha ishlab chiquvchilar bir xil metod nomlarini qo'llaydi, bu esa izchillikni ta'minlaydi.

Siz Spring konteynerini tayin kiritilgan bin uchun qayta chaqirish metodlarining nomlarini topishga sozlashingiz mumkin, agar bunday ismlar ularga berilgan bo'lsa. Bu sizning ilova sinflaringizni yozishingiz va init() nomi bilan qayta chaqirish metodini ishlatishingiz mumkinligini anglatadi, har bir bin ta'rifi uchun init-method="init" atributini sozlash shart emas. Spring IoC-konteyneri bu metodni bin yaratishda (va standart qayta chaqirish hayotiy tsikl kontraktiga muvofiq) chaqiradi. Ushbu funksiya shuningdek, ishga tushirish va yo'q qilish metodlari qayta chaqirilishining izchil nomlanishi konvensiyasini ta'minlaydi.

Aytaylik, sizning tashkillashtirish qayta chaqiruv metodlaringiz init() deb nomlangan va yo'q qilish qayta chaqiruv metodlaringiz - destroy() deb nomlangan. Bunda sizning sinfingiz quyidagi misoldagi kabi ko'rinadi:

Java
public class DefaultBlogService implements BlogService {
    private BlogDao blogDao;
    public void setBlogDao(BlogDao blogDao) {
        this.blogDao = blogDao;
    }
    // bu (ajablanarli emas) tashkillashtirish qayta chaqiruv metodi
    public void init() {
        if (this.blogDao == null) {
            throw new IllegalStateException("The [blogDao] property must be set.");
        }
    }
}
Kotlin
class DefaultBlogService : BlogService {
    private var blogDao: BlogDao? = null
    // bu (ajablanarli emas) tashkillashtirish qayta chaqiruv metodi
    fun init() {
        if (blogDao == null) {
            throw IllegalStateException("The [blogDao] property must be set.")
        }
    }
}

Keyin siz ushbu sinfni quyidagiga o'xshagan binlarda ishlatishingiz mumkin:

<beans default-init-method="init">
    <bean id="blogService" class="com.something.DefaultBlogService">
        <property name="blogDao" ref="blogDao" />
    </bean>
</beans>

Tepada joylashgan <beans/> element atrubutida default-init-method atributining mavjud bo'lishi bunga olib keladi, shuning uchun Spring IoC-konteyneri bin sinfining init metodini qayta chaqirish metodi sifatida tan oladi. Agar bin yaratilsa va birlashtirilsa, agar bin sinfida shunday metod mavjud bo'lsa, u tegishli vaqtda amalga oshiriladi.

Siz yo'q qilish metodi qayta chaqiruvlarini shunga o'xshash tarzda (XML orqali) sozlashingiz mumkin, default-destroy-method atributidan foydalanib, <beans/> tepa darajadagi elementda.

Ba'zida mavjud bin sinflari allaqachon taklif qilinmagan nomga ega bo'lgan qayta chaqirish metodlarini o'z ichiga olgan hollarda, siz (XML orqali) nomini <bean/> ning init-method va destroy-method atributlari orqali belgilash orqali dasturiy ta'minotning umuman qiymatini o'zgartirishingiz mumkin.

Spring konteyneri, bin barcha bog'liqliklarni qabul qilgandan so'ng, sozlangan tashkillashtirish qayta chaqiruvini chaqiradi. Shu sababli, tashkillashtirish qayta chaqiruv bin uchun xomroq va hali unga AOP-interseptorlar va boshqalar qo'llanilmagan. Avvaliga maqsad bin to'liq yaratiladi, keyin AOP-proksi (misol uchun) o'zining interseptorlar zanjiri bilan qo'llaniladi. Agar maqsad bin va proksi alohida aniqlangan bo'lsa, sizning kodingiz hatto to'g'ridan-to'g'ri xom maqsad bina bilan o'zaro aloqada bo'lishi mumkin va proksi orqali emas. Shu sababli, init metodiga interseptorlarni qo'llash mantiqsiz bo'lardi, chunki bu holda maqsad bin hayotiy tsikli uning proksi yoki interseptorlar bilan bog'liqligini talab qiladi va natijada sizning kodingiz to'g'ridan-to'g'ri xom maqsad bina bilan o'zaro aloqada bo'ladi.

Hayotiy tsikl mexanizmlarini birlashtirish

Spring 2.5 versiyasidan boshlab, bin hayotiy tsikli mantiqini boshqarishning uchta variantini taklif qiladi:

  • InitializingBean va DisposableBean qayta chaqiruv interfeyslari

  • Maxsus init() va destroy() metodlari

  • @PostConstruct va @PreDestroy annotatsiyalari. Ushbu mexanizmlarini ma'lum bir binni boshqarish uchun birlashtira olasiz.

Agar bir bin uchun bir nechta hayotiy tsikl mexanizmlari sozlangan bo'lsa va har bir mexanizm o'zining metod nomiga ega bo'lsa, u holda har bir mexanizm bilan birgalikda belgilangan metod quyidagi eslatmadan keyin aytilgan tartibda chaqiriladi. Ammo, agar bir nominal metod - masalan, init() tashkillashtirish uchun - ushbu hayotiy tsikl mexanizmlaridan biri uchun sozlangan bo'lsa, ushbu metod bir marta chaqiriladi, bu esa oldingi bo'limda ta'riflangan tartibda amalga oshiriladi.

Turli metodlar bilan bir xil bin uchun konfigurlangan hayotiy tsikl mexanizmlari quyidagi tartibda chaqiriladi:

  1. @PostConstruct bilan annotatsiyalangan metodlar

  2. afterPropertiesSet(), InitializingBean qayta chaqiruv interfeysi tomonidan belgilanganidek

  3. Maxsus konfigurlangan init() metodi

Yo'q qilish metodlari ham xuddi shu tartibda chaqiriladi:

  1. @PreDestroy bilan annotatsiyalangan metodlar

  2. destroy(), DisposableBean qayta chaqiruv interfeysi tomonidan belgilanganidek

  3. Maxsus konfigurlangan destroy() metodi

Ishga tushirish va tugatish qayta chaqiruvlari

Lifecycle interfeysi, o'zining hayotiy tsikli talablariga (masalan, fon jarayonini boshlash va to'xtatish) ega bo'lgan har qanday obyekt uchun asosiy metodlarni aniqlaydi:

public interface Lifecycle {
    void start();
    void stop();
    boolean isRunning();
}

Spring tomonidan boshqariladigan har qanday obyekt Lifecycle interfeysini amalga oshirishi mumkin. Keyin, ApplicationContext o'zi boshlash va to'xtatish signallarini olganida (masalan, bajarish vaqtida to'xtatib qayta ishga tushirish), u bu chaqiriqlarni ushbu kontekstda aniqlangan barcha Lifecycle implemantatsiyalariga kaskad qiladi. Bu, quyidagi ro'yxatda ko'rsatilgan LifecycleProcessor orqali delegatsiya orqali amalga oshiriladi:

public interface LifecycleProcessor extends Lifecycle {
    void onRefresh();
    void onClose();
}

LifecycleProcessor o'zi Lifecycle interfeysining kengaytmasi ekanligini e'tiborga oling. U shuningdek, kontekstni yangilash va yopilishi bilan reaksiya qilish uchun ikkita boshqa metod qo'shadi.

Shuni yodda tutingki, org.springframework.context.Lifecycle tanish interfeysi boshlash va to'xtatishni bildiruvchi umumiy shartnoma hisoblanadi va avtomatik ishga tushirishni kontekstni yangilashda anglatmaydi. Maxsus binning avtomatik ishga tushirilishini boshqarish uchun (bosqichlarni boshlashni o'z ichiga oladi), org.springframework.context.SmartLifecycle dan foydalanishni ko'rib chiqaring.

Shuni ham e'tiborga olingki, to'xtatish to'g'risida ogohlantirish, yo'q qilishdan oldin kelishi kafolatlanmagan. Oddiy to'xtatish holatida barcha Lifecycle binlar to'xtatish to'g'risida ogohlantirish olinadi, oldin umumiy yo'q qilish qayta chaqiruvlari tarqatiladi. Ammo agar issiq tiklash vaqtida (yoki foydalanishdagi kontekstni yangilash holatida yoki to'xtatilgan yangilash urinishlari bo'lsa) faqat yo'q qilish metodlari chaqiriladi.

Ishga tushirish va tugatish chaqiruvlarining tartibi muhim rol o'ynashi mumkin. Agar har qanday ikkita obyekt o'rtasida "depends-on" turidagi munosabat bo'lsa, u holda qaram tomon o'z bog'liqligidan keyin ishlaydi va o'z bog'liqligidan oldin to'xtaydi. Ammo ba'zida to'g'ridan-to'g'ri bog'liqlar noma'lum bo'ladi. Faqat ma'lum bir turdagi obyektlar boshqa turdagi obyektlardan oldin boshlanishi kerakligini bilishingiz mumkin. Ushbu holatlarda, SmartLifecycle interfeysi, o'zining nafaqat bo'lgan Phased interfeysida belgilangan getPhase() metodi orqali farqli bir variantni aniqlaydi. Quyidagi ro'yxatda Phased interfeysining aniqlangan ma'nosi ko'rsatilgan:

public interface Phased {
    int getPhase();
}

Quyidagi ro'yxatda SmartLifecycle interfeysining aniqlangan ma'nosi ko'rsatilgan:

public interface SmartLifecycle extends Lifecycle, Phased {
    boolean isAutoStartup();
    void stop(Runnable callback);
}

Ishga tushirishda, eng kichik fazaga ega obyektlar avval boshlanadi. To'xtashda esa aksincha bajariladi. Shuning uchun, SmartLifecycle ni amalga oshiradigan va getPhase() metodi Integer.MIN_VALUE qaytadigan obyektlardan biri, eng birinchi ishga tushiriladi va oxirgi to'xtatiladi. Spektrning boshqa tomonidan, Integer.MAX_VALUE faza qiymati, obyektni eng oxirida ishlashni boshlashi va birinchi o'z to'xtatilishini belgilaydi, ehtimol boshqa ishlayotgan jarayonlarga bog'liqligi sababli. Faza qiymati ko'rib chiqilganda, shuningdek, SmartLifecycle ni amalga oshirmaydigan har qanday "oddiy" Lifecycle obyektning standart fazasi 0 ga teng ekanligini bilish muhimdir. Shu sababli, har qanday manfiy faza qiymati ushbu standart komponentlar oldidan ishlashni boshlashni bildiradi (va ulardan keyin to'xtashni). Karizmatik holatda, har qanday ijobiy faza qiymati ham aksingdir.

To'xtatish metodi, SmartLifecycle da aniqlangan, callback qabul qiladi. Har qanday amalga oshiruv bu amalga kelishish jarayoni tugaganidan so'ng ushbu callback’ni ishlashga boshlashi kerak. Bu asinxron to'xtatishni, agar talab qilinsa, ta'minlaydi, chunki LifecycleProcessor interfeysining amaldagi amalga oshirilishi, DefaultLifecycleProcessor, har bir fazada bu callback’ni ishlashni boshlashga yangi qabul qilingan vaqtning to'xtatish fazasida kutadi. Odatda har bir faza uchun kutish vaqti 30 soniyadir. Siz lifecycleProcessor nomi bilan ta'riflangan beanni kontekstdan ta'riflab, odatiy vaqtni o'zgartirishingiz mumkin. Agar faqat kutish vaqtini o'zgartirishni xohlasangiz, quyidagicha ta'rifni ko'rsatishingiz kifoya:

<bean id="lifecycleProcessor" class="org.springframework.context.support.DefaultLifecycleProcessor">
    <!-- kutish vaqtining qiymati millisekundlarda -->
    <property name="timeoutPerShutdownPhase" value="10000"/>
</bean>

Yuqorida aytilganidek, LifecycleProcessor interfeysi kontekstni yangilash va yopilish haqidagi qayta chaqiruvlarini aniqlaydi. Bular, agar u stop() metodini aniq chaqirgan holda tugatish jarayonini boshqarsa-da, kontekst yopilganida amalga oshiriladi. Refresh qayta chaqiruv esa SmartLifecycle binnar uchun yana bir o'ziga xos xususiyatni taklif etadi. Agar kontekst yangilansa (barcha obyektlar nusxalari yaratilgan va dasturlashtirilganidan so'ng), ushbu qayta chaqiruv amalga oshiriladi. Bu nuqtada, amaldagi hayotiy tsikl protsessor har bir SmartLifecycle obyektining isAutoStartup() metodi tomonidan qaytarilayotgan bulian (mantiqiy) qiymatini tekshiradi. Agar true bo'lsa, bu obyekt bu nuqtada ishga tushadi, va o'zining start() metodini aniq chaqirishni kutmasdan (kontekstni yangilashdan farqli o'laroq, boshlash konteksti kontekstning amaldagi amalga oshirilishida avtomatik ravishda sodir bo'lmaydi). Faza qiymati va har qanday "depends-on" munosabatlar ishlash tartibini belgilaydi.

Spring IoC-konteynerining naqshinkor to'xtatilishi web-bo'lmagan dasturlarda

Ushbu bo'lim faqat web-bo'lmagan dasturlar uchun mo'ljallangan. Spring frameworkdagi web-dasturlar uchun ApplicationContext amalga oshirilishlari mos web-dastur tugagandan so'ng Spring IoC-konteynerining naqshinkor to'xtatilishini boshqarishga ega.

Agar siz Spring IoC-konteyneridan web-dasturlardan boshqa muhitlarda (masalan, to'liq funksional mijozli dasturiy muhitda) foydalansangiz, Java Virtual Machine (JVM) bilan tugatish mexanizmini ro'yxatga oling. Shu tarzda, sizning singleton binlarda har qanday resurslarni bo'shatish uchun tegishli yo'q qilish metodlarini chaqirish va to'g'ri to'xtatishni ta'minlashingiz mumkin. Siz baribir ushbu yo'q qilish qayta chaqiruvlarini to'g'ri sozlashingiz va amalga oshirishingiz kerak.

Tugatish mexanizmini ro'yxatga olish uchun, quyidagi misolda ko'rsatilganidek, ConfigurableApplicationContext interfeysida e'lon qilingan registerShutdownHook() metodini chaqiring:

Java
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public final class Boot {
    public static void main(final String[] args) throws Exception {
        ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
        // yuqoridagi kontekst uchun tugatish mexanizmini qo'shamiz...
        ctx.registerShutdownHook();
        // ilova ishga tushmoqda...
        // asosiy metod tugaydi, mexanizm ilova tugashidan oldin chaqiriladi...
    }
}
Kotlin
import org.springframework.context.support.ClassPathXmlApplicationContext
fun main() {
    val ctx = ClassPathXmlApplicationContext("beans.xml")
    // yuqoridagi kontekst uchun tugatish mexanizmini qo'shamiz...
    ctx.registerShutdownHook()
    // ilova ishga tushmoqda...
    // asosiy metod tugaydi, mexanizm ilova tugashidan oldin chaqiriladi...
}
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION