Published on

مروری بر فریم ورک اسپرینگ

نویسندگان

فیلسوف یونانی هراکلیتوس : "تنها چیزی که ثابت است، تغییر است." در زمینه توسعه نرم‌افزار، این جمله به حقیقتی مهم اشاره می‌کند؛ اینکه نرم‌افزار و فناوری دائماً در حال تغییر و تحول هستند. در دنیای برنامه‌نویسی و مهندسی نرم‌افزار، تغییرات در ابزارها، زبان‌ها، چارچوب‌ها و نیازهای مشتریان یا کاربران به طور مداوم رخ می‌دهد.

بنابراین، توسعه‌دهندگان نرم‌افزار باید انعطاف‌پذیر باشند و خود را با این تغییرات سازگار کنند. به طور کلی، این جمله بر اهمیت انطباق با تغییرات و آماده بودن برای یادگیری و رشد در این حوزه تأکید دارد. روش توسعه نرم‌افزار در طول سال‌ها به‌طور قابل توجهی تغییر کرده است. 20 سال پیش، تمرکز اصلی بر توسعه برنامه‌های وب مبتنی بر مرورگر و بانک‌های اطلاعاتی رابطه‌ای بود. اما امروز ما بیشتر با معماری میکروسرویس‌ها و برنامه‌های ابری سر و کار داریم که نیاز به ذخیره‌سازی داده‌ها در پایگاه‌های داده مختلف و پیاده‌سازی برنامه‌های واکنشی دارند.

این تحول نیاز به تغییر در ابزارها و چارچوب‌هایی مانند اسپرینگ را برجسته می‌کند. یکی از مفاهیم کلیدی در Spring که به مدیریت اجزا و مؤلفه‌ها یا همان "Beans" معروف است. هر برنامه کاربردی غیرساده (nontrivial) از اجزا و مؤلفه‌های مختلفی تشکیل شده است که هرکدام مسئول بخش خاصی از کارکرد کلی برنامه هستند.

این مؤلفه‌ها باید به گونه‌ای هماهنگ با هم تعامل داشته باشند تا برنامه به درستی کار کند. در قلب Spring، چیزی به نام "context" یا "Application Context" وجود دارد که نقش یک container (ظرف) را ایفا می‌کند. این container وظیفه ایجاد، مدیریت و ارتباط بین مؤلفه‌های برنامه (که به آن‌ها Beans می‌گویند) را بر عهده دارد.

این به نوعی شبیه به فرآیند ساخت یک خانه است؛ جایی که آجرها، ملات، چوب، میخ‌ها، لوله‌کشی و سیم‌کشی باید با هم ترکیب شوند تا خانه‌ای کامل ساخته شود. در Spring، "wiring" به معنی اتصال و تنظیم ارتباطات بین این مؤلفه‌هاست. Spring از طریق این اتصال، مؤلفه‌ها را به یکدیگر معرفی می‌کند تا هرکدام بتوانند به درستی وظایف خود را انجام دهند. این فرآیند یکی از ویژگی‌های کلیدی Spring است که از مفاهیمی مانند تزریق وابستگی (Dependency Injection) استفاده می‌کند تا به صورت خودکار اجزا را با هم مرتبط کند،

بدون اینکه توسعه‌دهنده نیاز به مدیریت پیچیدگی‌های داخلی داشته باشد. به زبان ساده، Spring به عنوان یک چارچوب، به شما کمک می‌کند تا مؤلفه‌های مختلف برنامه‌تان را به هم وصل کنید و مدیریت این ارتباطات را به صورت اتوماتیک انجام دهید.

حالا برای مثال به سناریوی زیر توجه کنید که در آن به توضیح مفاهیم Dependency Injection (DI) و Inversion of Control (IoC) در Spring می‌پردازیم، و همچنین نحوه پیکربندی سرویس‌ها با استفاده از Spring XML و پیکربندی مبتنی بر جاوا را به تصویر می‌کشیم. در ادامه، به تفصیل به این مفاهیم و مثال‌ها خواهیم پرداخت.

سناریو:

در این مثال، دو سرویس داریم:

  1. Inventory Service (سرویس انبار): برای بازیابی سطح موجودی‌ها استفاده می‌شود.
  2. Product Service (سرویس محصول): اطلاعات اولیه محصولات را ارائه می‌دهد، اما برای ارائه اطلاعات کامل، وابسته به سرویس انبار است تا سطح موجودی‌ها را هم بتواند ارائه کند.

توضیح روابط بین این سرویس‌ها:

  • ProductService برای ارائه اطلاعات کامل محصولات، نیاز به داده‌هایی از InventoryService دارد. بنابراین، InventoryService به ProductService تزریق می‌شود.
  • Spring Application Context مسئول مدیریت و تزریق این سرویس‌ها است. در واقع، Spring با استفاده از IoC و DI، به‌طور خودکار سرویس‌ها را به یکدیگر تزریق می‌کند.

شکل زیر روابط بین سرویس‌ها و نحوه مدیریت آن‌ها توسط Spring Application Context را نشان می‌دهد. در این تصویر، InventoryService به‌عنوان وابستگی به ProductService تزریق شده است و سایر اجزای برنامه نیز توسط Spring مدیریت می‌شوند.

Di

روش‌های پیکربندی:

1. پیکربندی با XML:

در گذشته، پیکربندی سرویس‌ها و وابستگی‌ها در Spring با استفاده از فایل‌های XML انجام می‌شد. در اینجا مثالی از پیکربندی XML برای تعریف دو Bean (InventoryService و ProductService) و تزریق آن‌ها آمده است:

<bean id="inventoryService"
      class="com.example.InventoryService" />

<bean id="productService"
      class="com.example.ProductService">
    <constructor-arg ref="inventoryService" />
</bean>

در این پیکربندی، ProductService به InventoryService از طریق تزریق در سازنده (constructor) وابسته است. Spring به‌طور خودکار InventoryService را ایجاد کرده و آن را به ProductService تزریق می‌کند.

2. پیکربندی با جاوا:

در نسخه‌های جدیدتر Spring، پیکربندی مبتنی بر جاوا جایگزین XML شده است. این روش نه‌تنها امن‌تر و تایپ-محورتر است، بلکه به دلیل استفاده از کد جاوا، قابلیت بازآرایی و تغییرات کمتری در پروژه‌ها ایجاد می‌کند. مثال معادل جاوا برای همان پیکربندی XML به شکل زیر است:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ServiceConfiguration {

    @Bean
    public InventoryService inventoryService() {
        return new InventoryService();
    }

    @Bean
    public ProductService productService() {
        return new ProductService(inventoryService());
    }
}

در اینجا:

  • @Configuration: به Spring می‌گوید که این کلاس یک کلاس پیکربندی است و Bean‌هایی را به Spring Application Context اضافه می‌کند.
  • @Bean: مشخص می‌کند که متدهایی مانند inventoryService() و productService() باید Beanهای قابل مدیریت توسط Spring باشند. این Bean‌ها در Application Context ذخیره شده و وابستگی‌ها به‌طور خودکار مدیریت می‌شوند.

مزایای پیکربندی مبتنی بر جاوا:

پیکربندی مبتنی بر جاوا نسبت به XML دارای مزایای زیر است:

  • Type Safety (ایمنی نوع): از آنجا که جاوا strongly typed است، اشکالات مربوط به نوع داده‌ها زودتر شناسایی می‌شود.
  • قابلیت بازآرایی بهتر: تغییرات در کدهای جاوا نسبت به XML ساده‌تر است و با refactor کردن، جاوا به‌راحتی کدها را مدیریت می‌کند.

Autowiring و Component Scanning:

به جای پیکربندی دستی Bean‌ها (چه با XML و چه با جاوا)، Spring Boot به‌صورت خودکار بسیاری از این فرآیندها را انجام می‌دهد. این فرآیندها شامل:

  • Component Scanning: Spring می‌تواند به‌طور خودکار تمام کلاس‌های موجود در classpath را اسکن کرده و Beanهای آن‌ها را شناسایی و ایجاد کند.
  • Autowiring: Spring به‌طور خودکار وابستگی‌های بین Beanها را از طریق @Autowired تزریق می‌کند.

Spring Boot و Auto-Configuration:

Spring Boot ویژگی‌های پیکربندی خودکار (auto-configuration) را معرفی کرده است. این ویژگی به Spring اجازه می‌دهد که بر اساس اجزای موجود در classpath، محیط سیستم و متغیرهای پیکربندی، تصمیم بگیرد که چه Bean‌هایی باید به هم متصل شوند، بدون نیاز به نوشتن کدهای پیکربندی به‌صورت دستی. این قابلیت به توسعه‌دهندگان اجازه می‌دهد تا بدون نوشتن خطوط زیادی از کد پیکربندی، به سرعت یک برنامه کاربردی Spring ایجاد کنند.

مثال:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class ProductService {
    private final InventoryService inventoryService;

    @Autowired
    public ProductService(InventoryService inventoryService) {
        this.inventoryService = inventoryService;
    }

    public void printProductDetails() {
        // Use inventoryService to fetch inventory levels
        System.out.println("Product and inventory details fetched.");
    }
}

در این مثال، Spring Boot به‌صورت خودکار ProductService را ایجاد کرده و InventoryService را به آن تزریق می‌کند.

جمع‌بندی:

  • Spring به ما اجازه می‌دهد که وابستگی‌ها را به‌طور خودکار مدیریت کنیم و به‌جای پیکربندی دستی، از پیکربندی‌های خودکار مانند autowiring و component scanning استفاده کنیم.
  • Spring Boot با ویژگی auto-configuration، فرآیند پیکربندی را ساده‌تر کرده است.
  • در این مثال، ProductService به InventoryService وابسته است و Spring مسئول مدیریت این وابستگی‌ها است، چه از طریق پیکربندی XML یا پیکربندی مبتنی بر جاوا.

مروری بر اکوسیستم Spring

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

  1. Core Spring Framework: هسته‌ی اصلی Spring شامل Dependency Injection (DI)، Inversion of Control (IoC) و ابزارهایی مانند Spring MVC برای توسعه وب و APIهای REST است. همچنین، پشتیبانی از برنامه‌نویسی واکنشی از طریق Spring WebFlux و پشتیبانی از دیتابیس با JdbcTemplate فراهم می‌شود.

  2. Spring Boot: Spring Boot با پیکربندی خودکار (Autoconfiguration) و وابستگی‌های آماده (Starter Dependencies) فرآیند توسعه را بسیار ساده کرده است. Actuator برای مانیتورینگ و مشاهده وضعیت برنامه نیز بخشی از Spring Boot است.

  3. Spring Data: این بخش امکان تعریف Repositoryهای دیتابیس تنها با استفاده از رابط‌های جاوا را فراهم می‌کند و از انواع دیتابیس‌ها (رابطه‌ای، سندی و گرافی) پشتیبانی می‌کند.

  4. Spring Security: یک فریم‌ورک قوی برای مدیریت امنیت برنامه‌ها، شامل احراز هویت، مجوزها و امنیت API.

  5. Spring Integration و Spring Batch: برای یکپارچه‌سازی داده‌ها و پردازش بلادرنگ یا دسته‌ای، این ابزارها الگوهای رایج یکپارچه‌سازی را پیاده‌سازی می‌کنند.

  6. Spring Cloud: مجموعه‌ای از ابزارها برای توسعه برنامه‌های مبتنی بر میکروسرویس‌ها و اپلیکیشن‌های ابری.

  7. Spring Native: پروژه‌ای آزمایشی که با استفاده از GraalVM به شما اجازه می‌دهد برنامه‌های Spring Boot را به صورت Native کامپایل کنید، که باعث افزایش سرعت اجرا و کاهش مصرف منابع می‌شود.

Spring با این ابزارها، توسعه‌دهندگان را قادر می‌سازد تا به‌سرعت برنامه‌های پیشرفته و مقیاس‌پذیر را پیاده‌سازی کنند.