سپرینگ (Spring) یکی از معروف ترین و پرکاربرد ترین framework های جاوایی است .این framework متن باز بوده و اولین بار در سال 2003 ارائه شده است. اسپرینگ از ابتدای ارائه تا الآن تغییرات زیادی داشته و بسیار قدرتمند معروف شده است.در طی آموزش های مختلف ابتدا اسپرینگ و امکانات آن را معرفی می کنیم سپس با ارائه مثال های بیشتر با امکانات مختلف آن آشنا می شویم.
اسپرینگ چیست؟
اسپرینگ framework قدرتمندی است که هدف اصلی آن برنامه های enterprise هستند اگرچه اسپرینگ بیشتر java EE را هدف گرفته است ولی در محیط های غیر از EE نیز می توان از آن استفاده کرد. بر خلاف تصوری که اشتباهاً در بین خیلی ها شکل گرفته است اسپرینگ برای ساخت اپلیکیشن تحت وب نیست بلکه Spring web که مبتنی بر مدل MVC بود و بیشتر به عنوان Spring MVC شناخته می شود تنها بخشی از اسپرینگ است که از آن برای ساخت برنامه های تحت وب استفاده می شود. اسپرینگ ماژولار است و شما بر اساس نیازی که دارید می توانید ماژول های مورد نیاز خودتان را انتخاب کنید و بقیه را کنار بگذارید.اسپرینگ همه چیز را از اول ایجاد نکرده است بلکه نحوه استفاده از تکنولوژی های موجود را ساده تر می کند و بهبود می دهد.اسپرینگ با استفاده از Dependency Injection و Inversion of Control (که بعداً در مورد آنها بیشتر توضیح می دهم) وابستگی بین اشیا در کد را کاهش می دهد و به ما کمک می کند که کد هایی قابل حمل و reusable بنویسیم .اسپرینگ به ما این امکان را می دهد که کد ها را به سادگی تست کنیم.
اسپرینگ به برنامه نویسان اجازه می دهد تا برنامه هایشان را به سبک POJO بنویسند و این یک امتیاز عالی برای برنامه نویسان جاواست.
مثال هایی از ساده سازی برنامه نویسی توسط اسپرینگ :
- به سادگی می توانید با پایگاه داده کار کنید بدون اینکه خود را درگیر پیچیدگی های transaction API کنید.
- به سادگی می توانید متد هایی را به صورت remote اجرا کنید بدون اینکه نیاز باشد در گیر RMI و ... شوید.
- می توانید به سادگی متد هایی برای کار با message ها بنویسید بدون اینکه درگیر توابع JMS شوید.
- و ....
اسپرینگ از حدود 20 ماژول تشکیل شده است که این ماژول ها را می توان به 8 دسته مطابق شکل زیر تقسیم کرد.
قبل از معرفی ماژول ها بهتر است با سه واژه DI و IoC و AOP آشنا شویم.
IoC :
Inversion of Control یا همان IoC یک واژه کلی است و باید در بستر مناسب خودش تعریف شود. IoC به این معنی نیست که همه چیز برعکس می شود بلکه در IoC باید به این بیاندیشیم که کنترل چه چیزی عوض شده است؟ هدف کلی از IoC این است که وابستگی بین کد ها را کاهش دهد و تیکه کد های کاربردی تا حد امکان مستقل از هم باشند که در این محیط های مختلف به شکل های مختلفی پیاده سازی می شود. یک مثال مشهور در این زمینه برنامه های کنسولی قدیمی است که در آن ها منو به صورت لیستی از اعداد نمایش داده می شد و سپس کاربر عددی را وارد می کرد و برنامه مبتنی بر عدد کاربر عملی را انجام می داد. به عنوان مثال کد جاوای زیر را در نظر بگیرید :
import java.util.Scanner;
public class Main {
Scanner in;
int displayMenu(){
System.out.println("-----");
System.out.println("1) get Name ...");
System.out.println("2) print Hello ");
System.out.println("3) display Random");
System.out.println("4) exit");
int item=in.nextInt();
return item;
}
void logic(){
while(true){
int menuItem=displayMenu();
if(menuItem==4){
//exit ...
break;
}else if(menuItem==3){
//display Random ...
System.out.println(Math.random());
}else if(menuItem==2){
//print Hello...
System.out.println("Hello!!");
}else if(menuItem==1){
//get Name...
String name=in.next();
}
}
}
public Main(){
in=new Scanner(System.in);
logic();
}
public static void main(String[] args) {
new Main();
}
}
در این مثال ساده متد logic هر بار متد displayMenu را فراخوانی می کند نتیجه را بررسی می کند و عمل مناسب را انجام می دهد.همانطور که دیده می شود بین منطق برنامه و نمایش منو ارتباط بسیار تنگاتنگی وجود دارد به طوری که اگر کمی متد logic را تغییر دهیم شاید دیگر
displayMenu معنا دار نباشد. در نرم افزار های امروزی که نمایش گرافیکی (GUI) دارند استفاده از Listener ها کار ها را ساده تر کرده است هنگامی که رویدادی اتفاق می افتد framework مورد نظر عمل مورد نیاز را انجام می دهد (در لیست Listener ها جست جو می کند تا Listener مورد نیاز را پیدا کند و متد مربوطه را اجرا کند) ، با استفاده از Listener ها دیگر لازم نیست برنامه نویس تمام رویداد ها را بررسی کند و سپس عمل مورد نیاز را انجام دهد ( busy waiting نداریم).
در کل می توان گفت که هدف از IoC این است که :
- منطق چه چیزی انجام شود (what to do) از منطق چه زمانی انجام شود (when to do) جدا شود.
- دو منطق ذکر شده حد الامکان اطلاعات کمی از یکدیگر داشته باشند.
نتیجه اسفاده از IoC کاهش وابستگی کد هاست. هر چه کد ها کمتر وابسته باشند بیشتر می توان آن ها را به اجزای جدا و قابل استفاده مجدد تبدیل کرد.
IoC در محیط های مختلف معنا های مختلفی دارد و به شیوه های مختلفی می توان آن را پیاده سازی کرد که در اینجا به این موارد نمی پردازیم.
DI :
Dependency Injection یا DI همانطور که از نامش پیداست از دو بخش Dependency و Injection تشکیل شده است. Dependency هنگامی است که یک کلاس A و یک کلاس B داشته باشیم و کلاس B به کلاس A وابسته باشد این وابستگی در برنامه های معمولی جاوا با ساخت یک شی از کلاس A حل می شود :
class B {
A a;
void someMethod(){
a=new A();
}
}
هنگامی که A ها بیشتر و بیشتر می شوند رابطه B با A بیشتر و بیشتر می شود و جدا ساختن A و B از هم مشکل می شود. به علاوه بسیاری از وظایف بی دلیل بر گردن برنامه نویس می افتند.
به عنوان مثال در برنامه نویسی معمولی به این شیوه عمل می کنیم :
- من پیچ شماره پنج دارم آچار شماره پنج را به من بده.
- من پیچ شماره هفت را دارم آچار شماره هفت را به من بده.
به عنوان مثال :
class B {
A a;
void someMethod(){
number=5;
if(number==5){
a=new A5();
}if(number==7){
a=new A7();
}
a.use();
}
}
در محیطی که DI اعمال شود تشخیص وابستگی ها بر عهده Container خواهد بود. در چنین محیط هایی کافی است بگوییم :
- هی این پیچ من است آچار را بده ...
container تشخیص دهنده است :هووم می بینم که پیچ شماره پنج داری ، بیا اینم آچار شماره پنج ;-)
class B {
A a;
void someMethod(){
number=5;
//use a
a.use();
}
}
تشخیص وابستگی و ایجاد شی مناسب و مدیریت lifecyle اشیا در محیطی که DI در آن وجود داشته باشد بر عهده Container است.
DI نوعی IoC محسوب می شود ولی الزاماً هر جایی که IoC وجود داشته باشد DI وجود ندارد و بدون DI نیز می توان IoC داشت.
در آموزش های مرتبط با اسپرینگ در قالب مثال های بیشتر با DI بیشتر آشنا می شویم.
AOP :
Aspect Oriented Programming یا همان AOP که در فارسی به آن برنامه نویسی جنبه گرا نیز می گویند ، مدل خاصی از برنامه نویسی است که در آن سعی می شود وظایف از هم مستقل گردند ، یعنی بر خلاف OOP که در آن استقلال Object ها اهمیت دارد (و DI سعی در افزایش این نوع استقلال دارد) در AOP سعی داریم برنامه را از لحاظ cross-cutting-concern ها جدا کنیم. concern ها یا همان جنبه ها مفاهیمی هستند که قابل تجزیه نیستند مثلاً امنیت ، انتقال داده ،احراز هویت و ... ، AOP سبک خاصی از برنامه نویسی است و در اینجا قصد معرفی کامل آن را نداریم .اسپرینگ با ارائه ماژول AOP به ما این امکان را می دهد که مبتنی بر سبک AOP برنامه نویسی کنیم ، همچنین ماژول Aspect به ما اجازه می دهد تا اسپرینگ را با AspectJ ترکیب کنیم. AspectJ یکی از مشهور ترین و قوی ترین framework هایی است که به ما اجازه می دهد به سبک AOP برنامه بنویسیم.
ماژول ها :
همانطور که قبلاً گفتم اسپرینگ از هشت بخش تشکیل شده است که حدوداً بیست ماژول را شامل می شود در ادامه به صورت مختصر با بعضی از بخش ها آشنا می شویم :
Core Container :
این بخش از ماژول های Beans و Core و Context و Expression Language تشکیل شده است.
ماژول های Core و Beans هسته اصلی اسپرینگ را تشکیل می دهند و ویژگی های DI و IoC را در اختیار ما قرار می دهند. ماژول Beans نیز BeanFactory را در اختیار ما قرار می دهد که پیاده سازی پیچیده ای از الگوی factory pattern است.
Context به عنوان واسط عمل می کند و به اما اجازه دسترسی به آبجکت های ایجاد شده را می دهد.
Expression Language گسترشی از Expression Language معرفی شده در JSP 2.1 است و به ما اجازه اجرای کوئری های پیچیده و دسترسی به اشیا مختلف را می دهد.
Spring Web :
این بخش از ماژول های Web و Portlet و Servlet و WebSocket تشکیل شده است.
همانطور که در ابتدای این آموزش نیز اشاره شد Spring Web برای طراحی web بر اساس مدل MVC به کار می رود و می تواند جایگزین بسیار خوبی برای framework هایی مثل struts باشد. اگر بگویم Spring Web پرکاربردترین و مشهور ترین بخش اسپرینگ است چندان بیراه نگفته ایم .(قبلاً هم اشاره کردم که خیلی ها Spring Web را با اسپرینگ اشتباه می گیرند).
Web : ماژول Web ویژگی ها پایه ای را در اختیار ما قرار می دهد.
Portelt : اگر با پرتال ها (مانند Liferay) و مفهوم پرتلت آشنایی داشته باشید باید بگویم که ماژول Portlet امکان برنامه نویسی پرتلت بر اساس مدل MVC را به شما می دهد.
Web-Servlet : این ماژول پیاده سازی مدل MVC را در اختیار ما قرار می دهد.
Data Access/Integeration :
این بخش همانطور که از نام آن پیداست برای کار با داده ها در سطوح مختلف است.
ماژول JDBC کار با JDBC را آسان تر می کند و ماژول ORM نیز کار با API هایی مانند JPA و JDO و .. را ساده تر می کند.
Test :
یکی از مهم ترین مزایای اسپرینگ فرایند تست است ، به دلیل وابستگی کمی که بین کد ها وجود دارد به راحتی می توانیم هر بخش را به صورت جداگانه تست کنیم بدون اینکه نیاز باشد برنامه به صورت کامل توسعه یابد.ماژول test به ما اجازه می دهد از ابزار هایی مانند JUnit یا TestNG برای تست برنامه ها استفاده کنیم.
در این آموزش به صورت مختصر با اسپرینگ و امکانات آن آشنا شدیم ، برای اطلاعات کامل می توانید به مستندات اصلی مراجعه کنید.لینک زیر معرفی اسپرینگ توسط سایت اصلی آن است :
Introduction to Spring Framework.
منبع : safecomp.ir