آموزش مفهوم Dependency Injection در Spring
هر برنامه ای که بر پایه جاوا طراحی شده ، شامل تعدادی شی ( objet ) است که با همکاری و ارتباط با یکدیگر خروجی نرم افزار را تولید نموده و به کاربر نشان میدهند .
هنگامی که یک برنامه سطح بالا جاوا را طراحی می کنید ، بایستی کلاس های برنامه تا حدامکان از همدیگر جدا بوده و مستقل عمل کنند . این قابلیت باعث می شود تا امکان استفاده مجدد از کلاس ها در سطح برنامه راحت تر شده و همچنین در فرآیند تست (Unit testing ) کار ساده تری داشته باشیم .
Dependecy Injection که گاهی اوقات Wiring هم نامیده میشود ، به ما کمک میکند تا کلاس ها را به هم مرتبط کرده و در عین حال کاری میکند تا آنها مستقل از هم عمل کنند .
برای مثال فرض کنید برنامه ای دارید که دارای یک ویرایشگر متن بوده و می خواهید قابلیت بررسی املاء ( Spell Checking ) را نیز به آن اضافه کنید .
کد استاندارد برای انجام این کار به صورت زیر است :
public class TextEditor {
private SpellChecker spellChecker;
public TextEditor() {
spellChecker = new SpellChecker();
}
}
کاری که ما اینجا انجام می دهیم ، این است که یک Dependecy یا اتصال بین TextEditor و SpellChecker ایجاد میکنیم . اما در یک سناریو Inversion of Control یا IOC ، کاری که انجام می شود به صورت زیر است :
public class TextEditor {
private SpellChecker spellChecker;
public TextEditor(SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
}
در اینجا TextEditor نبایستی نگران اجرا شدن SpellChecker باشد . Spellchecker به صورت مستقل پیاده سازی شده و در هنگام اجرای اولیه TextEditor به آن ارجاع می شود . تمامی این فرآیند توسط چهارچوب کاری Spring کنترل می شود .
در مثال فوق ، به طور کامل کنترل را از دست TextEditor خارج کرده و آن را در جایی دیگر ( برای مثال فایل پیکربندی Configuration ) قرار داده ایم . از طرف دیگر Dependency ( برای مثال کلاس SpellChecker ) با استفاده از سازنده کلاس ( Class Constructor )S
به درون کلاس TextEditor تزریق شده است . بنابراین جریان اجرای کدها توسط Dependency Injection به طور کامل معکوس شده است ، زیرا شما همه وابستگی های برنامه را به یک سیستم خارجی منتقل کرده اید .
روش دوم جهت تزریق Dependency استفاده از متدهای Setter Methods کلاس TextEditor است که در آن ما نسخه ای از شی SpellChecker را می سازیم . این نسخه از شی SpellChecker باعث فراخوانی متدهای Setter شده و خواص TextEditor را مقداردهی خواهد
کرد .
بنابراین ، DI به دو روش کلی قابل پیاده سازی است که در جدول زیر به بررسی هردو روش می پردازیم :
تزریق برپایه سازنده ( Counstructor-based dependency )
Constructor-based DI زمانی انجام میشود که Container یک سازنده کلاس ( Class Constructor ) را با تعدادی آرگومان فراخوانی می کند . هرکدام از این آرگومان ها ، نماینده یک dependcy در کلاس دیگر می باشد .
تزریق برپایه متدهای Setter یا ( Setter-based dependcy injection ) :
Stter-based DI زمانی انجام می شود که Container متدهای Stter Methods را پس از فراخوانی یک سازنده بدون آرگومان ( no-argument constructor) یا یک تابع بدون آرگومان ، جهت مقدار دهی اولیه bean برنامه ، اجرا می کند .
شما در یک برنامه Spring می توانید از هردو روش فوق باهم استفاده کنید . اما بهتر است از آرگومان های Constructor_based برای dependency های اختیاری استفاده کنید .
با استفاده از اصول DI کدهای تمیزتری خواهیم داشت و همچنین جداسازی کدها در زمانی که اشیا با dependency های آنها تعیین شده اند ، راحت تر خواهد بود .
در این روش برنامه نویسی ، اشیاء به وابستگی های خود dependency)ها (نگاه نکرده و نمی دانند کلاس یا وابستگی های خودشان کجا هستند . همه چیز توسط چهارچوب کاری Spring کنترل خواهد شد .