JavaRush /جاوا بلاگ /Random-UR /انحصار انجیکشن میں ایک مختصر سیر یا "CDI اور کیا ہے؟"
Viacheslav
سطح

انحصار انجیکشن میں ایک مختصر سیر یا "CDI اور کیا ہے؟"

گروپ میں شائع ہوا۔
وہ بنیاد جس پر اب سب سے زیادہ مشہور فریم ورک بنائے گئے ہیں وہ ہے انحصار انجیکشن۔ میں یہ دیکھنے کی تجویز کرتا ہوں کہ CDI تفصیلات اس بارے میں کیا کہتی ہیں، ہمارے پاس کون سی بنیادی صلاحیتیں ہیں اور ہم انہیں کیسے استعمال کر سکتے ہیں۔
انحصار انجکشن یا میں ایک مختصر سیر

تعارف

میں اس مختصر جائزے کو CDI جیسی چیز کے لیے وقف کرنا چاہوں گا۔ یہ کیا ہے؟ سی ڈی آئی کا مطلب سیاق و سباق اور انحصار انجیکشن ہے۔ یہ جاوا EE تصریح ہے جو انحصار انجیکشن اور سیاق و سباق کو بیان کرتی ہے۔ معلومات کے لیے، آپ ویب سائٹ http://cdi-spec.org کو دیکھ سکتے ہیں ۔ چونکہ CDI ایک تصریح ہے (اس کی وضاحت کہ اسے کیسے کام کرنا چاہیے، انٹرفیس کا ایک سیٹ)، ہمیں اسے استعمال کرنے کے لیے عمل درآمد کی بھی ضرورت ہوگی۔ اس طرح کے نفاذ میں سے ایک ویلڈ ہے - http://weld.cdi-spec.org/ انحصار کو منظم کرنے اور ایک پروجیکٹ بنانے کے لیے، ہم Maven کا استعمال کریں گے - https://maven.apache.org لہذا، ہم نے Maven انسٹال کر لیا ہے، اب ہم اسے عملی طور پر سمجھیں گے، تاکہ خلاصہ کو نہ سمجھ سکیں۔ ایسا کرنے کے لیے، ہم Maven کا استعمال کرتے ہوئے ایک پروجیکٹ بنائیں گے۔ آئیے کمانڈ لائن کھولیں (ونڈوز میں، آپ "رن" ونڈو کو کھولنے اور cmd کو چلانے کے لیے Win+R استعمال کر سکتے ہیں) اور Maven سے ہمارے لیے سب کچھ کرنے کو کہیں۔ اس کے لیے Maven کا ایک تصور ہے جسے آرکیٹائپ کہتے ہیں: Maven Archetype ۔
انحصار انجکشن یا میں ایک مختصر سیر
اس کے بعد، سوالوں پر " ایک نمبر کا انتخاب کریں یا فلٹر لگائیں " اور " org.apache.maven.archetypes:maven-archetype-quickstart version " کا انتخاب کریں بس Enter دبائیں۔ اس کے بعد، پروجیکٹ کے شناخت کنندگان، نام نہاد GAV درج کریں (دیکھیں نام سازی کنونشن گائیڈ
انحصار انجکشن یا میں ایک مختصر سیر
پروجیکٹ کی کامیاب تخلیق کے بعد، ہم تحریر دیکھیں گے "کامیابی کی تعمیر"۔ اب ہم اپنے پسندیدہ IDE میں اپنا پروجیکٹ کھول سکتے ہیں۔

سی ڈی آئی کو پروجیکٹ میں شامل کرنا

تعارف میں، ہم نے دیکھا کہ CDI کی ایک دلچسپ ویب سائٹ ہے - http://www.cdi-spec.org/ ۔ ایک ڈاؤن لوڈ سیکشن ہے، جس میں ایک ٹیبل ہے جس میں ہمیں مطلوبہ ڈیٹا موجود ہے:
انحصار انجکشن یا میں ایک مختصر سیر
یہاں ہم دیکھ سکتے ہیں کہ Maven اس حقیقت کو کس طرح بیان کرتا ہے کہ ہم پروجیکٹ میں CDI API استعمال کرتے ہیں۔ API ایک ایپلیکیشن پروگرامنگ انٹرفیس ہے، یعنی کچھ پروگرامنگ انٹرفیس۔ ہم انٹرفیس کے ساتھ اس بات کی فکر کیے بغیر کام کرتے ہیں کہ یہ اس انٹرفیس کے پیچھے کیا اور کیسے کام کرتا ہے۔ API ایک جار آرکائیو ہے جسے ہم اپنے پروجیکٹ میں استعمال کرنا شروع کر دیں گے، یعنی ہمارا پروجیکٹ اس جار پر انحصار کرنا شروع کر دیتا ہے۔ لہذا، ہمارے پروجیکٹ کے لیے CDI API ایک انحصار ہے۔ Maven میں، ایک پروجیکٹ کو POM.xml فائلوں ( POM - Project Object Model ) میں بیان کیا گیا ہے ۔ انحصارات کو انحصار بلاک میں بیان کیا گیا ہے، جس میں ہمیں ایک نیا اندراج شامل کرنے کی ضرورت ہے:
<dependency>
	<groupId>javax.enterprise</groupId>
	<artifactId>cdi-api</artifactId>
	<version>2.0</version>
</dependency>
جیسا کہ آپ نے دیکھا ہوگا، ہم فراہم کردہ قدر کے ساتھ دائرہ کار کی وضاحت نہیں کرتے ہیں۔ اتنا فرق کیوں ہے؟ اس دائرہ کار کا مطلب ہے کہ کوئی ہمیں انحصار فراہم کرے گا۔ جب کوئی ایپلیکیشن جاوا EE سرور پر چلتا ہے، تو اس کا مطلب ہے کہ سرور ایپلیکیشن کو تمام ضروری JEE ٹیکنالوجیز فراہم کرے گا۔ اس جائزے کی سادگی کی خاطر، ہم جاوا SE ماحول میں کام کریں گے، اس لیے کوئی بھی ہمیں یہ انحصار فراہم نہیں کرے گا۔ آپ انحصاری دائرہ کار کے بارے میں مزید یہاں پڑھ سکتے ہیں: " انحصاری دائرہ کار "۔ ٹھیک ہے، اب ہمارے پاس انٹرفیس کے ساتھ کام کرنے کی صلاحیت ہے۔ لیکن ہمیں عمل درآمد کی بھی ضرورت ہے۔ جیسا کہ ہمیں یاد ہے، ہم ویلڈ استعمال کریں گے۔ یہ دلچسپ ہے کہ ہر جگہ مختلف انحصار دیا جاتا ہے۔ لیکن ہم دستاویزات کی پیروی کریں گے۔ لہذا، آئیے " 18.4.5. کلاس پاتھ سیٹ کرنا " پڑھیں اور جیسا کہ یہ کہتا ہے ویسا کریں:
<dependency>
	<groupId>org.jboss.weld.se</groupId>
	<artifactId>weld-se-core</artifactId>
	<version>3.0.5.Final</version>
</dependency>
یہ ضروری ہے کہ ویلڈ کے تھرڈ لائن ورژن CDI 2.0 کو سپورٹ کرتے ہیں۔ لہذا، ہم اس ورژن کے API پر اعتماد کر سکتے ہیں۔ اب ہم کوڈ لکھنے کے لیے تیار ہیں۔
انحصار انجکشن یا میں ایک مختصر سیر

سی ڈی آئی کنٹینر شروع کرنا

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 پھلیاں) ہوتی ہیں۔
انحصار انجکشن یا میں ایک مختصر سیر

سی ڈی آئی پھلیاں

تو، پھلیاں. سی ڈی آئی بن کیا ہے؟ یہ جاوا کلاس ہے جو کچھ اصولوں پر عمل کرتی ہے۔ ان اصولوں کو تصریح میں، باب " 2.2 میں بیان کیا گیا ہے۔ کس قسم کی کلاسیں پھلیاں ہیں؟ "۔ آئیے اسی پیکج میں سی ڈی آئی بین شامل کریں جس طرح ایپ کلاس ہے:
public class Logger {
    public void print(String message) {
        System.out.println(message);
    }
}
اب ہم اس بین کو اپنے طریقے سے کہہ سکتے ہیں main:
Logger logger = container.select(Logger.class).get();
logger.print("Hello, World!");
جیسا کہ آپ دیکھ سکتے ہیں، ہم نے نئے مطلوبہ الفاظ کا استعمال کرتے ہوئے بین نہیں بنایا۔ ہم نے CDI کنٹینر سے پوچھا: "CDI کنٹینر۔ مجھے واقعی Logger کلاس کی ایک مثال درکار ہے، براہ کرم مجھے دیں۔" اس طریقہ کو " Dependency lookup " کہا جاتا ہے، یعنی انحصار کی تلاش۔ اب ایک نئی کلاس بنائیں:
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 کنٹینر کے ذریعے انحصار کو انجیکشن لگانے کے لیے کیا جاتا ہے جب پھلیاں انسٹیٹیوٹ کرتے ہیں۔ جیسا کہ آپ دیکھ سکتے ہیں، ہم ڈیٹ سورس فیلڈ کو کوئی قدر تفویض نہیں کر رہے ہیں۔ اس کی وجہ یہ حقیقت ہے کہ سی ڈی آئی کنٹینر سی ڈی آئی بینز کے اندر (صرف وہ پھلیاں جو اس نے خود انسٹیٹیوٹ کی ہیں، یعنی جس کا انتظام کرتا ہے) کو " انحصار انجکشن " استعمال کرنے کی اجازت دیتا ہے۔ یہ Inversion of Control کا ایک اور طریقہ ہے ، ایک ایسا نقطہ نظر جہاں انحصار کو کسی اور کے ذریعے کنٹرول کیا جاتا ہے بجائے اس کے کہ ہم واضح طور پر اشیاء تخلیق کریں۔ انحصار انجکشن ایک طریقہ، کنسٹرکٹر، یا فیلڈ کے ذریعے کیا جا سکتا ہے. مزید تفصیلات کے لیے، CDI تفصیلات کا باب " 5.5. انحصار انجیکشن " دیکھیں۔ اس بات کا تعین کرنے کے طریقہ کار کو کیا لاگو کرنے کی ضرورت ہے ٹائپ سیف ریزولوشن کہلاتا ہے، جس کے بارے میں ہمیں بات کرنے کی ضرورت ہے۔
انحصار انجکشن یا میں ایک مختصر سیر

نام کی قرارداد یا Typesafe قرارداد

عام طور پر، ایک انٹرفیس کو لاگو کرنے کے لیے آبجیکٹ کی قسم کے طور پر استعمال کیا جاتا ہے، اور CDI کنٹینر خود اس بات کا تعین کرتا ہے کہ کون سا عمل منتخب کرنا ہے۔ یہ بہت سی وجوہات کے لیے مفید ہے، جس پر ہم بحث کریں گے۔ تو ہمارے پاس لاگر انٹرفیس ہے:
public interface Logger {
    void print(String message);
}
وہ کہتا ہے کہ اگر ہمارے پاس کوئی لاگر ہے تو ہم اسے پیغام بھیج سکتے ہیں اور وہ اپنا کام مکمل کر لے گا یعنی لاگ۔ اس معاملے میں کیسے اور کہاں دلچسپی نہیں ہوگی۔ آئیے اب لاگر کے لیے ایک نفاذ بنائیں:
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 کیا کرنا ہے؟ کئی مختلف حالتیں دستیاب ہیں۔ سب سے آسان ایک CDI بین کے لیے @Vetoed تشریح ہے تاکہ CDI کنٹینر اس کلاس کو CDI بین کے طور پر نہ سمجھے۔ لیکن ایک بہت زیادہ دلچسپ نقطہ نظر ہے. ویلڈ سی ڈی آئی دستاویزات کے " 4.7 متبادل@Alternative " باب میں بیان کردہ تشریح کا استعمال کرتے ہوئے CDI بین کو "متبادل" کے طور پر نشان زد کیا جا سکتا ہے ۔ اس کا کیا مطلب ہے؟ اس کا مطلب یہ ہے کہ جب تک ہم اسے استعمال کرنے کے لیے واضح طور پر نہیں کہتے، اسے منتخب نہیں کیا جائے گا۔ یہ بین کا متبادل ورژن ہے۔ آئیے نیٹ ورک لاگر بین کو @Alternative کے بطور نشان زد کریں اور ہم دیکھ سکتے ہیں کہ کوڈ کو دوبارہ عمل میں لایا گیا ہے اور SystemOutLogger کے ذریعہ استعمال کیا گیا ہے۔ متبادل کو فعال کرنے کے لیے، ہمارے پاس beans.xml فائل ہونی چاہیے ۔ سوال پیدا ہوسکتا ہے: " beans.xml، میں آپ کو کہاں رکھوں؟ " لہذا، آئیے فائل کو صحیح طریقے سے رکھیں:
انحصار انجکشن یا میں ایک مختصر سیر
جیسے ہی ہمارے پاس یہ فائل ہوگی، ہمارے کوڈ کے ساتھ آرٹفیکٹ کو " Explicit bean archive " کہا جائے گا۔ اب ہمارے پاس 2 الگ الگ کنفیگریشن ہیں: سافٹ ویئر اور ایکس ایم ایل۔ مسئلہ یہ ہے کہ وہ وہی ڈیٹا لوڈ کریں گے۔ مثال کے طور پر، ڈیٹا سورس بین ڈیفینیشن 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قدر " کوئی نہیں " کے ساتھ ایک وصف شامل کریں اور پروگرام کے لحاظ سے ایک متبادل کی وضاحت کریں:
initializer.addPackages(App.class.getPackage());
initializer.selectAlternatives(NetworkLogger.class);
اس طرح، CDI متبادل کا استعمال کرتے ہوئے، کنٹینر اس بات کا تعین کر سکتا ہے کہ کون سی بین کو منتخب کرنا ہے۔ دلچسپ بات یہ ہے کہ اگر سی ڈی آئی کنٹینر ایک ہی انٹرفیس کے کئی متبادل جانتا ہے، تو ہم اسے تشریح کا استعمال کرتے ہوئے ترجیح بتا کر بتا سکتے ہیں @Priority(چونکہ CDI 1.1)۔
انحصار انجکشن یا میں ایک مختصر سیر

کوالیفائرز

الگ سے، یہ کوالیفائر کے طور پر ایسی چیز پر بحث کرنے کے قابل ہے. کوالیفائر کو بین کے اوپر ایک تشریح سے ظاہر کیا جاتا ہے اور بین کی تلاش کو بہتر بناتا ہے۔ اور اب مزید تفصیلات۔ دلچسپ بات یہ ہے کہ کسی بھی صورت میں کسی بھی CDI بین میں کم از کم ایک کوالیفائر ہوتا ہے @Any۔ اگر ہم بین کے اوپر کسی کوالیفائر کی وضاحت نہیں کرتے ہیں، لیکن پھر 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کوالیفائر کے تعین کو متاثر نہیں کرتے ہیں۔ اب آپ کو کوالیفائر کی وضاحت کرنے کی ضرورت ہے۔ یہ بین کی قسم کے اوپر اشارہ کیا گیا ہے (تاکہ CDI جانتا ہو کہ اسے کیسے بیان کرنا ہے) اور انجیکشن پوائنٹ کے اوپر (@Inject تشریح کے ساتھ تاکہ آپ سمجھ سکیں کہ اس جگہ پر انجیکشن کے لیے کون سی بین تلاش کرنی ہے)۔ مثال کے طور پر، ہم کوالیفائر کے ساتھ کچھ کلاس شامل کر سکتے ہیں۔ سادگی کے لیے، اس مضمون کے لیے ہم انہیں 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
@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);
اس طرح ہم حاصل ہونے والی قدر کو اوور رائیڈ کر سکتے ہیں تاکہ اس کا متحرک طور پر حساب لگایا جا سکے۔ مثال کے طور پر، اسے کچھ ترتیبات سے لیا جا سکتا ہے۔ پھر ہم پروگرام/سرور کو دوبارہ کمپائل یا دوبارہ شروع کیے بغیر، پرواز پر بھی عمل درآمد کو تبدیل کر سکتے ہیں۔ یہ بہت زیادہ دلچسپ ہو جاتا ہے، ہے نا؟ )
انحصار انجکشن یا میں ایک مختصر سیر

پروڈیوسرز

سی ڈی آئی کی ایک اور کارآمد خصوصیت پروڈیوسر ہے۔ یہ خاص طریقے ہیں (ان پر ایک خاص تشریح کے ساتھ نشان لگا دیا گیا ہے) جنہیں اس وقت کہا جاتا ہے جب کچھ بین نے انحصار انجیکشن کی درخواست کی ہو۔ مزید تفصیلات دستاویزات میں، سیکشن " 2.2.3. پروڈیوسر کے طریقے " میں بیان کی گئی ہیں۔ سب سے آسان مثال:
@Produces
public Integer getRandomNumber() {
	return new Random().nextInt(100);
}
اب جب Integer قسم کی فیلڈز میں انجیکشن لگائیں گے تو اس طریقہ کو بلایا جائے گا اور اس سے ایک قدر حاصل کی جائے گی۔ یہاں ہمیں فوراً سمجھ لینا چاہیے کہ جب ہم کلیدی لفظ کو نیا دیکھتے ہیں، تو ہمیں فوراً سمجھ لینا چاہیے کہ یہ CDI بین نہیں ہے۔ یعنی، رینڈم کلاس کی مثال صرف اس وجہ سے سی ڈی آئی بین نہیں بنے گی کہ یہ کسی ایسی چیز سے اخذ کی گئی ہے جو سی ڈی آئی کنٹینر کو کنٹرول کرتی ہے (اس معاملے میں، پروڈیوسر)۔
انحصار انجکشن یا میں ایک مختصر سیر

انٹرسیپٹرز

انٹرسیپٹرز انٹرسیپٹرز ہیں جو کام میں "مداخلت" کرتے ہیں۔ CDI میں یہ بالکل واضح طور پر کیا جاتا ہے۔ آئیے دیکھتے ہیں کہ ہم ترجمانوں (یا انٹرسیپٹرز) کے ذریعے لاگنگ کیسے کر سکتے ہیں۔ سب سے پہلے، ہمیں انٹرسیپٹر کے پابند ہونے کی وضاحت کرنے کی ضرورت ہے۔ بہت سی چیزوں کی طرح، یہ تشریحات کا استعمال کرتے ہوئے کیا جاتا ہے:
@Inherited
@InterceptorBinding
@Target({TYPE, METHOD})
@Retention(RUNTIME)
public @interface ConsoleLog {
}
یہاں اہم بات یہ ہے کہ یہ انٹرسیپٹر ( ) کے لیے بائنڈنگ ہے ، جسے توسیع ( ) @InterceptorBindingسے وراثت میں ملے گا ۔ @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(. فائر کی بجائے) اور ایک تشریح @ObservesAsync(@Observes کی بجائے)۔ مثال کے طور پر، اگر تمام واقعات کو مختلف تھریڈز میں انجام دیا جاتا ہے، پھر اگر 1 تھریڈ ایک استثناء پھینکتا ہے، تو باقی دوسرے ایونٹس کے لیے اپنا کام کر سکیں گے۔ آپ CDI میں واقعات کے بارے میں مزید پڑھ سکتے ہیں، ہمیشہ کی طرح، تفصیلات میں، باب " 10. واقعات " میں۔
انحصار انجکشن یا میں ایک مختصر سیر

سجاوٹ کرنے والے

جیسا کہ ہم نے اوپر دیکھا، مختلف ڈیزائن پیٹرن 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);
    }
}
اسے ڈیکوریٹر قرار دے کر، ہم کہتے ہیں کہ جب کوئی لاگر نفاذ استعمال ہوتا ہے، تو یہ "ایڈ آن" استعمال کیا جائے گا، جو حقیقی نفاذ کو جانتا ہے، جو ڈیلیگیٹ فیلڈ میں محفوظ ہوتا ہے (چونکہ یہ تشریح کے ساتھ نشان زد ہوتا ہے @Delegate)۔ ڈیکوریٹر صرف سی ڈی آئی بین کے ساتھ منسلک ہو سکتے ہیں، جو خود نہ تو کوئی انٹرسیپٹر ہے اور نہ ہی ڈیکوریٹر۔ تصریح میں ایک مثال بھی دیکھی جا سکتی ہے: " 1.3.7. ڈیکوریٹر مثال "۔ ڈیکوریٹر، انٹرسیپٹر کی طرح، آن ہونا ضروری ہے۔ مثال کے طور پر، beans.xml میں :
<decorators>
	<class>ru.javarush.LoggerDecorator</class>
</decorators>
مزید تفصیلات کے لیے ویلڈ کا حوالہ دیکھیں: " باب 10۔ ڈیکوریٹر

دورانیہ حیات

پھلیاں کا اپنا لائف سائیکل ہے۔ یہ کچھ اس طرح لگتا ہے:
انحصار انجکشن یا میں ایک مختصر سیر
جیسا کہ آپ تصویر سے دیکھ سکتے ہیں، ہمارے پاس نام نہاد لائف سائیکل کال بیکس ہیں۔ یہ تشریحات ہیں جو سی ڈی آئی کنٹینر کو بین کے لائف سائیکل کے ایک خاص مرحلے پر کچھ طریقوں کو کال کرنے کے لیے بتائیں گی۔ مثال کے طور پر:
@PostConstruct
public void init() {
	System.out.println("Inited");
}
یہ طریقہ اس وقت بلایا جائے گا جب ایک کنٹینر کے ذریعے سی ڈی آئی بین کو انسٹیٹیوٹ کیا جائے گا۔ @PreDestroy کے ساتھ بھی ایسا ہی ہوگا جب بین کو تباہ کردیا جائے گا جب اس کی مزید ضرورت نہیں ہے۔ یہ کچھ بھی نہیں ہے کہ مخفف CDI میں حرف C - سیاق و سباق شامل ہے۔ سی ڈی آئی میں پھلیاں سیاق و سباق کے مطابق ہوتی ہیں، یعنی ان کی زندگی کا دور اس سیاق و سباق پر منحصر ہوتا ہے جس میں وہ سی ڈی آئی کنٹینر میں موجود ہیں۔ اس کو بہتر طور پر سمجھنے کے لیے، آپ کو تصریح سیکشن " 7. سیاق و سباق کا لائف سائیکل " پڑھنا چاہیے۔ یہ جاننا بھی ضروری ہے کہ کنٹینر کا خود ایک لائف سائیکل ہے، جس کے بارے میں آپ " کنٹینر لائف سائیکل ایونٹس " میں پڑھ سکتے ہیں۔
انحصار انجکشن یا میں ایک مختصر سیر

کل

اوپر ہم نے سی ڈی آئی نامی آئس برگ کے بالکل سرے کو دیکھا۔ CDI JEE تفصیلات کا حصہ ہے اور JavaEE ماحول میں استعمال ہوتا ہے۔ جو لوگ Spring استعمال کرتے ہیں وہ CDI استعمال نہیں کرتے، لیکن DI، یعنی یہ قدرے مختلف وضاحتیں ہیں۔ لیکن مندرجہ بالا کو جاننے اور سمجھنے سے، آپ آسانی سے اپنا خیال بدل سکتے ہیں۔ اس بات پر غور کرتے ہوئے کہ موسم بہار CDI دنیا (وہی انجیکشن) سے تشریحات کی حمایت کرتا ہے۔ اضافی مواد: #ویاچسلاو
تبصرے
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION