JavaRush /Java blogi /Random-UZ /Bog'liqlik in'ektsiyasiga qisqa ekskursiya yoki "CDI yana...
Viacheslav
Daraja

Bog'liqlik in'ektsiyasiga qisqa ekskursiya yoki "CDI yana nima?"

Guruhda nashr etilgan
Hozirda eng mashhur ramkalar qurilgan poydevor - bu qaramlik in'ektsiyasi. Men CDI spetsifikatsiyasida bu haqda nima deyilganini, qanday asosiy imkoniyatlarga ega ekanligimizni va ulardan qanday foydalanishimiz mumkinligini ko'rib chiqishni taklif qilaman.
Bog'liqlik in'ektsiyasiga qisqacha ekskursiya yoki

Kirish

Men ushbu qisqa sharhni CDI kabi narsaga bag'ishlamoqchiman. Nima bu? CDI qisqartmasi kontekstlar va qaramlik kiritishni anglatadi. Bu Dependency Injection va kontekstlarni tavsiflovchi Java EE spetsifikatsiyasi. Ma'lumot uchun http://cdi-spec.org veb-saytiga murojaat qilishingiz mumkin . CDI spetsifikatsiya bo'lgani uchun (u qanday ishlashi kerakligi tavsifi, interfeyslar to'plami), uni ishlatish uchun bizga dastur ham kerak bo'ladi. Bunday ilovalardan biri Weld - http://weld.cdi-spec.org/ Bog'liqlarni boshqarish va loyiha yaratish uchun biz Maven-dan foydalanamiz - https://maven.apache.org Shunday qilib, bizda Maven o'rnatildi, endi biz mavhumni tushunmaslik uchun uni amalda tushunadi. Buning uchun biz Maven yordamida loyiha yaratamiz. Buyruqlar qatorini ochamiz (Windows-da Win+R tugmalaridan foydalanib, “Ishga tushirish” oynasini ochishingiz va cmd-ni bajarishingiz mumkin) va Mavendan biz uchun hamma narsani qilishini so'rang. Buning uchun Mavenda arxetip deb ataladigan kontseptsiya mavjud: Maven arxetipi .
Bog'liqlik in'ektsiyasiga qisqacha ekskursiya yoki
Shundan so'ng, " Raqamni tanlang yoki filtrni qo'llang " va " org.apache.maven.archetypes:maven-archetype-quickstart versiyasini tanlang " savollariga shunchaki Enter tugmasini bosing. Keyinchalik, GAV deb ataladigan loyiha identifikatorlarini kiriting (Qarang: Nomlash konventsiyasi qo'llanmasi ).
Bog'liqlik in'ektsiyasiga qisqacha ekskursiya yoki
Loyihani muvaffaqiyatli yaratgandan so'ng, biz "MUVOFIQ QURISH" yozuvini ko'ramiz. Endi biz loyihamizni sevimli IDE-da ochishimiz mumkin.

Loyihaga CDI qo'shish

Kirish qismida biz CDI ning qiziqarli veb-sayti borligini ko'rdik - http://www.cdi-spec.org/ . Yuklab olish bo'limi mavjud bo'lib, unda bizga kerakli ma'lumotlarni o'z ichiga olgan jadval mavjud:
Bog'liqlik in'ektsiyasiga qisqacha ekskursiya yoki
Bu erda biz Maven loyihada CDI API-dan foydalanishimizni qanday tasvirlayotganini ko'rishimiz mumkin. API - bu amaliy dasturlash interfeysi, ya'ni ba'zi dasturlash interfeysi. Biz ushbu interfeys ortida nima va qanday ishlashi haqida o'ylamasdan interfeys bilan ishlaymiz. API - bu jar arxivi bo'lib, biz uni loyihamizda foydalanishni boshlaymiz, ya'ni loyihamiz ushbu jarga bog'liq bo'la boshlaydi. Shuning uchun, bizning loyihamiz uchun CDI API bog'liqlikdir. Maven'da loyiha POM.xml fayllarida tasvirlangan ( POM - Project Object Model ). Bog'liqliklar bog'liqliklar blokida tasvirlangan, unga yangi yozuv qo'shishimiz kerak:
<dependency>
	<groupId>javax.enterprise</groupId>
	<artifactId>cdi-api</artifactId>
	<version>2.0</version>
</dependency>
Siz sezgan bo'lishingiz mumkin, biz taqdim etilgan qiymat bilan qamrovni belgilamaymiz. Nima uchun bunday farq bor? Bu qamrov kimdir bizga qaramlikni ta'minlashini anglatadi. Agar dastur Java EE serverida ishlayotgan bo'lsa, bu server ilovani barcha kerakli JEE texnologiyalari bilan ta'minlashini bildiradi. Ushbu sharhning soddaligi uchun biz Java SE muhitida ishlaymiz, shuning uchun hech kim bizga bu qaramlikni ta'minlamaydi. Qaramlik doirasi haqida ko'proq ma'lumotni bu yerda o'qishingiz mumkin: " Bog'liqlik doirasi ". OK, endi biz interfeyslar bilan ishlash imkoniyatiga egamiz. Lekin biz ham amalga oshirishga muhtojmiz. Esda tutganimizdek, biz Weld-dan foydalanamiz. Qizig'i shundaki, hamma joyda turli xil bog'liqliklar berilgan. Lekin biz hujjatlarga amal qilamiz. Shuning uchun, keling, " 18.4.5. Sinf yo'lini o'rnatish "ni o'qib chiqamiz va unda aytilgandek bajaramiz:
<dependency>
	<groupId>org.jboss.weld.se</groupId>
	<artifactId>weld-se-core</artifactId>
	<version>3.0.5.Final</version>
</dependency>
Weld ning uchinchi qator versiyalari CDI 2.0 ni qo'llab-quvvatlashi muhim. Shuning uchun biz ushbu versiyaning API-ga ishonishimiz mumkin. Endi biz kod yozishga tayyormiz.
Bog'liqlik in'ektsiyasiga qisqacha ekskursiya yoki

CDI konteynerini ishga tushirish

CDI - bu mexanizm. Kimdir bu mexanizmni nazorat qilishi kerak. Yuqorida o'qiganimizdek, bunday menejer konteynerdir. Shuning uchun biz uni yaratishimiz kerak, uning o'zi SE muhitida ko'rinmaydi. Keling, asosiy usulimizga quyidagilarni qo'shamiz:
public static void main(String[] args) {
	SeContainerInitializer initializer = SeContainerInitializer.newInstance();
	initializer.addPackages(App.class.getPackage());
	SeContainer container = initializer.initialize();
}
Biz CDI konteynerini qo'lda yaratdik, chunki... Biz SE muhitida ishlaymiz. Oddiy jangovar loyihalarda kod serverda ishlaydi, bu kodga turli texnologiyalarni taqdim etadi. Shunga ko'ra, agar server CDI-ni taqdim etsa, bu serverda allaqachon CDI konteyneri borligini anglatadi va biz hech narsa qo'shishimiz shart emas. Ammo ushbu qo'llanmaning maqsadlari uchun biz SE muhitini olamiz. Bundan tashqari, konteyner bu erda, aniq va tushunarli. Nima uchun bizga konteyner kerak? Ichkaridagi idishda loviya (CDI loviya) mavjud.
Bog'liqlik in'ektsiyasiga qisqacha ekskursiya yoki

CDI loviya

Shunday qilib, loviya. CDI qutisi nima? Bu ba'zi qoidalarga amal qiladigan Java sinfidir. Ushbu qoidalar spetsifikatsiyada " 2.2. Fasol qanday sinflarga kiradi? " bobida tasvirlangan. Keling, ilova sinfi bilan bir xil paketga CDI loviya qo'shamiz:
public class Logger {
    public void print(String message) {
        System.out.println(message);
    }
}
Endi biz ushbu loviyani usulimizdan chaqirishimiz mumkin main:
Logger logger = container.select(Logger.class).get();
logger.print("Hello, World!");
Ko'rib turganingizdek, biz loviyani new kalit so'zidan foydalanib yaratmadik. Biz CDI konteyneridan so‘radik: "CDI konteyneri. Menga Logger sinfining namunasi kerak, iltimos, bering." Bu usul " Dependency search ", ya'ni bog'liqliklarni qidirish deb ataladi . Endi yangi sinf yaratamiz:
public class DateSource {
    public String getDate() {
        return new Date().toString();
    }
}
Sana matnli tasvirini qaytaradigan ibtidoiy sinf. Endi xabarga sana chiqishini qo'shamiz:
public class Logger {
    @Inject
    private DateSource dateSource;

    public void print(String message) {
        System.out.println(dateSource.getDate() + " : " + message);
    }
}
Qiziqarli @Inject izohi paydo bo'ldi. Cdi payvandlash hujjatlarining " 4.1. In'ektsiya nuqtalari " bo'limida aytilganidek , ushbu izohdan foydalanib, biz Injection nuqtasini aniqlaymiz. Rus tilida buni "amalga oshirish nuqtalari" deb o'qish mumkin. Ular CDI konteyneri tomonidan loviya yaratishda bog'liqliklarni kiritish uchun ishlatiladi. Ko'rib turganingizdek, biz dateSource maydoniga hech qanday qiymat bermayapmiz. Buning sababi shundaki, CDI konteyneri CDI loviyalari ichida (faqat o'zi yaratgan, ya'ni u boshqaradigan loviyalar) " Dependency Injection " dan foydalanishga imkon beradi. Bu Boshqaruvni Inversiyalashning yana bir usuli bo'lib , qaramlik biz ob'ektlarni aniq yaratganimizdan ko'ra boshqa birov tomonidan boshqariladi. Bog'liqlik kiritish usuli, konstruktor yoki maydon orqali amalga oshirilishi mumkin. Batafsil ma'lumot uchun CDI spetsifikatsiyasining " 5.5. Bog'liqlik in'ektsiyasi " bo'limiga qarang. Amalga oshirish kerak bo'lgan narsani aniqlash tartibi xavfsiz rezolyutsiya deb ataladi, biz bu haqda gapirishimiz kerak.
Bog'liqlik in'ektsiyasiga qisqacha ekskursiya yoki

Nom ruxsati yoki turdagi xavfsiz rezolyutsiya

Odatda interfeys amalga oshiriladigan ob'ekt turi sifatida ishlatiladi va CDI konteynerining o'zi qaysi dasturni tanlashni belgilaydi. Bu ko'p sabablarga ko'ra foydalidir, biz ularni muhokama qilamiz. Shunday qilib, bizda logger interfeysi mavjud:
public interface Logger {
    void print(String message);
}
Uning aytishicha, agar bizda logger bo'lsa, biz unga xabar yuborishimiz mumkin va u o'z vazifasini bajaradi - log. Bu holatda qanday va qayerda qiziqish bo'lmaydi. Endi logger uchun dastur yarataylik:
public class SystemOutLogger implements Logger {
    @Inject
    private DateSource dateSource;

    public void print(String message) {
        System.out.println(message);
    }
}
Ko'rib turganingizdek, bu System.out ga yozuvchi logger. Ajoyib. Endi bizning asosiy usulimiz avvalgidek ishlaydi. Logger logger = container.select(Logger.class).get(); Bu chiziq hali ham logger tomonidan qabul qilinadi. Va go'zalligi shundaki, biz faqat interfeysni bilishimiz kerak va CDI konteyneri biz uchun amalga oshirish haqida allaqachon o'ylaydi. Aytaylik, bizda jurnalni uzoq xotiraga yuborishi kerak bo'lgan ikkinchi dastur mavjud:
public class NetworkLogger implements Logger {
    @Override
    public void print(String message) {
        System.out.println("Send log message to remote log system");
    }
}
Agar biz kodimizni o'zgartirmasdan ishga tushirsak, xatoga yo'l qo'yamiz, chunki CDI konteyneri interfeysning ikkita ilovasini ko'radi va ular orasidan tanlay olmaydi: org.jboss.weld.exceptions.AmbiguousResolutionException: WELD-001335: Ambiguous dependencies for type Logger Nima qilish kerak? Bir nechta o'zgarishlar mavjud. Eng oddiyi CDI loviya uchun @Vetoed izohidir , shunda CDI konteyneri bu sinfni CDI loviya sifatida qabul qilmaydi. Ammo bundan ham qiziqroq yondashuv mavjud. CDI loviya Weld CDI hujjatlarining " 4.7. Alternativlar@Alternative " bo'limida tavsiflangan izoh yordamida "muqobil" sifatida belgilanishi mumkin . Bu nima degani? Bu shuni anglatadiki, agar biz undan foydalanishni aniq aytmasak, u tanlanmaydi. Bu fasolning muqobil versiyasidir. Keling, NetworkLogger loviyasini @Alternative deb belgilaymiz va kod yana bajarilganini va SystemOutLogger tomonidan ishlatilishini ko'rishimiz mumkin. Muqobilni yoqish uchun bizda beans.xml fayli bo'lishi kerak . Savol tug'ilishi mumkin: " beans.xml, men sizni qaerga qo'yaman? " Shunday qilib, faylni to'g'ri joylashtiramiz:
Bog'liqlik in'ektsiyasiga qisqacha ekskursiya yoki
Ushbu faylga ega bo'lishimiz bilan bizning kodimiz bo'lgan artefakt " Aniq fasol arxivi " deb nomlanadi. Endi bizda ikkita alohida konfiguratsiya mavjud: dasturiy ta'minot va xml. Muammo shundaki, ular bir xil ma'lumotlarni yuklaydi. Misol uchun, DataSource fasol ta'rifi 2 marta yuklanadi va dasturimiz bajarilganda ishlamay qoladi, chunki CDI konteyneri ularni ikkita alohida loviya deb hisoblaydi (garchi aslida ular CDI konteyneri ikki marta o'rgangan bir xil sinfdir). Buning oldini olish uchun ikkita variant mavjud:
  • qatorni olib tashlang initializer.addPackages(App.class.getPackage())va xml fayliga muqobil ko'rsatkichni qo'shing:
<beans
    xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://xmlns.jcp.org/xml/ns/javaee
        http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd">
    <alternatives>
        <class>ru.javarush.NetworkLogger</class>
    </alternatives>
</beans>
  • loviya ildiz elementiga " yo'qbean-discovery-mode " qiymatiga ega atribut qo'shing va dasturiy jihatdan muqobilni belgilang:
initializer.addPackages(App.class.getPackage());
initializer.selectAlternatives(NetworkLogger.class);
Shunday qilib, CDI muqobilidan foydalanib, konteyner qaysi loviya tanlashni aniqlay oladi. Qizig'i shundaki, agar CDI konteyneri bir xil interfeys uchun bir nechta alternativalarni bilsa, biz buni annotatsiya yordamida ustuvorlikni ko'rsatish orqali aytishimiz mumkin @Priority(CDI 1.1 dan beri).
Bog'liqlik in'ektsiyasiga qisqacha ekskursiya yoki

Saralash bosqichi

Alohida, saralash kabi narsalarni muhokama qilish kerak. Kvalifikatsiya loviya ustidagi izoh bilan ko'rsatiladi va loviya qidirishni aniqlaydi. Va endi batafsilroq. Qizig'i shundaki, har qanday CDI loviya har qanday holatda kamida bitta kvalifikatsiyaga ega - @Any. Agar biz loviya ustida HAR QANDAY sifatlovchini ko'rsatmasak, lekin u holda CDI konteynerining o'zi @Anykvalifikatsiyaga boshqa kvalifikatsiyani qo'shadi - @Default. Agar biror narsani belgilasak (masalan, @Any ni aniq belgilang), u holda @Default kvalifier avtomatik ravishda qo'shilmaydi. Ammo saralashning go'zalligi shundaki, siz o'zingizning saralashlaringizni qilishingiz mumkin. Saralovchi izohlardan deyarli farq qilmaydi, chunki mohiyatiga ko'ra, bu faqat maxsus tarzda yozilgan annotatsiya. Masalan, protokol turi uchun Enum ni kiritishingiz mumkin:
public enum ProtocolType {
    HTTP, HTTPS
}
Keyinchalik biz ushbu turni hisobga oladigan kvalifikatsiya qilishimiz mumkin:
@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface Protocol {
    ProtocolType value();
    @Nonbinding String comment() default "";
}
Shuni ta'kidlash kerakki, deb belgilangan maydonlar @Nonbindingkvalifikatsiyani aniqlashga ta'sir qilmaydi. Endi siz kvalifikatsiyani belgilashingiz kerak. U loviya turi ustida (CDI uni qanday aniqlashni bilishi uchun) va Inyeksiya nuqtasi ustida (@Inject izohi bilan) ko'rsatilgan, shunda siz bu joyda in'ektsiya uchun qaysi loviya izlash kerakligini tushunasiz. Misol uchun, biz kvalifikatsiya bilan ba'zi sinflarni qo'shishimiz mumkin. Oddiylik uchun ushbu maqola uchun biz ularni NetworkLogger ichida qilamiz:
public interface Sender {
	void send(byte[] data);
}

@Protocol(ProtocolType.HTTP)
public static class HTTPSender implements Sender{
	public void send(byte[] data) {
		System.out.println("sended via HTTP");
	}
}

@Protocol(ProtocolType.HTTPS)
public static class HTTPSSender implements Sender{
	public void send(byte[] data) {
		System.out.println("sended via HTTPS");
	}
}
Va keyin biz Inject-ni bajarganimizda, qaysi sinf ishlatilishiga ta'sir qiluvchi kvalifikatsiyani belgilaymiz:
@Inject
@Protocol(ProtocolType.HTTPS)
private Sender sender;
Ajoyib, shunday emasmi?) Chiroyli ko'rinadi, lekin nima uchun ekanligi noma'lum. Endi quyidagilarni tasavvur qiling:
Protocol protocol = new Protocol() {
	@Override
	public Class<? extends Annotation> annotationType() {
		return Protocol.class;
	}
	@Override
	public ProtocolType value() {
		String value = "HTTP";
		return ProtocolType.valueOf(value);
	}
};
container.select(NetworkLogger.Sender.class, protocol).get().send(null);
Shunday qilib, biz qiymatni dinamik ravishda hisoblash uchun uni bekor qilishimiz mumkin. Misol uchun, u ba'zi sozlamalardan olinishi mumkin. Keyin dasturni/serverni qayta kompilyatsiya qilmasdan yoki qayta ishga tushirmasdan, dasturni hatto tezda o'zgartirishimiz mumkin. Bu yanada qiziqarli bo'ladi, shunday emasmi? )
Bog'liqlik in'ektsiyasiga qisqacha ekskursiya yoki

Ishlab chiqaruvchilar

CDI ning yana bir foydali xususiyati ishlab chiqaruvchilardir. Bu ba'zi bir fasol qaramlik in'ektsiyasini talab qilganda chaqiriladigan maxsus usullar (ular maxsus izoh bilan belgilanadi). Batafsil ma'lumotlar hujjatlarning " 2.2.3. Ishlab chiqaruvchi usullari " bo'limida tasvirlangan. Eng oddiy misol:
@Produces
public Integer getRandomNumber() {
	return new Random().nextInt(100);
}
Endi Integer tipidagi maydonlarga inyeksiya qilinganda bu usul chaqiriladi va undan qiymat olinadi. Bu erda biz darhol yangi kalit so'zni ko'rganimizda, bu CDI loviya emasligini darhol tushunishimiz kerak. Ya'ni, Random sinfining namunasi faqat CDI konteynerini (bu holda, ishlab chiqaruvchi) boshqaradigan narsadan olinganligi sababli CDI loviyasiga aylanmaydi.
Bog'liqlik in'ektsiyasiga qisqacha ekskursiya yoki

Interceptors

Interceptors - bu ishga "aralashuvchi" tutqichlar. CDI-da bu juda aniq amalga oshiriladi. Keling, tarjimonlar (yoki to'xtatuvchilar) yordamida qanday qilib jurnalni yozishni ko'rib chiqaylik. Birinchidan, biz tutuvchiga bog'lanishni tasvirlashimiz kerak. Ko'p narsalar singari, bu izohlar yordamida amalga oshiriladi:
@Inherited
@InterceptorBinding
@Target({TYPE, METHOD})
@Retention(RUNTIME)
public @interface ConsoleLog {
}
@InterceptorBindingBu erda asosiy narsa shundaki, bu kengaytmalar ( ) tomonidan meros qilib olinadigan interceptor ( ) uchun majburiydir @InterceptorBinding. Endi tutuvchining o'zini yozamiz:
@Interceptor
@ConsoleLog
public class LogInterceptor {
    @AroundInvoke
    public Object log(InvocationContext ic) throws Exception {
        System.out.println("Invocation method: " + ic.getMethod().getName());
        return ic.proceed();
    }
}
Interceptorlar misolda qanday yozilishi haqida batafsilroq spetsifikatsiyadan o'qishingiz mumkin: " 1.3.6. Interceptor misoli ". Biz qilishimiz kerak bo'lgan narsa inerseptorni yoqishdir. Buni amalga oshirish uchun bajarilayotgan usul ustidagi majburiy izohni belgilang:
@ConsoleLog
public void print(String message) {
Va endi yana bir muhim tafsilot. Interceptors sukut bo'yicha o'chirilgan va muqobillar bilan bir xil tarzda yoqilishi kerak. Masalan, beans.xml faylida :
<interceptors>
	<class>ru.javarush.LogInterceptor</class>
</interceptors>
Ko'rib turganingizdek, bu juda oddiy.
Bog'liqlik in'ektsiyasiga qisqacha ekskursiya yoki

Hodisa va kuzatuvchilar

CDI shuningdek, hodisalar va kuzatuvchilar modelini taqdim etadi. Bu erda hamma narsa to'xtatuvchilarda bo'lgani kabi aniq emas. Shunday qilib, bu holda hodisa mutlaqo har qanday sinf bo'lishi mumkin; tavsif uchun maxsus hech narsa kerak emas. Masalan:
public class LogEvent {
    Date date = new Date();
    public String getDate() {
        return date.toString();
    }
}
Endi kimdir voqeani kutishi kerak:
public class LogEventListener {
    public void logEvent(@Observes LogEvent event){
        System.out.println("Message Date: " + event.getDate());
    }
}
Bu erda asosiy narsa @Observes izohini belgilashdir, bu shunchaki usul emas, balki LogEvent tipidagi hodisalarni kuzatish natijasida chaqirilishi kerak bo'lgan usul ekanligini ko'rsatadi. Xo'sh, endi bizga tomosha qiladigan odam kerak:
public class LogObserver {
    @Inject
    private Event<LogEvent> event;
    public void observe(LogEvent logEvent) {
        event.fire(logEvent);
    }
}
Bizda konteynerga LogEvent hodisasi uchun hodisa sodir bo'lganligini bildiradigan yagona usul mavjud. Endi faqat kuzatuvchidan foydalanish qoladi. Masalan, NetworkLogger-da biz kuzatuvchimizning in'ektsiyasini qo'shishimiz mumkin:
@Inject
private LogObserver observer;
Va chop etish usulida biz kuzatuvchiga yangi voqea borligi haqida xabar berishimiz mumkin:
public void print(String message) {
	observer.observe(new LogEvent());
Hodisalarni bir ipda yoki bir nechtada qayta ishlash mumkinligini bilish muhimdir. Asinxron ishlov berish uchun usul .fireAsync(.fire o'rniga) va izohdan @ObservesAsync(@Observes o'rniga) foydalaning. Misol uchun, agar barcha hodisalar turli xil oqimlarda bajarilgan bo'lsa, u holda 1 ip Istisnoni tashlasa, qolganlari boshqa hodisalar uchun o'z ishlarini bajarishlari mumkin bo'ladi. Odatdagidek, CDI-dagi voqealar haqida ko'proq spetsifikatsiyaning " 10. Voqealar " bo'limida o'qishingiz mumkin .
Bog'liqlik in'ektsiyasiga qisqacha ekskursiya yoki

Dekoratorlar

Yuqorida ko'rganimizdek, CDI qanoti ostida turli dizayn naqshlari to'plangan. Va yana biri - dekorativ. Bu juda qiziq narsa. Keling, ushbu sinfni ko'rib chiqaylik:
@Decorator
public abstract class LoggerDecorator implements Logger {
    public final static String ANSI_GREEN = "\u001B[32m";
    public static final String ANSI_RESET = "\u001B[0m";

    @Inject
    @Delegate
    private Logger delegate;

    @Override
    public void print(String message) {
        delegate.print(ANSI_GREEN + message + ANSI_RESET);
    }
}
Uni dekorativ deb e'lon qilish orqali biz aytamizki, har qanday Logger ilovasidan foydalanilganda, delegat maydonida saqlanadigan haqiqiy dasturni biladigan ushbu "qo'shimcha" ishlatiladi (chunki u izoh bilan belgilangan @Delegate). Dekoratorlar faqat CDI loviya bilan bog'lanishi mumkin, uning o'zi ham to'xtatuvchi ham, dekorativ ham emas. Misolni spetsifikatsiyada ham ko'rish mumkin: " 1.3.7. Dekorator misoli ". Dekorator, to'xtatuvchi kabi, yoqilgan bo'lishi kerak. Masalan, beans.xml da :
<decorators>
	<class>ru.javarush.LoggerDecorator</class>
</decorators>
Batafsil ma'lumot uchun payvand chokiga qarang: " 10-bob. Dekoratorlar ".

Hayot davrasi

Fasolning o'ziga xos hayot aylanishi bor. Bu shunday ko'rinadi:
Bog'liqlik in'ektsiyasiga qisqacha ekskursiya yoki
Rasmdan ko'rinib turibdiki, bizda hayot aylanish jarayoni deb ataladigan qo'ng'iroqlar mavjud. Bular CDI konteyneriga fasolning hayot aylanishining ma'lum bir bosqichida ma'lum usullarni chaqirishni aytadigan izohlardir. Masalan:
@PostConstruct
public void init() {
	System.out.println("Inited");
}
Bu usul CDI loviya konteyner tomonidan yaratilganda chaqiriladi. Fasol endi kerak bo'lmaganda yo'q qilinganda @PreDestroy bilan ham xuddi shunday bo'ladi. CDI qisqartmasida C harfi borligi bejiz emas - Kontekst. CDI-dagi fasol kontekstlidir, ya'ni ularning hayot aylanishi CDI konteynerida mavjud bo'lgan kontekstga bog'liq. Buni yaxshiroq tushunish uchun " 7. Kontekstli misollarning hayot aylanishi " spetsifikatsiya bo'limini o'qib chiqishingiz kerak . Bundan tashqari, konteynerning o'zi ham hayot aylanishiga ega ekanligini bilish kerak, bu haqda siz " Konteynerning hayot aylanishi voqealari " da o'qishingiz mumkin.
Bog'liqlik in'ektsiyasiga qisqacha ekskursiya yoki

Jami

Yuqorida biz CDI deb nomlangan aysbergning eng uchini ko'rib chiqdik. CDI JEE spetsifikatsiyasining bir qismidir va JavaEE muhitida qo'llaniladi. Bahordan foydalanadiganlar CDI dan foydalanmaydilar, lekin DI, ya'ni bu biroz boshqacha spetsifikatsiyalar. Ammo yuqoridagilarni bilib, tushunib, fikringizni osongina o'zgartirishingiz mumkin. Bahor CDI dunyosidan izohlarni qo'llab-quvvatlashini hisobga olsak (xuddi shu Inject). Qo'shimcha materiallar: #Viacheslav
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION