15. اسپرینگ IoC
15.1. Introduction
هدف ما بررسی گزینههای پیکربندی و یکپارچهسازی فریمورک Spring (http://www.springframework.org) و همچنین تعریف و استفاده از مفهوم IoC (معکوسسازی کنترل)، که با نام تزریق وابستگی نیز شناخته میشود، است.
بیایید نگاهی به برنامهٔ سهلایهای بیندازیم که همینالان ساختهایم:
![]() |
برای پاسخ به درخواستهای کاربر، کنترلکننده [Application] باید با لایه [service] ارتباط برقرار کند. در مثال ما، این یک نمونه از نوع [DaoImpl] بود. کنترلکننده [Application] در متد [init] خود (بخش 14.8.3) یک مرجع به لایه [service] را به دست آورد:
- خط ۶: لایه [dao] با ایجاد صریح یک نمونه از [DaoImpl] نمونه سازی شد
- خط ۹: لایه [service] با ایجاد صریح یک نمونه از [ServiceImpl] نمونه سازی شد
توجه داشته باشید که کلاسهای [DaoImpl] و [ServiceImpl] به ترتیب رابطهای [IDao] و [IService] را پیادهسازی میکنند. در نسخههای آینده، رابط [IDao] توسط کلاسی پیادهسازی خواهد شد که فهرستی از افراد را که در یک پایگاه داده ذخیره شدهاند، مدیریت میکند. برای این مثال، بیایید این کلاس را [DaoBD] بنامیم. جایگزینی پیادهسازی [DaoImpl] لایه [dao] با پیادهسازی [DaoBD] مستلزم کامپایل مجدد لایه [web] خواهد بود. این به این دلیل است که خط ۶ بالا، که لایه [dao] را با نوع [DaoImpl] نمونهسازی میکند، اکنون باید آن را با نوع [DaoBD] نمونهسازی کند. لایه [web] ما بنابراین به لایه [dao] وابسته است. خط ۹ بالا نشان میدهد که این لایه همچنین به لایه [service] وابسته است.
اسپرینگ IoC به ما امکان میدهد یک برنامه سهلایه ایجاد کنیم که در آن لایهها از یکدیگر مستقل هستند، c.a.d، به این معنی که تغییر یکی مستلزم تغییر دیگری نیست. این امر انعطافپذیری زیادی در تکامل برنامه فراهم میکند.
معماری قبلی به شرح زیر تکامل خواهد یافت:
![]() |
کنترلکننده [Application]، مرجع مورد نیاز خود را از لایه [service] به شرح زیر دریافت خواهد کرد:
- در متد [init]، این کنترلکننده درخواست میکند که لایه [Spring IoC] مرجعی به لایه [service] در اختیار آن قرار دهد
- سپس [Spring IoC] از یک فایل پیکربندی، XML، استفاده میکند که به آن میگوید کدام کلاس باید نمونهسازی شود و چگونه باید اولیه شود.
- [Spring IoC] مرجع لایهٔ تازهساخت [service] را به کنترلر [Application] بازمیگرداند.
مزیت این راهحل این است که نام کلاسهای ایجادکننده لایههای مختلف دیگر در متد [init] کنترلر به صورت کد سخت درج نشدهاند، بلکه به سادگی در یک فایل پیکربندی قرار دارند. تغییر پیادهسازی یک لایه مستلزم تغییر این فایل پیکربندی است، اما نه خود کنترلر.
اکنون با استفاده از چند مثال به قابلیتهای [Spring IoC] نگاهی میاندازیم.
15.2. Spring IoC در عمل
15.2.1. اسپرینگ
[Spring IoC] بخشی از یک پروژه بزرگتر است که در آدرس URL [http://www.springframework.org/] (مه ۲۰۰۶) در دسترس قرار دارد:
![]() | ![]() |
![]() |
- [1]: Spring از فناوریهای شخص ثالث مختلفی استفاده میکند که در اینجا به عنوان dépendances به آنها اشاره شده است. شما باید نسخهای را دانلود کنید که حاوی dépendances باشد تا مجبور به دانلود کتابخانههای ابزار شخص ثالث در آینده نشوید.
- [2]: ساختار دایرکتوری فایل فشردهشده دانلودشده
- [3]: توزیعهای [Spring] و c.a.d. آرشیوهای .jar خود پروژه Spring، بدون وابستگیهای آن. جنبه [IoC] از Spring توسط آرشیوهای [spring-core.jar, spring-beans.jar] فراهم میشود.
- [4,5]: آرشیوهای ابزارهای شخص ثالث
15.2.2. پروژههای اکلیپس برای مثالها
ما سه مثال برای نشان دادن نحوه استفاده از Spring IoC خواهیم ساخت. همه آنها در پروژهٔ Eclipse زیر گنجانده شدهاند:

پروژه [springioc-exemples] طوری پیکربندی شده است که فایلهای منبع و کلاسهای کامپایلشده در ریشه پوشه پروژه قرار گیرند:
![]() |
- [1]: ساختار دایرکتوری پروژه [Eclipse]
- [2]: فایلهای پیکربندی Spring در ریشه پروژه قرار دارند، یعنی در پوشه Classpath برنامه
- [3]: کلاسهای مثال ۱
- [4]: کلاسهای مثال ۲
- [5]: کلاسهای مثال ۳
- [6]: کتابخانههای پروژه [spring-core.jar, spring-beans.jar] را میتوان در پوشه [dist] توزیع Spring و کتابخانههای [commons-logging.jar] را در پوشه [lib/jakarta-commons] یافت. این سه آرشیو در Classpath برنامه گنجانده شدهاند.
15.2.3. مثال ۱
عناصر در مثال ۱ در بسته [springioc01] پروژه قرار داده شدهاند:
![]()
کلاس [Personne] به شرح زیر است:
کلاس شامل است:
- خطوط ۶–۷: دو فیلد خصوصی، 'name' و 'age'
- خطوط 23–38: متدهای get و set برای این دو فیلد
- خطوط ۱۰–۱۲: متد toString برای بازیابی مقدار شی [Personne] به صورت یک رشته
- خطوط ۱۵–۲۱: یک متد `init` که هنگام ایجاد شی توسط Spring فراخوانی میشود، و یک متد `close` که هنگام تخریب شی فراخوانی میشود
برای نمونهسازی اشیاء از نوع [Personne] با استفاده از Spring، از فایل زیر [spring-config-01.xml] استفاده خواهیم کرد:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="personne1" class="istia.st.springioc01.Personne" init-method="init" destroy-method="close">
<property name="nom" value="Simon" />
<property name="age" value="40" />
</bean>
<bean id="personne2" class="istia.st.springioc01.Personne" init-method="init" destroy-method="close">
<property name="nom" value="Brigitte" />
<property name="age" value="20" />
</bean>
</beans>
- خطوط ۳ و ۱۲: تگ <beans> تگ ریشه برای فایلهای پیکربندی Spring است. در داخل این تگ، تگ <bean> برای تعریف اشیاء مختلف مورد استفاده قرار میگیرد.
- خطوط ۴–۷: تعریف یک bean
- خط ۴: این بیون [personne1] نامیده میشود (ویژگی id) و نمونهای از کلاس [istia.st.springioc01.Personne] است (ویژگی class). متد [init] این نمونه پس از ایجاد آن (ویژگی init-method) فراخوانی خواهد شد و متد [close] این نمونه قبل از نابودی آن فراخوانی خواهد شد (ویژگی destroy-method).
- خط ۵: مقداری را که باید به ویژگی [nom] (صفت name) از نمونهٔ ایجادشدهٔ [Personne] اختصاص داده شود، تعریف میکند. برای انجام این инициализация، اسپرینگ از متد [setNom] استفاده خواهد کرد. بنابراین این متد باید وجود داشته باشد. در اینجا این شرایط برقرار است.
- خط ۶: همین موضوع در مورد خصوصیت [age] نیز صدق میکند.
- خطوط ۸–۱۱: تعریف مشابهی از یک bean به نام [personne2]
کلاس تست [Main] به شرح زیر است:
توضیحات:
- خط ۱۰: برای بازیابی بینهای تعریفشده در فایل [spring-config-01.xml]، از یک شیء از نوع [XmlBeanFactory] استفاده میکنیم که به ما امکان میدهد بینهای تعریفشده در فایل XML را نمونهسازی کنیم. فایل [spring-config-01.xml] در [ClassPath] برنامه، c.a.d، در یکی از دایرکتوریهایی قرار میگیرد که ماشین مجازی جاوا هنگام جستجوی کلاسی که برنامه به آن ارجاع داده است، بررسی میکند. ابژه [ClassPathResource] برای جستجو در میان منابع داخل [ClassPath] یک برنامه، در این مورد فایل [spring-config-01.xml]، استفاده میشود. شیء حاصل [bf] (کارخانه بین) برای بهدستآوردن مرجع یک بین با نام «XX» از طریق عبارت bf.getBean("XX") استفاده میشود.
- خط ۱۲: یک مرجع برای بین با نام [personne1] در فایل [spring-config-01.xml] درخواست میشود.
- خط ۱۳: مقدار شیء متناظر [Personne] نمایش داده میشود.
- خطوط ۱۵–۱۶: همین کار برای bean با نام [personne2] انجام میشود.
- خطوط ۱۸–۱۹: دانه با نام [personne2] دوباره بازیابی میشود.
- خط ۲۱: تمام بیونهایی با نام [bf] و c.a.d و همچنین آنهایی که از فایل [spring-config-01.xml] ایجاد شدهاند، حذف میشوند.
اجرای کلاس [Main] نتایج زیر را تولید میکند:
توضیحات:
- خط ۱ با اجرای خط ۱۲ از [Main] به دست آمد. عملیات
ایجاد دانه [personne1] را اجباری کرد. از آنجایی که [init-method="init"] در تعریف bean [personne1] نوشته شده بود، متد [init] از شیء ایجاد شده [Personne] اجرا شد. پیام مربوطه نمایش داده میشود.
- خط ۲: خط ۱۳ از [Main] مقدار شی ایجاد شده [Personne] را نمایش داد.
- خطوط ۳–۴: همین پدیده برای بین با نام [personne2] رخ میدهد.
- خط ۵: عملیات در خطوط ۱۸–۱۹ از [Main]
personne2 = (Personne) bf.getBean("personne2");
System.out.println("personne2=" + personne2.toString());
موجب ایجاد یک شیء جدید از نوع [Personne] نشد. اگر اینطور بود، متد [init] نمایش داده میشد. این اصل الگوی تکinstance (Singleton) است. به طور پیشفرض، اسپرینگ تنها یک instance از هر bean را در فایل پیکربندی خود ایجاد میکند. این یک سرویس ارجاع شیء است. اگر برای ارجاع به شیئی که هنوز ایجاد نشده است درخواست شود، آن را ایجاد کرده و ارجاعی به آن بازمیگرداند. اگر شیء قبلاً ایجاد شده باشد، اسپرینگ به سادگی ارجاعی به آن بازمیگرداند. در اینجا، از آنجایی که [personne2] قبلاً ایجاد شده است، اسپرینگ به سادگی ارجاعی به آن بازمیگرداند.
- خروجی در خطوط ۶–۷ توسط خط ۲۱ از `[Main]` تحریک شد، که درخواست نابودی تمام بیانهایی را که توسط شیء `[XmlBeanFactory bf]` ارجاع شدهاند، یعنی بیانهای `[personne1, personne2]`، میدهد. از آنجا که این دو بیون دارای ویژگی [destroy-method="close"] هستند، متد [close] در هر دو بیون اجرا میشود و باعث نمایش خطوط ۶–۷ میگردد.
اکنون که مبانی پیکربندی Spring را پوشش دادهایم، میتوانیم توضیحات را کمی سریعتر پیش ببریم.
15.2.4. مثال ۲
عناصر در مثال ۲ در پکیج [springioc02] پروژه قرار دارند:

پکیج [springioc02] ابتدا با کپی و پیست پکیج [springioc01] ایجاد میشود؛ سپس کلاس [Voiture] به آن اضافه شده و کلاس [Main] برای مثال جدید تطبیق داده میشود.
کلاس [Voiture] به شرح زیر است:
کلاس شامل:
- خطوط ۵–۷: سه فیلد خصوصی: type، make و owner. این فیلدها را میتوان با استفاده از متدهای عمومی get و set بیِن در خطوط ۲۶–۴۸ مقداردهی اولیه و خواند. همچنین میتوان آنها را با استفاده از سازنده Car(String, String, Person) که در خطوط ۱۳–۱۷ تعریف شده است مقداردهی اولیه کرد. این کلاس همچنین دارای یک سازنده بدون آرگومان برای انطباق با استاندارد JavaBean است.
- خطوط ۲۰–۲۳: یک متد toString برای بازیابی مقدار شی [Voiture] به صورت یک رشته
- خطوط ۵۱–۵۷: یک متد `init` که بلافاصله پس از ایجاد شی توسط Spring فراخوانی میشود، و یک متد `close` که هنگام تخریب شی فراخوانی خواهد شد
برای ایجاد اشیاء از نوع [Voiture]، از فایل Spring زیر [spring-config-02.xml] استفاده خواهیم کرد:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="personne1" class="istia.st.springioc02.Personne" init-method="init" destroy-method="close">
<property name="nom" value="Simon" />
<property name="age" value="40" />
</bean>
<bean id="personne2" class="istia.st.springioc02.Personne" init-method="init" destroy-method="close">
<property name="nom" value="Brigitte" />
<property name="age" value="20" />
</bean>
<bean id="voiture1" class="istia.st.springioc02.Voiture" init-method="init" destroy-method="close">
<constructor-arg index="0" value="Peugeot" />
<constructor-arg index="1" value="307" />
<constructor-arg index="2">
<ref local="personne2" />
</constructor-arg>
</bean>
</beans>
این فایل یک بین با کلید «voiture1» از نوع [Voiture] (خطوط ۱۲–۱۷) را به بینهای تعریفشده در [spring-config-01.xml] اضافه میکند. برای инициалиزه کردن این بین، میتوانستیم بنویسیم:
به جای انتخاب متدی که در مثال ۱ نشان داده شده است، ما در اینجا تصمیم گرفتهایم از سازندهٔ کلاس Car(String, String, Person) استفاده کنیم.
- خط ۱۲: تعریف نام بین، کلاس آن، متدی که پس از نمونهسازی اجرا میشود و متدی که پس از تخریب اجرا میشود.
- خط ۱۳: مقدار پارامتر اول سازنده [Voiture(String, String, Personne)].
- خط ۱۴: مقدار پارامتر دوم سازنده [Voiture(String, String, Personne)].
- خطوط ۱۵–۱۷: مقدار پارامتر سوم سازنده [Voiture(String, String, Personne)]. این پارامتر از نوع [Personne] است. این کلاس با مرجع (برچسب ref) دانه [personne2] که در همان فایل تعریف شده است (ویژگی local) تأمین میشود.
برای آزمایشهای ما، از کلاس زیر [Main] استفاده خواهیم کرد:
متد [main] مرجع به بن [voiture1] (خط ۱۲) را بازیابی کرده و آن را نمایش میدهد (خط ۱۳). نتایج به شرح زیر است:
توضیحات:
- متد [main] یک مرجع به بیون [voiture1] (خط ۱۲) درخواست میکند. اسپرینگ ساخت بیون [voiture1] را آغاز میکند زیرا این بیون هنوز ایجاد نشده است (سینگلتون). از آنجایی که بیِن [voiture1] به بیِن [personne2] ارجاع میدهد، بیِن دوم نیز به نوبه خود ایجاد میشود. بیِن [personne2] ایجاد شده است. سپس متد آن [init] اجرا میشود (خط ۱) در نتایج. سپس بین [voiture1] نمونه سازی میشود. سپس متد آن [init] اجرا میشود (خط ۲) در نتایج.
- خط ۳ نتایج از خط ۱۳ [main] میآید: مقدار bean [voiture1] نمایش داده میشود.
- خط ۱۵ از [main] درخواست نابودی تمام بیینهای موجود را میدهد که باعث نمایش خطوط ۴ و ۵ نتایج میشود.
15.2.5. مثال ۳
عناصر در مثال ۳ در پکیج [springioc03] پروژه قرار داده شدهاند:

پکیج [springioc03] ابتدا با کپی و پیست کردن پکیج [springioc01] ایجاد میشود، سپس کلاس [GroupePersonnes] به آن اضافه میشود، کلاس [Voiture] حذف شده و کلاس [Main] برای مثال جدید تطبیق داده میشود.
کلاس [GroupePersonnes] به شرح زیر است:
دو عضو خصوصی آن عبارتند از:
خط ۸: members: آرایهای از افرادی که عضو گروه هستند
خط ۹: groupesDeTravail: یک دیکشنری که یک شخص را به یک گروه کاری نگاشت میکند
در اینجا باید توجه داشت که کلاس [GroupePersonnes] هیچ سازندهای بدون آرگومان تعریف نمیکند. شایان ذکر است که در صورت عدم وجود هرگونه سازنده، یک سازنده «پیشفرض» وجود دارد که همان سازنده بدون آرگومان است و هیچ کاری انجام نمیدهد.
هدف در اینجا نشان دادن نحوهٔ امکانپذیر ساختن инициалиزهسازی اشیاء پیچیده، مانند اشیائی که دارای فیلدهای از نوع آرایه یا دیکشنری هستند، توسط Spring است. فایل bean با نام [spring-config-03.xml] از مثال ۳ به شرح زیر است:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="personne1" class="istia.st.springioc03.Personne" init-method="init" destroy-method="close">
<property name="nom" value="Simon" />
<property name="age" value="40" />
</bean>
<bean id="personne2" class="istia.st.springioc03.Personne" init-method="init" destroy-method="close">
<property name="nom" value="Brigitte" />
<property name="age" value="20" />
</bean>
<bean id="groupe1" class="istia.st.springioc03.GroupePersonnes" init-method="init" destroy-method="close">
<property name="membres">
<list>
<ref local="personne1" />
<ref local="personne2" />
</list>
</property>
<property name="groupesDeTravail">
<map>
<entry key="Brigitte" value="Marketing" />
<entry key="Simon" value="Ressources humaines" />
</map>
</property>
</bean>
</beans>
- خطوط ۱۴–۱۷: تگ <list> برای مقداردهی اولیه یک فیلد از نوع آرایه یا فیلدی که رابط List را پیادهسازی میکند، با مقادیر مختلف استفاده میشود.
- خطوط ۲۰–۲۳: تگ <map> به شما امکان میدهد همین کار را با فیلدی که رابط Map را پیادهسازی میکند، انجام دهید.
برای آزمایشهایمان، از کلاس زیر استفاده خواهیم کرد: [Main]:
- خطوط ۱۲–۱۳: ما از Spring یک مرجع به bean با نام [groupe1] درخواست میکنیم و مقدار آن را نمایش میدهیم.
نتایج بهدستآمده به شرح زیر است:
توضیحات:
- در خط ۱۲ از [Main]، یک مرجع به بین [groupe1] درخواست میشود. اسپرینگ شروع به ایجاد این بین میکند. از آنجا که بین [groupe1] به بینهای [personne1] و [personne2] ارجاع میدهد، این دو بین ایجاد میشوند (خطوط ۱ و ۲ نتایج). سپس بیون [groupe1] نمونه برداری شده و متد آن [init] اجرا میشود (خط ۳ نتایج).
- خط ۱۳ از [Main] خط ۴ نتایج را نمایش میدهد.
- خط 15 از [Main] خطوط 5 تا 7 نتایج را نمایش میدهد.
15.3. پیکربندی یک برنامهٔ چندلایه با Spring
بیایید یک برنامهٔ سهلایه با ساختار زیر را در نظر بگیریم:
کاربر
دادهها
لایه کسبوکار [metier]
لایه دسترسی به داده [dao]
لایه رابط کاربری [ui]
در اینجا هدف ما نشان دادن مزایای استفاده از Spring برای ساخت چنین معماری است.
- این سه لایه از طریق استفاده از رابطهای جاوا مستقل خواهند شد
- ادغام این سه لایه توسط Spring انجام خواهد شد
ساختار برنامه در اکلیپس میتواند به صورت زیر باشد:
![]() |
- [1]: لایه [dao]:
- [IDao]: رابط لایه
- [Dao1, Dao2]: دو پیادهسازی از این رابط
- [2]: لایه [metier]:
- [IMetier]: رابط لایه
- [Metier1, Metier2]: دو پیادهسازی از این رابط
- [3]: لایه [ui]:
- [IUi]: رابط لایه
- [Ui1, Ui2]: دو پیادهسازی از این رابط
- [4]: فایلهای پیکربندی Spring برنامه. ما برنامه را به دو روش پیکربندی خواهیم کرد.
- [5]: کتابخانههای مورد نیاز برنامه. اینها همان کتابخانههایی هستند که در مثالهای قبلی استفاده شدهاند.
- [6]: بستهٔ تست. [Main1] از پیکربندی [spring-config-01.xml] استفاده خواهد کرد و [Main2] از پیکربندی [spring-config-02.xml] استفاده خواهد کرد.
هدف این مثال نشان دادن این است که میتوانیم پیادهسازی یک یا چند لایه از برنامه را بدون هیچ تأثیری بر سایر لایهها تغییر دهیم. همه چیز در فایل پیکربندی Spring مدیریت میشود.
لایه [dao]
لایه [dao] رابط زیر [IDao] را پیادهسازی میکند:
پیادهسازی [Dao1] به شرح زیر خواهد بود:
پیادهسازی [Dao2] به شرح زیر خواهد بود:
لایه [métier]
لایه [métier] رابط زیر [IMetier] را پیادهسازی میکند:
پیادهسازی [Metier1] به شرح زیر خواهد بود:
پیادهسازی [Metier2] به شرح زیر خواهد بود:
لایه [ui]
لایه [ui] رابط زیر [IUi] را پیادهسازی میکند:
پیادهسازی [Ui1] به شرح زیر خواهد بود:
پیادهسازی [Ui2] به شرح زیر خواهد بود:
فایلهای پیکربندی Spring
اولین مورد، [spring-config-01.xml]:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!--کلاس DAO -->
<bean id="dao" class="istia.st.springioc.troistier.dao.Dao1"/>
<!-- کلاس تجاری -->
<bean id="metier" class="istia.st.springioc.troistier.metier.Metier1">
<property name="dao">
<ref local="dao" />
</property>
</bean>
<!--کلاس UI -->
<bean id="ui" class="istia.st.springioc.troistier.ui.Ui1">
<property name="metier">
<ref local="metier" />
</property>
</bean>
</beans>
دومین مورد، [spring-config-02.xml]:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!--کلاس DAO -->
<bean id="dao" class="istia.st.springioc.troistier.dao.Dao2"/>
<!--کلاس کسبوکار -->
<bean id="metier"
class="istia.st.springioc.troistier.metier.Metier2">
<property name="dao">
<ref local="dao" />
</property>
</bean>
<!--کلاس UI -->
<bean id="ui" class="istia.st.springioc.troistier.ui.Ui2">
<property name="metier">
<ref local="metier" />
</property>
</bean>
</beans>
برنامههای آزمون
برنامه [Main1] به شرح زیر است:
برنامه [Main1] از فایل پیکربندی [spring-config-01.xml] و در نتیجه پیادهسازیهای لایه [Ui1, Metier1, Dao1] استفاده میکند. نتایج نمایش داده شده در کنسول Eclipse:
برنامه [Main2] به شرح زیر است:
برنامه [Main2] از فایل پیکربندی [spring-config-02.xml] و در نتیجه پیادهسازیهای لایههای [Ui2, Metier2, Dao2] استفاده میکند. نتایج نمایش داده شده در کنسول Eclipse:
15.4. Conclusion
اپلیکیشن ما انعطافپذیری زیادی برای توسعه در آینده فراهم میکند. پیادهسازی یک لایه را میتوان به سادگی از طریق پیکربندی تغییر داد. کد لایههای دیگر بدون تغییر باقی میماند. این امر به لطف مفهوم IoC، که یکی از دو ستون اصلی Spring است، محقق میشود. ستون دیگر AOP (برنامهنویسی جنبهگرا) است که به آن نپرداختهایم. این امکان را میدهد که «رفتار» به یک متد کلاس اضافه شود—باز هم از طریق پیکربندی—بدون تغییر کد متد.






