JavaRush /وبلاگ جاوا /Random-FA /یک سفر کوتاه به تزریق وابستگی یا "CDI دیگر چیست؟"
Viacheslav
مرحله

یک سفر کوتاه به تزریق وابستگی یا "CDI دیگر چیست؟"

در گروه منتشر شد
پایه ای که امروزه محبوب ترین فریم ورک ها بر روی آن ساخته شده اند، تزریق وابستگی است. پیشنهاد می کنم ببینید مشخصات CDI در این مورد چه می گوید، چه قابلیت های اساسی داریم و چگونه می توانیم از آنها استفاده کنیم.
گشت کوتاهی در تزریق وابستگی یا

معرفی

من می خواهم این بررسی کوتاه را به چیزی به عنوان CDI اختصاص دهم. این چیه؟ CDI مخفف Contexts and Dependency Injection است. این یک مشخصات Java EE است که Dependency Injection و زمینه ها را توصیف می کند. برای اطلاعات، می توانید به وب سایت http://cdi-spec.org مراجعه کنید . از آنجایی که CDI یک مشخصات است (توضیح نحوه عملکرد آن، مجموعه ای از رابط ها)، برای استفاده از آن به پیاده سازی نیز نیاز داریم. یکی از این پیاده سازی ها Weld - http://weld.cdi-spec.org/ برای مدیریت وابستگی ها و ایجاد یک پروژه، از Maven استفاده می کنیم - https://maven.apache.org بنابراین، ما Maven را نصب کرده ایم، اکنون ما آن را در عمل درک خواهد کرد تا انتزاع را درک نکنیم. برای این کار با استفاده از Maven یک پروژه ایجاد می کنیم. بیایید خط فرمان را باز کنیم (در ویندوز می توانید از Win+R برای باز کردن پنجره Run و اجرای cmd استفاده کنید) و از Maven بخواهیم که همه کارها را برای ما انجام دهد. برای این، Maven مفهومی به نام کهن الگو دارد: Maven Archetype .
گشت کوتاهی در تزریق وابستگی یا
پس از آن، در سؤالات « انتخاب یک عدد یا اعمال فیلتر » و « انتخاب org.apache.maven.archetypes:maven-archetype-quickstart version » کافی است Enter را فشار دهید. سپس، شناسه‌های پروژه، به اصطلاح GAV را وارد کنید (به راهنمای کنوانسیون نام‌گذاری مراجعه کنید ).
گشت کوتاهی در تزریق وابستگی یا
پس از ایجاد موفقیت آمیز پروژه، کتیبه "ساخت موفقیت" را مشاهده خواهیم کرد. اکنون می توانیم پروژه خود را در IDE مورد علاقه خود باز کنیم.

افزودن CDI به پروژه

در مقدمه دیدیم که CDI وب سایت جالبی دارد - http://www.cdi-spec.org/ . یک بخش دانلود وجود دارد که حاوی جدولی است که حاوی داده های مورد نیاز ما است:
گشت کوتاهی در تزریق وابستگی یا
در اینجا می‌توانیم ببینیم که Maven چگونه این واقعیت را توصیف می‌کند که ما از CDI API در پروژه استفاده می‌کنیم. API یک رابط برنامه نویسی کاربردی است، یعنی یک رابط برنامه نویسی. ما با رابط کار می کنیم بدون اینکه نگران این باشیم که پشت این رابط چه کاری و چگونه کار می کند. API یک آرشیو jar است که ما شروع به استفاده از آن در پروژه خود خواهیم کرد، یعنی پروژه ما شروع به وابستگی به این jar می کند. بنابراین، CDI API برای پروژه ما یک وابستگی است. در Maven، یک پروژه در فایل های POM.xml ( POM - Project Object Model ) توضیح داده می شود. وابستگی ها در بلوک وابستگی ها توضیح داده شده اند که باید یک ورودی جدید به آن اضافه کنیم:
<dependency>
	<groupId>javax.enterprise</groupId>
	<artifactId>cdi-api</artifactId>
	<version>2.0</version>
</dependency>
همانطور که ممکن است متوجه شده باشید، ما محدوده را با مقدار ارائه شده مشخص نمی کنیم. چرا اینقدر تفاوت وجود دارد؟ این محدوده به این معنی است که شخصی وابستگی را برای ما فراهم می کند. هنگامی که یک برنامه کاربردی بر روی یک سرور Java EE اجرا می شود، به این معنی است که سرور تمام فناوری های ضروری JEE را در اختیار برنامه قرار می دهد. برای سادگی این بررسی، ما در یک محیط Java SE کار خواهیم کرد، بنابراین هیچ کس این وابستگی را برای ما فراهم نخواهد کرد. در اینجا می توانید اطلاعات بیشتری در مورد دامنه وابستگی بخوانید: " دامنه وابستگی ". خوب، ما اکنون توانایی کار با رابط ها را داریم. اما ما به اجرا هم نیاز داریم. همانطور که به یاد داریم، از Weld استفاده خواهیم کرد. جالب است که همه جا وابستگی های مختلفی داده می شود. اما ما مستندات را دنبال می کنیم. بنابراین، بیایید " 18.4.5. Setting the Classpath " را بخوانید و همانطور که می گوید انجام دهید:
<dependency>
	<groupId>org.jboss.weld.se</groupId>
	<artifactId>weld-se-core</artifactId>
	<version>3.0.5.Final</version>
</dependency>
مهم است که نسخه های خط سوم Weld از CDI 2.0 پشتیبانی کنند. بنابراین می توانیم روی API این نسخه حساب کنیم. اکنون آماده نوشتن کد هستیم.
گشت کوتاهی در تزریق وابستگی یا

راه اندازی یک کانتینر CDI

CDI یک مکانیسم است. یک نفر باید این مکانیسم را کنترل کند. همانطور که قبلاً در بالا خواندیم، چنین مدیری یک ظرف است. بنابراین، باید آن را ایجاد کنیم؛ خود آن در محیط SE ظاهر نخواهد شد. بیایید موارد زیر را به روش اصلی خود اضافه کنیم:
public static void main(String[] args) {
	SeContainerInitializer initializer = SeContainerInitializer.newInstance();
	initializer.addPackages(App.class.getPackage());
	SeContainer container = initializer.initialize();
}
ما ظرف CDI را به صورت دستی ایجاد کردیم زیرا... ما در یک محیط SE کار می کنیم. در پروژه های رزمی معمولی، کد بر روی یک سرور اجرا می شود که فناوری های مختلفی را در اختیار کد قرار می دهد. بر این اساس، اگر سرور CDI ارائه دهد، به این معنی است که سرور از قبل دارای یک کانتینر CDI است و ما نیازی به اضافه کردن چیزی نخواهیم داشت. اما برای اهداف این آموزش، ما از محیط SE استفاده می کنیم. علاوه بر این، ظرف اینجاست، به وضوح و قابل درک. چرا به ظرف نیاز داریم؟ ظرف داخل حاوی لوبیا (CDI beans) است.
گشت کوتاهی در تزریق وابستگی یا

لوبیا CDI

بنابراین، لوبیا. سطل CDI چیست؟ این یک کلاس جاوا است که از قوانینی پیروی می کند. این قوانین در مشخصات، در فصل " 2.2. لوبیا چه نوع کلاس هایی هستند؟ " توضیح داده شده است. بیایید یک CDI bean را به همان بسته کلاس App اضافه کنیم:
public class Logger {
    public void print(String message) {
        System.out.println(message);
    }
}
اکنون می‌توانیم این bean را از mainروش خود فراخوانی کنیم:
Logger logger = container.select(Logger.class).get();
logger.print("Hello, World!");
همانطور که می بینید، ما bean را با استفاده از کلمه کلیدی جدید ایجاد نکردیم. ما از کانتینر CDI پرسیدیم: "CDI container. من واقعاً به یک نمونه از کلاس Logger نیاز دارم، لطفاً آن را به من بدهید." این روش " جستجوی وابستگی " نامیده می شود، یعنی جستجوی وابستگی ها. حالا بیایید یک کلاس جدید ایجاد کنیم:
public class DateSource {
    public String getDate() {
        return new Date().toString();
    }
}
یک کلاس ابتدایی که یک نمایش متنی از تاریخ را برمی گرداند. اکنون خروجی تاریخ را به پیام اضافه می کنیم:
public class Logger {
    @Inject
    private DateSource dateSource;

    public void print(String message) {
        System.out.println(dateSource.getDate() + " : " + message);
    }
}
یک حاشیه نویسی جالب @Inject ظاهر شده است. همانطور که در فصل " 4.1. نقاط تزریق " مستندات جوش cdi بیان شد، با استفاده از این حاشیه، نقطه تزریق را تعریف می کنیم. در روسی، این را می توان به عنوان "نقاط اجرایی" خواند. آنها توسط ظرف CDI برای تزریق وابستگی هنگام نمونه برداری از لوبیا استفاده می شوند. همانطور که می بینید، ما هیچ مقداری را به فیلد dateSource اختصاص نمی دهیم. دلیل این امر این واقعیت است که ظرف CDI به داخل دانه های CDI (فقط آن دانه هایی که خودش نمونه سازی کرده است، یعنی مدیریت می کند) اجازه می دهد تا از " تزریق وابستگی " استفاده کنند. این روش دیگری از وارونگی کنترل است ، رویکردی که در آن وابستگی توسط شخص دیگری کنترل می‌شود نه اینکه ما به صراحت اشیا را ایجاد کنیم. تزریق وابستگی را می توان از طریق یک متد، سازنده یا فیلد انجام داد. برای جزئیات بیشتر، به فصل مشخصات CDI " 5.5. تزریق وابستگی " مراجعه کنید. رویه تعیین آنچه باید اجرا شود، تفکیک امنیتی نوع نامیده می شود، که باید در مورد آن صحبت کنیم.
گشت کوتاهی در تزریق وابستگی یا

وضوح نام یا وضوح Typesafe

به طور معمول، یک رابط به عنوان نوع شی مورد استفاده قرار می گیرد، و ظرف CDI خود تعیین می کند که کدام پیاده سازی را انتخاب کند. این به دلایل زیادی مفید است که در مورد آنها صحبت خواهیم کرد. بنابراین ما یک رابط لاگر داریم:
public interface Logger {
    void print(String message);
}
میگه اگه یه لاگر داشته باشیم می تونیم بهش پیغام بدیم و کارش رو انجام میده - log. چگونه و کجا در این مورد مورد توجه نخواهد بود. بیایید اکنون یک پیاده سازی برای لاگر ایجاد کنیم:
public class SystemOutLogger implements Logger {
    @Inject
    private DateSource dateSource;

    public void print(String message) {
        System.out.println(message);
    }
}
همانطور که می بینید، این یک لاگر است که در System.out می نویسد. فوق العاده است. اکنون، روش اصلی ما مانند قبل کار خواهد کرد. Logger logger = container.select(Logger.class).get(); این خط همچنان توسط لاگر دریافت خواهد شد. و زیبایی این است که ما فقط باید رابط کاربری را بدانیم، و ظرف CDI از قبل در مورد پیاده سازی برای ما فکر می کند. بیایید بگوییم پیاده سازی دومی داریم که باید گزارش را در جایی به یک ذخیره سازی راه دور ارسال کند:
public class NetworkLogger implements Logger {
    @Override
    public void print(String message) {
        System.out.println("Send log message to remote log system");
    }
}
اگر اکنون کد خود را بدون تغییر اجرا کنیم، با خطا مواجه خواهیم شد، زیرا ظرف CDI دو پیاده سازی از رابط را می بیند و نمی تواند بین آنها یکی را انتخاب کند: org.jboss.weld.exceptions.AmbiguousResolutionException: WELD-001335: Ambiguous dependencies for type Logger چه باید کرد؟ چندین تنوع موجود است. ساده ترین آنها حاشیه نویسی @Vetoed برای یک دانه CDI است تا ظرف CDI این کلاس را به عنوان یک دانه CDI درک نکند. اما روش بسیار جالب تری وجود دارد. یک دانه CDI را می توان به عنوان یک "جایگزین" با استفاده از حاشیه نویسی @Alternativeشرح داده شده در فصل " 4.7. Alternatives " مستندات Weld CDI علامت گذاری کرد. چه مفهومی داره؟ این بدان معناست که تا زمانی که به صراحت بگوییم از آن استفاده نکنید، انتخاب نخواهد شد. این یک نسخه جایگزین از لوبیا است. بیایید Bean NetworkLogger را به عنوان @Alternative علامت گذاری کنیم و می بینیم که کد دوباره اجرا شده و توسط SystemOutLogger استفاده می شود. برای فعال کردن گزینه جایگزین، باید یک فایل beans.xml داشته باشیم . ممکن است این سوال پیش بیاید: " beans.xml، شما را کجا قرار دهم؟ " بنابراین، بیایید فایل را به درستی قرار دهیم:
گشت کوتاهی در تزریق وابستگی یا
به محض اینکه ما این فایل را داشته باشیم، آرتیفکت با کد ما “ Archive Explicit bean ” نامیده می شود. اکنون 2 پیکربندی جداگانه داریم: نرم افزار و xml. مشکل این است که آنها همان داده ها را بارگذاری می کنند. به عنوان مثال، تعریف Bean DataSource 2 بار بارگذاری می شود و برنامه ما هنگام اجرا از کار می افتد، زیرا ظرف CDI آنها را به عنوان 2 لوبیا جداگانه در نظر می گیرد (اگرچه در واقع آنها یک کلاس هستند که ظرف CDI حدود دو بار آن را آموخته است). برای جلوگیری از این 2 گزینه وجود دارد:
  • خط را حذف کنید initializer.addPackages(App.class.getPackage())و نشانی از جایگزین به فایل xml اضافه کنید:
<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>
  • یک ویژگی bean-discovery-modeبا مقدار " none " به عنصر ریشه beans اضافه کنید و یک جایگزین را به صورت برنامه ریزی شده مشخص کنید:
initializer.addPackages(App.class.getPackage());
initializer.selectAlternatives(NetworkLogger.class);
بنابراین، با استفاده از جایگزین CDI، ظرف می تواند تعیین کند که کدام دانه را انتخاب کند. جالب توجه است، اگر ظرف CDI چندین جایگزین برای یک رابط می‌شناسد، می‌توانیم آن را با نشان دادن اولویت با استفاده از یک حاشیه‌نویسی @Priority(Since CDI 1.1) تشخیص دهیم.
گشت کوتاهی در تزریق وابستگی یا

مقدماتی

به طور جداگانه، ارزش بحث در مورد چیزی به عنوان واجد شرایط را دارد. واجد شرایط با یک حاشیه نویسی در بالای لوبیا نشان داده می شود و جستجوی لوبیا را بهبود می بخشد. و اکنون جزئیات بیشتر. جالب است که هر دانه CDI در هر صورت حداقل یک واجد شرایط دارد - @Any. اگر هیچ یک از واجد شرایط را در بالای bean مشخص نکنیم، اما خود ظرف CDI @Anyیک واجد شرایط دیگر را به واجد شرایط اضافه می کند - @Default. اگر چیزی را مشخص کنیم (مثلاً به صراحت @Any را مشخص کنیم)، آنگاه واجد شرایط @Default به طور خودکار اضافه نخواهد شد. اما زیبایی مسابقات مقدماتی این است که شما می توانید مسابقات مقدماتی خود را بسازید. واجد شرایط تقریباً هیچ تفاوتی با حاشیه نویسی ندارد، زیرا در اصل، این فقط یک حاشیه نویسی است که به روشی خاص نوشته شده است. به عنوان مثال، می توانید Enum را برای نوع پروتکل وارد کنید:
public enum ProtocolType {
    HTTP, HTTPS
}
در مرحله بعد می توانیم یک واجد شرایط ایجاد کنیم که این نوع را در نظر بگیرد:
@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface Protocol {
    ProtocolType value();
    @Nonbinding String comment() default "";
}
شایان ذکر است که فیلدهایی که به عنوان علامت گذاری شده اند @Nonbindingتأثیری در تعیین واجد شرایط ندارند. حالا شما باید واجد شرایط را مشخص کنید. در بالای نوع bean (به طوری که CDI بداند چگونه آن را تعریف کند) و بالاتر از نقطه تزریق (با حاشیه نویسی Inject@ نشان داده شده است تا متوجه شوید که کدام دانه را برای تزریق در این مکان باید جستجو کنید). به عنوان مثال، ما می توانیم یک کلاس با یک qualifier اضافه کنیم. برای سادگی، برای این مقاله آنها را در NetworkLogger انجام خواهیم داد:
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");
	}
}
و سپس وقتی Inject را انجام می‌دهیم، یک واجد شرایط را تعیین می‌کنیم که بر روی کلاس استفاده‌شده تأثیر می‌گذارد:
@Inject
@Protocol(ProtocolType.HTTPS)
private Sender sender;
عالی است، اینطور نیست؟) زیبا به نظر می رسد، اما معلوم نیست چرا. حالا موارد زیر را تصور کنید:
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);
به این ترتیب می توانیم مقدار دریافتی را نادیده بگیریم تا بتوان آن را به صورت پویا محاسبه کرد. به عنوان مثال، می توان آن را از برخی تنظیمات برداشت. سپس می‌توانیم پیاده‌سازی را حتی در حال پرواز، بدون کامپایل یا راه‌اندازی مجدد برنامه/سرور، تغییر دهیم. خیلی جالب تر می شود، اینطور نیست؟ )
گشت کوتاهی در تزریق وابستگی یا

تهیه کنندگان

یکی دیگر از ویژگی های مفید CDI تولیدکنندگان است. اینها روش‌های خاصی هستند (با یک حاشیه‌نویسی خاص مشخص می‌شوند) که زمانی فراخوانی می‌شوند که مقداری bean درخواست تزریق وابستگی کرده باشد. جزئیات بیشتر در مستندات، در بخش " 2.2.3. روش های تولید کننده " توضیح داده شده است. ساده ترین مثال:
@Produces
public Integer getRandomNumber() {
	return new Random().nextInt(100);
}
حال هنگام تزریق به فیلدهای نوع Integer این متد فراخوانی شده و مقداری از آن به دست می آید. در اینجا باید فوراً درک کنیم که وقتی کلمه کلیدی new را می بینیم، باید فوراً بفهمیم که این یک لوبیا CDI نیست. یعنی یک نمونه از کلاس Random فقط به این دلیل که از چیزی که ظرف CDI را کنترل می کند (در این مورد، سازنده) مشتق شده است، به یک دانه CDI تبدیل نمی شود.
گشت کوتاهی در تزریق وابستگی یا

رهگیرها

رهگیرها رهگیرهایی هستند که در کار "تداخل" می کنند. در CDI این کار کاملاً واضح انجام می شود. بیایید ببینیم چگونه می‌توانیم با استفاده از مفسرها (یا رهگیرها) ورود به سیستم را انجام دهیم. ابتدا باید اتصال به رهگیر را شرح دهیم. مانند بسیاری از موارد، این کار با استفاده از حاشیه نویسی انجام می شود:
@Inherited
@InterceptorBinding
@Target({TYPE, METHOD})
@Retention(RUNTIME)
public @interface ConsoleLog {
}
نکته اصلی در اینجا این است که این یک اتصال برای رهگیر ( @InterceptorBinding) است که توسط extends ( ) به ارث می رسد @InterceptorBinding. حالا بیایید خود رهگیر را بنویسیم:
@Interceptor
@ConsoleLog
public class LogInterceptor {
    @AroundInvoke
    public Object log(InvocationContext ic) throws Exception {
        System.out.println("Invocation method: " + ic.getMethod().getName());
        return ic.proceed();
    }
}
شما می توانید در مورد نحوه نوشتن رهگیرها در مثال از مشخصات بیشتر بخوانید: " 1.3.6. مثال رهگیر ". خوب، تنها کاری که باید انجام دهیم این است که اینرسپتور را روشن کنیم. برای انجام این کار، حاشیه نویسی الزام آور را در بالای متد در حال اجرا مشخص کنید:
@ConsoleLog
public void print(String message) {
و حالا یک جزئیات بسیار مهم دیگر. رهگیرها به طور پیش‌فرض غیرفعال هستند و باید مانند گزینه‌های جایگزین فعال شوند. به عنوان مثال، در فایل beans.xml :
<interceptors>
	<class>ru.javarush.LogInterceptor</class>
</interceptors>
همانطور که می بینید، بسیار ساده است.
گشت کوتاهی در تزریق وابستگی یا

رویداد و ناظران

CDI همچنین مدلی از رویدادها و ناظران را ارائه می دهد. در اینجا همه چیز به اندازه رهگیرها واضح نیست. بنابراین، رویداد در این مورد می تواند مطلقاً هر کلاسی باشد؛ هیچ چیز خاصی برای توضیحات لازم نیست. مثلا:
public class LogEvent {
    Date date = new Date();
    public String getDate() {
        return date.toString();
    }
}
حالا کسی باید منتظر رویداد باشد:
public class LogEventListener {
    public void logEvent(@Observes LogEvent event){
        System.out.println("Message Date: " + event.getDate());
    }
}
نکته اصلی در اینجا تعیین حاشیه نویسی @Observes است که نشان می دهد این فقط یک متد نیست، بلکه متدی است که باید در نتیجه مشاهده رویدادهایی از نوع LogEvent فراخوانی شود. خوب، اکنون به کسی نیاز داریم که تماشا کند:
public class LogObserver {
    @Inject
    private Event<LogEvent> event;
    public void observe(LogEvent logEvent) {
        event.fire(logEvent);
    }
}
ما یک متد واحد داریم که به ظرف می گوید که یک رویداد برای نوع رویداد LogEvent رخ داده است. اکنون تنها چیزی که باقی می ماند استفاده از ناظر است. به عنوان مثال، در NetworkLogger می توانیم یک تزریق از مشاهده گر خود اضافه کنیم:
@Inject
private LogObserver observer;
و در روش چاپ می توانیم به مشاهده کننده اطلاع دهیم که یک رویداد جدید داریم:
public void print(String message) {
	observer.observe(new LogEvent());
مهم است بدانید که رویدادها را می توان در یک رشته یا در چندین موضوع پردازش کرد. برای پردازش ناهمزمان، از یک روش .fireAsync(به‌جای .fire) و یک حاشیه‌نویسی @ObservesAsync(به‌جای @Observes) استفاده کنید. به عنوان مثال، اگر همه رویدادها در رشته های مختلف اجرا شوند، اگر 1 رشته یک Exception را پرتاب کند، بقیه می توانند کار خود را برای رویدادهای دیگر انجام دهند. می‌توانید طبق معمول، در بخش مشخصات، در بخش " 10. رویدادها " درباره رویدادها در CDI اطلاعات بیشتری کسب کنید.
گشت کوتاهی در تزریق وابستگی یا

دکوراتورها

همانطور که در بالا دیدیم، الگوهای طراحی مختلف در زیر بال CDI جمع آوری شده است. و در اینجا یکی دیگر - یک دکوراتور. این یک چیز بسیار جالب است. بیایید نگاهی به این کلاس بیندازیم:
@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);
    }
}
با اعلام آن به عنوان دکوراتور، می گوییم که وقتی از هر پیاده سازی Logger استفاده می شود، از این "افزونه" استفاده می شود که اجرای واقعی را می داند که در قسمت delegate ذخیره می شود (از آنجایی که با حاشیه نویسی مشخص شده است @Delegate). دکوراتورها را فقط می توان با یک لوبیا CDI مرتبط کرد که خود نه رهگیر و نه تزئین کننده است. یک مثال نیز در مشخصات قابل مشاهده است: " 1.3.7. Decorator example ". دکوراتور نیز مانند رهگیر باید روشن باشد. به عنوان مثال، در beans.xml :
<decorators>
	<class>ru.javarush.LoggerDecorator</class>
</decorators>
برای جزئیات بیشتر، به مرجع جوش مراجعه کنید: " فصل 10. دکوراتورها ".

چرخه زندگی

لوبیا چرخه زندگی خود را دارد. چیزی شبیه این به نظر می رسد:
گشت کوتاهی در تزریق وابستگی یا
همانطور که در تصویر می بینید، ما اصطلاحاً callbacks چرخه حیات داریم. اینها حاشیه نویسی هایی هستند که به ظرف CDI می گویند که روش های خاصی را در مرحله خاصی از چرخه حیات bean فراخوانی کند. مثلا:
@PostConstruct
public void init() {
	System.out.println("Inited");
}
این روش زمانی فراخوانی می شود که یک دانه CDI توسط یک ظرف نمونه سازی شود. همین امر در مورد @PreDestroy زمانی اتفاق می‌افتد که لوبیا زمانی که دیگر مورد نیاز نیست از بین می‌رود. بی جهت نیست که مخفف CDI حاوی حرف C - Context است. لوبیاها در CDI متنی هستند، به این معنی که چرخه زندگی آنها بستگی به زمینه ای دارد که در داخل ظرف CDI وجود دارد. برای درک بهتر این موضوع، باید بخش مشخصات « 7. چرخه حیات نمونه‌های متنی » را بخوانید. همچنین ارزش این را دارد که بدانید خود کانتینر یک چرخه حیات دارد که می توانید در مورد " رویدادهای چرخه حیات کانتینر " بخوانید.
گشت کوتاهی در تزریق وابستگی یا

جمع

در بالا به نوک کوه یخ به نام CDI نگاه کردیم. CDI بخشی از مشخصات JEE است و در محیط JavaEE استفاده می شود. کسانی که از Spring استفاده می کنند از CDI استفاده نمی کنند بلکه از DI استفاده می کنند، یعنی اینها مشخصات کمی متفاوت است. اما با دانستن و درک موارد فوق به راحتی می توانید نظر خود را تغییر دهید. با توجه به اینکه Spring از حاشیه نویسی های دنیای CDI (همان Inject) پشتیبانی می کند. مواد اضافی: #ویاچسلاو
نظرات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION