ظرف IoC – قسمت 1 از 3 – Spring MVC

در اسپرینگ به ظرف پایه ای IoC، کارخانه bean می گویند. هر کارخانه bean پیکربندی و ارتباط بین اشیاء را از طریق تزریق وابستگی ها و در شرایط سازگار و عملی ایجاد می کند. علاوه بر این، یک کارخانه bean با توجه به چرخه حیات اشیاء bean، تا حدی مدیریت این اشیاء را فراهم می کند. رویکرد IoC به خوبی اجازه جداسازی یک قطعه کد را از قطعه کدهای دیگر می دهد. علاوه بر این، در کنار استفاده از امکان reflection برای دسترسی به اشیاء، این تضمین وجود دارد که کد برنامه به آگاهی از حضور کارخانه bean نیاز نداشته و به طور کلی برای استفاده در اسپرینگ نیاز به تغییر در این کد نیست. به کمک این ظرف، می توان کدهای نرم افزاری ای که به پیکربندی اشیا نیاز داشته، و آن ها را به کمک روش هایی مثل یگانگی و یا روش های دیگر مانند اشیاء ویژه کارخانه به دست می آورد، می توانند به طور کامل حذف شده و یا به میزان قابل توجهی کاهش یابند.

نکته مهم: در یک برنامه مبتنی بر اسپرینگ، به طور معمول تنها برخی کدهای خاص به آگاهی از حضور ظرف اسپرینگ نیاز دارند و یا نیاز دارند از رابط ظرف اسپرینگ استفاده کنند. حتی در اغلب اوقات این کدها را نیز می توان با تکیه بر کد موجود چارچوب برای بارگذاری کارخانه bean در رویکرد اعلانی، حذف کرد.

کارخانه bean

کارخانه های bean با پیاده سازی های مختلفی به وجود آمده اند تا از سطوح عملیاتی تا حدودی متفاوت پشتیبانی کنند. این کارخانه ها در عمل بیشتر به روش پیکره بندی وابسته هستند. از جمله پیکره بندی های رایج می توان به پیکره بندی XML اشاره کرد. تمام کارخانه های bean، رابط org.springframework.beans.factory.BeanFactory را پیاده سازی می کنند. در صورت نیاز به مدیریت در رویکرد برنامه نویسی، می توان از این رابط استفاده کرد و به نمونه های ایجاد شده دسترسی داشت. در رابط های سطوح پایین تر BeanFactory قابلیت های بیشتر ایجاد شده اند. فهرستی از سلسله مراتب این رابط ها در زیر آمده است:

BeanFactory: رابط پایه ای که برای دسترسی به تمام اشیاء bean استفاده می شود. متد getBean(String name) امکان دسترسی با نام را به اشیاء bean موجود ظرف می دهد. getBean(String name, Class requiredType) شکل تغییر یافته این متد است که اجازه می دهد کلاس مورد نیاز شی bean بازگشتی را مشخص شود. در صورت عدم وجود این شی، یک استثنا ایجاد خواهد شد. متدهای دیگری نیز وجود دارند که برای پرس و جو و بررسی وجود یک bean با نام، یافتن نوع bean (با نام داده شده)، و دریافت نام های مستعار یک bean موجود در کارخانه استفاده می شوند (یک bean می تواند با نام های متعددی در کارخانه شناخته شود). همچنین با کمک این متدها شما می توانید یگانگی یک bean خاص را بررسی کنید؛ به این معنی که در صورتی که bean مورد نظر برای اولین بار درخواست شده باشد، یک نمونه از آن ایجاد و در درخواست های بعد مجددا از همان نمونه استفاده شود، و یا این که باید با هر بار درخواست، یک نمونه جدید از آن ایجاد شود.

HierarchicalBeanFactory: اکثر کارخانه های bean می توانند به عنوان بخشی از یک ساختاری سلسله مراتبی ایجاد شوند، به طوری که اگر شما از یک کارخانه برای یک bean خاص پرس و جو کنید و این bean در آن کارخانه وجود نداشته باشد، از کارخانه والد برای دریافت آن bean درخواست شود، و کارخانه والد نیز می تواند از کارخانه والد خود درخواست کند. تا آنجا که به مشتری مربوط می شود، کل سلسله مراتب کارخانه ها و از جمله خود کارخانه ی مورد استفاده، به صورت یک کارخانه ادغام شده در نظر گرفته می شود. یکی از دلایل استفاده از این مدل سلسله مراتبی، انطباق آن با لایه های معماری عملیاتی یا ماژول های درون یک برنامه است. در حالی که دریافت یک bean از یک کارخانه، که بخشی از یک سلسله مراتب است شفاف خواهد بود، با این وجود رابط HierarchicalBeanFactory برای این استفاده می شود که شما بتوانید به کمک آن به والد یک کارخانه دسترسی یابید.

ListableBeanFactory: متدهای درون این زیررابط BeanFactory، اجازه فهرست بندی و یا شمارش اشیاء bean درون یک کارخانه را می دهند. این فهرست می تواند شامل نام اشیاء bean و همچنین نام و تعداد یک نوع خاص bean در کارخانه باشد. علاوه بر این، متدهای متعددی وجود دارند که به شما اجازه دریافت یک Map حاوی تمام اشیاء bean مربوط به یک نوع خاص درون کارخانه را می دهند. دقت کنید که در حالی که متدهای رابط BeanFactory به طور خودکار در هر سلسله مراتبی که یک کارخانه بتواند بخشی از آن باشد قرار می گیرند، اما رابط ListableBeanFactory تنها بر روی یک کارخانه bean اعمال می شود. کلاس کمکی BeanFactoryUtils متدهای کاملا مشابه ListableBeanFactory را تهیه کرده است که در تمام سلسله مراتب کارخانه bean می توانند استفاده شوند. این متدها غالبا برای استفاده در کدهای برنامه مناسب هستند.

AutowireCapableBeanFactory: این رابط به شما اجازه می دهد تا به کمک متدهای ()autowireBeanProperties و ()applyBeanPropertyValues، کارخانه ای داشته باشید که بتواند یک شی موجود را خارج از کارخانه پیکره بندی کرده و وابستگی های آن را تهیه کند. به این ترتیب، این کارخانه از مرحله ساخت طبیعی آن شی، که بخشی از تهیه bean از طریق ()BeanFactory.getBean است گذر می کند. هنگام کار با کتابخانه هایی که در ایجاد نمونه از آن ها توسط خودشان صورت می گیرد، برای اسپرینگ گزینه ای برای ایجاد bean وجود نخواهد داشت، اما هنوز هم این امکان وجود دارد که تزریق وابستگی توسط اسپرینگ صورت پذیرد. متد ()autowire اجازه می دهد که با تعیین نام کلاس، کارخانه یک نمونه از آن کلاس را ساخته، به کمک reflection تمام وابستگی های آن کلاس را شناسایی کرده، آن وابستگی ها را به نمونه bean ساخته شده تزریق کرده و در نهایت این شی کاملا تنظیم شده را برگرداند. توجه داشته باشید که کارخانه، اشیاای را که توسط این متدها پیکربندی شده باشند، همانند نمونه های یگانه ای که به صورت عادی ساخته می شوند، نگه داری و مدیریت نخواهد کرد. اگر چه شما می توانید خودتان آن شی را به عنوان یک نمونه یگانه به کارخانه اضافه کنید.

ConfigurableBeanFactory: این رابط، امکانات پیکربندی بیشتری را ارائه می دهد که می توانند در مرحله مقداردهی اولیه اشیا bean پایه ای، بر روی آن ها اعمال شوند.

عموما اسپرینگ تلاش می کند تا از استثنائات چک نشده[۱] (زیرکلاس های RuntimeException) برای خطاهای پوشش داده نشده استفاده کند. رابط های کارخانه bean، از جمله BeanFactory و زیر رابط های آن، در این مورد هیچ تفاوتی با هم ندارند. در اغلب موارد، خطاهای پیکربندی غیرقابل بازگشت هستند و در نتیجه تمام استثناهایی که توسط این APIها ایجاد می شوند از کلاس استثنائات چک نشده BeansException مشتق می شوند. توسعه دهندگان می توانند زمان و مکانی که باید آن ها را کنترل کنند انتخاب کرده و حتی سعی کنند در صورت وجود یک استراتژی مناسب، این استثنائات را حل کنند.

بستر برنامه

اسپرینگ از یک کارخانه bean به نام بستر برنامه[۲] استفاده می کند که تا حدودی پیشرفته تر از سایر کارخانه های bean است.

نکته مهم: یک بستر برنامه، یک کارخانه bean با رابط کاربری org.springframework.context.ApplicationContext، زیرکلاسی از BeanFactory است.

به طور کلی، هر کاری که یک کارخانه bean بتواند انجام دهد، بستر برنامه نیز می تواند به خوبی انجام دهد. اما قابلیت های یک بستر برنامه و سبک های استفاده از آن بیشتر است:

سبک استفاده چارچوب عمومی-گرا[۳]: در بستر برنامه می توان عملیات خاص بر روی ظرف و یا اشیاء bean موجود در ظرف را، که باید در یک رویکرد برنامه نویسی شده توسط کارخانه bean کنترل شوند، به صورت اعلانی[۴]انجام داد. این عملیات شامل پساپردازنده[۵]های ویژه bean و کارخانه bean هستند، که در مورد آن ها در ادامه توضیح داده شده است. علاوه بر این، تعدادی از امکانات چارچوب اسپرینگ وجود دارند که به طور خودکار بسترهای برنامه را، برای مثال در لایه وب MVC، بارگذاری می کنند. بنابراین می توان نتیجه گرفت که کارخانه bean عمدتا توسط کد کاربر ایجاد می شود، در حالی که بسترهای برنامه توسط کد چارچوب ایجاد خواهند شد. همانطور که گفته شد بسترهای برنامه، بیشتر در حالت اعلانی استفاده می شوند. البته، در هر دو مورد، قسمت زیادی از کد کاربر توسط ظرف ایجاد شده مدیریت می شود، و این در حالی است که کد کاربر در مورد ظرف هیچ اطلاعی ندارد.

پشتیبانی از MessageSource: بستر برنامه، MessageSource را پیاده سازی کرده است. این رابط برای دریافت پیام های متمرکز[۶] تهیه شده و می توان پیاده سازی مورد نظر خود را برای آن تهیه کرد.

پشتیبانی از رویدادهای برنامه و چارچوب: این بستر قادر است رویدادهای چارچوب و یا برنامه را برای شنوندگان[۷] ثبت شده ارسال کند.

پشتیبانی از ResourceLoader: رابط Resource اسپرینگ یک انتزاع عمومی انعطاف پذیر برای کنترل منابع سطح پایین است. خود بستر برنامه یک ResourceLoader است و از این رو یک برنامه با دسترسی به نمونه های Resource با استقرار خاص را فراهم می کند.

نکته مهم: ممکن است دقیقا مشخص نباشد چه زمانی استفاده از یک کارخانه bean مناسب تر است و چه زمان باید از یک بستر برنامه استفاده کرد. تقریبا در همه موارد بهتر است از یک بستر برنامه استفاده کنید، چرا که بدون هیچ هزینه خاصی، به شما ویژگی های بیشتری را می دهد. از آن جایی که کارخانه bean در مصرف حافظه کمی صرفه جویی می کند، در صورتی که میزان مصرف حافظه اهمیت زیادی داشته باشد، بهتر است از این گزینه استفاده شود. مثلا در زمانی که از applet استفاده می کنیم هر بایت مورد استفاده در حافظه قابل توجه است. دلیل کم شدن میزان مصرف حافظه این است که شما تنها از بسته های کتابخانه اسپرینگی استفاده می کنید که قابلیت های کارخانه bean را بارگذاری می کنند و قابلیت های بستر برنامه را بارگذاری نمی شوند.

شروع به کار ظرف

مثال های قبل، روش های مختلف شروع به کار یک ظرف را توسط کد کاربر نشان داد. اجازه دهید به چند نمونه از این روش ها در اینجا اشاره کنیم.

ما می توانیم یک ApplicationContext را با اشاره به (فایل) منبع در classpath بارگذاری کنیم:

 

 

و یا به یک مکان در سیستم فایل اشاره کنیم:

 

 

ما همچنین می توانیم دو یا چند فایل XML را با هم ترکیب کنیم. این کار اجازه می دهد تا بتوانیم تعاریف bean را در ماژول های منطقا مجزایی قرار دهیم، اما همچنان با ترکیب آن ها یک بستر از تعاریف را داشته باشیم. در زیر یک نمونه XML که به دو قسمت تقسیم شده، نشان داده شده است:

 

 

 

نکته: خوانندگان دقیق توجه خواهند داشت که در مقایسه با مثال قبل، ما کمی روش اشاره به weatherDao را که به عنوان یک عضو داده ای bean سرویس آب و هوا استفاده می شود، تغییر داده ایم.

حال برای بارگذاری و ترکیب هر دو (یا چند) قسمت، کافی است لیست آن ها را وارد کنیم:

 

 

در رابط Resource اسپرینگ، این امکان وجود دارد که از پیشوند classpath* برای تعیین تمامی منابع منطبق با یک نام خاص و قابل مشاهده برای بارگذاری کننده کلاس و پدران آن استفاده شود. برای مثال فرض کنید برنامه کاربردی به چند فایل jar تقسیم شده باشد. در این صورت تمام این فایل ها از طریق classpath در دسترس خواهند بود و در هر jar فایلی با نام applicationContext.xml برای تعریف بستر برنامه آن فایل موجود است. در این شرایط دستور زیر بستری از تمامی مولفه ها ایجاد می کند:

 

 

ایجاد و بارگذاری یک کارخانه bean پیکربندی شده بر اساس XML نیز به همین سادگی است. ساده ترین مکانیسم این است که از رابط Resource اسپرینگ برای بارگذاری از منبع classpath استفاده شود:

 

 

یا

 

 

همچنین ما می توانیم از یک InputStream نیز استفاده کنیم:

 

 

قطعه کد زیر نشان می دهد که چگونه می توان به راحتی مرحله ایجاد کارخانه bean را از مرحله تعریف bean جدا کرد:

 

 

 

کلاس GenericApplicationContext مشابه همین جدا سازی بین ساخت و تجزیه تعریف ها را در بسترهای برنامه انجام می دهد. معمولا برنامه های کاربردی اسپرینگ درون کد خود به ایجاد ظرف اشاره نکرده و برای انجام این کار به کد چارچوب تکیه می کنند. برای مثال، شما می توانید به صورت اعلانی ContextLoader اسپرینگ را پیکربندی کنید تا به طور خودکار یک بستر برنامه را در راه اندازی یک برنامه وب بارگذاری کند.

استفاده از اشیاء bean موجود در کارخانه

هنگامی که کارخانه bean یا بستر برنامه بارگذاری شد، دسترسی به bean با رویکرد ابتدایی، به سادگی به کمک ()getBean رابط BeanFactory امکان پذیر است:

 

 

و یا متد های دیگر از رابط های پیشرفته تر:

 

 

درخواست یک bean از ظرف باعث ایجاد و مقدار دهی اولیه آن bean شده، و در نتیجه مرحله تزریق وابستگی را نیز، که قبلا در مورد آن صحبت شد شامل می شود. مرحله تزریق وابستگی می تواند باعث ایجاد اشیاء bean دیگری شود (وابستگی های bean اول)، و این روال ادامه یافته تا در نهایت به ایجاد گراف نمونه اشیاء مرتبط منتهی شود.

سوالی که این جا پیش می آید این است که باید با خود کارخانه bean و یا بستر برنامه چه کار کرد تا بتواند سایر کدهایی را که نیاز دارد، دریافت کند. در طول آشنایی با طریقه پیکربندی و روش کار ظرف، به این سوال پاسخ داده خواهد شد.

نکته مهم: به یاد داشته باشید که به جز بخش کمی از کد برنامه، تقریبا تمام کد برنامه ای که به سبک IoC نوشته شده است، نیازی به دسترسی به کارخانه ندارد، زیرا ظرف برنامه این اشیاء را به اشیاء دیگری که توسط همین ظرف مدیریت می شوند متصل خواهد کرد. در آن بخش از کد که نیاز است خودش این کار را انجام دهد، راه حل ابتدایی این است که کارخانه در یک محل شناخته شده و ترجیحا جایی قرار گیرد که برای بستر برنامه معنی دار باشد. اسپرینگ امکان بارگذاری اعلانی بستر برنامه را برای استفاده در برنامه وب فراهم کرده و آن را در ServletContext قرار می دهد.

پیکربندی bean با استفاده از XML

تاکنون چندین نمونه از فایل های حاوی فرمت XML را برای تعریف کارخانه bean بررسی کرده ایم، اما هنوز کاملا وارد جزئیات نشده ایم. تعریف یک کارخانه bean با عنصر سطح بالایی به نام beans شروع شده و در دل خود یک یا چند عنصر bean را شامل می شود:

 

 

عناصر معتبر و ویژگی مورد استفاده در فایل تعریف، به طور کامل توسط XML DTD[8] به نام spring-beans.dtd توضیح داده شده اند. این DTD، همراه با مرجع اسپرینگ، به عنوان منابع اطلاعات پیکربندی در نظر گرفته می شود. به طور کلی، ویژگی های اختیاری عنصر beans می تواند رفتار کل فایل پیکربندی را تحت تاثیر قرار داده و برخی از مقادیر پیش فرض را برای خصیصه های تعریف عناصر bean ارائه دهد، در حالی که (بیشتر) ویژگی های اختیاری و زیرعناصر مربوط به عناصر bean، تنها به توصیف پیکربندی و چرخه حیات آن bean می پردازند. این DTD به عنوان بخشی از توزیع اسپرینگ تعریف شده و شما می توانید آن را به صورت آنلاین در آدرس www.springframework.org/dtd/spring-beans.dtd مشاهده کنید.

[۱] Non-checked Exceptions

[۲] Application Context

[۳] General Framework-Oriented Usage Style

[۴] Declarative

[۵] Post-Processors

[۶] Localized

[۷] Listeners

[۸] Document Type Definition

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *