menusearch
javapro.ir

10 راز اسپرینگ‌بوت(Spring Boot) برای کدنویسی کارآمد

جستجو
دوشنبه ۲۴ شهریور ۱۴۰۴ | ۰۰:۲۴:۱۴
۱۴۰۴/۶/۱۸ سه شنبه
(2)
(0)
10 راز اسپرینگ‌بوت(Spring Boot) برای کدنویسی کارآمد
10 راز اسپرینگ‌بوت(Spring Boot) برای کدنویسی کارآمد

 

10 راز اسپرینگ بوت برای کدنویسی کارآمد

10 راز اسپرینگ‌بوت برای کدنویسی کارآمد

اسپرینگ‌بوت به‌خاطر افزایش بهره‌وری توسعه‌دهندگان مشهور است — پیش‌فرض‌های از‌پیش‌تعریف‌شده، سرورهای درون‌ساخته (Embedded) و پیکربندی خودکار (Auto-Configuration).

اما اگر مدتی با آن کار کرده باشید، احتمالاً متوجه شده‌اید که بعضی وقت‌ها کدتان شلوغ و تکراری به‌نظر می‌رسد یا زمانتان صرف حل مسائلی می‌شود که اسپرینگ‌بوت خودش راه‌حل آماده برایشان دارد — فقط کافی است ترفند درست را بلد باشید.

بعد از چندین سال کار با اسپرینگ‌بوت در سیستم‌های واقعی، مجموعه‌ای از نکات کمتر شناخته‌شده اما بسیار کاربردی جمع‌آوری کرده‌ام که باعث می‌شوند اپلیکیشن‌های شما ساده‌تر، تمیزتر و به‌مراتب کارآمدتر شوند.

 

بریم سراغ اصل مطلب.

 

۱. شرط‌های سفارشی با @Conditional

بیشتر توسعه‌دهندگان فقط از @ConditionalOnProperty استفاده می‌کنند، اما سیستم شرطی اسپرینگ‌بوت خیلی قدرتمندتر از این‌هاست.

شما می‌توانید شرط‌های سفارشی خودتان را تعریف کنید تا ایجاد Beanها را به صورت پویا (Dynamic) کنترل کنید.

برای مثال، می‌توانید یک Bean را فقط زمانی بارگذاری کنید که Redis در دسترس باشد:

 

public class OnRedisAvailableCondition implements Condition {
  @Override
  public boolean matches(ConditionContext context, 
                         AnnotatedTypeMetadata metadata) {
    try (Socket socket = new Socket("localhost", 6379)) {
      return true;
    } catch (Exception e) {
      return false;
    }
  }
}

@Configuration
public class RedisConfig {
  @Bean
  @Conditional(OnRedisAvailableCondition.class)
  public RedisClient redisClient() {
    return new RedisClient("localhost", 6379);
  }
}

 

اپلیکیشن شما بسته به شرایط محیط (Environment) به‌صورت هوشمندانه خودش را تطبیق می‌دهد، بدون اینکه در زمان اجرا (Startup) دچار خطا شود.

۲. کاهش زمان راه‌اندازی با Lazy Initialization

اپلیکیشن‌های اسپرینگ‌بوت معمولاً سنگین هستند، مخصوصاً در معماری میکروسرویس‌ها.

از نسخه ۲.۲ Spring Boot به بعد می‌توانید ایجاد Beanها را به‌تعویق بیندازید تا فقط زمانی ساخته شوند که واقعاً به آن‌ها نیاز دارید.

کافی است تنها یک پراپرتی را تغییر دهید:

 

spring.main.lazy-initialization=true

 

برای مثال، یک کنترلر مدیریتی (Admin Controller) که به‌ندرت استفاده می‌شود، حتی در زمان راه‌اندازی اپلیکیشن بارگذاری نمی‌شود و فقط وقتی اولین بار فراخوانی شود ساخته خواهد شد.

این ویژگی مثل یک سلاح مخفی برای کاهش زمان استارتاپ در اپلیکیشن‌های بزرگ عمل می‌کند.

۳. تغییرات اولیه در Context با ApplicationContextInitializer

آیا لازم دارید قبل از اینکه Beanها بارگذاری شوند، کانتکست اسپرینگ را دستکاری کنید؟

اینجاست که ApplicationContextInitializer به کار می‌آید.

 

public class TenantContextInitializer 
        implements ApplicationContextInitializer<ConfigurableApplicationContext> {
  @Override
  public void initialize(ConfigurableApplicationContext context) {
    String tenant = System.getenv("TENANT");
    context.getEnvironment().setActiveProfiles(tenant != null ? 
                                               tenant : "default");
  }

 

کافی است آن را در فایل spring.fact or ies ثبت کنید:

 

or g.springframew or k.context.ApplicationContextInitializer=\
com.example.TenantContextInitializer

 

این روش برای چندمستاجری (Multi-Tenant) یا راه‌اندازی پویا با پروفایل‌های مختلف فوق‌العاده کاربردی است.

۴. قدرت پنهان @ConfigurationProperties با Mapها و Listها

بیشتر توسعه‌دهندگان فقط خصوصیات ساده (Flat Properties) را نگاشت می‌کنند.

اما شما می‌توانید تنظیمات ساختاریافته را مستقیماً به آبجکت‌ها متصل (Bind) کنید.

 

مثال تنظیمات در فایل application.yml:

 

app:
  servers:
    - url: https://api1.example.com
      timeout: 5000
    - url: https://api2.example.com
      timeout: 3000
  features:
    auth: true
    cache: false

 

 

کلاس جاوا برای نگاشت مستقیم این تنظیمات:

 

@ConfigurationProperties(prefix = "app")
public class AppProperties {
  private List<ServerConfig> servers;
  private Map<String, Boolean> features;

  // getters/setters
  public static class ServerConfig {
    private String url;
    private int timeout;
  }
}


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

 

. ساخت Starterهای داخلی با Auto-Configuration

اگر در یک تیم یا سازمان بزرگ کار کرده باشید، احتمالاً متوجه تکرار کدهای مشابه در سرویس‌های مختلف شده‌اید؛ مثل:

پیکربندی لاگینگ

مانیتورینگ

تنظیمات امنیتی

تنظیمات کش

و این لیست همین‌طور ادامه دارد.

خب، عالی نمی‌شد اگر توسعه‌دهندگان فقط یک وابستگی (Dependency) اضافه می‌کردند و به شکل خودکار تمام Beanهای موردنیاز از قبل پیکربندی‌شده در اختیارشان قرار می‌گرفت؟

دقیقاً همین کاری است که Spring Boot Starterها انجام می‌دهند.

و نکته مهم اینجاست: شما می‌توانید Starterهای مخصوص خودتان را بسازید.

گام اول: ساخت یک کلاس Auto-Configuration

این کلاس چیزی نیست جز یک کلاس معمولی با Annotation @Configuration که Beanها را تعریف می‌کند.


 

@Configuration
public class LoggingAutoConfiguration {
  @Bean
  public LoggerService loggerService() {
    return new LoggerService();
  }
}

 

اگر این کلاس داخل یک JAR قرار داشته باشد، می‌خواهیم اسپرینگ‌بوت به‌صورت خودکار و به محض اضافه‌شدن این JAR به وابستگی‌ها، آن را بارگذاری کند.

گام دوم: معرفی آن به اسپرینگ‌بوت

اگر از Spring Boot 2.x استفاده می‌کنید:

یک فایل در مسیر زیر بسازید:

 

src/main/resources/META-INF/spring.fact or ies

 

و این خط را اضافه کنید:

 

or g.springframew or k.boot.autoconfigure.EnableAutoConfiguration=\
com.example.LoggingAutoConfiguration

 

این خط به اسپرینگ‌بوت می‌گوید:

«هی اسپرینگ‌بوت! وقتی اپلیکیشن من شروع شد، کلاس LoggingAutoConfiguration رو هم به‌صورت خودکار پیکربندی کن.»

اما اگر از Spring Boot 3.x (روش جدیدتر) استفاده می‌کنید:

اسپرینگ‌بوت ۳ یک مکانیزم تمیزتر معرفی کرده است. به‌جای استفاده از spring.fact or ies، باید یک فایل در مسیر زیر بسازید:

 

src/main/resources/META-INF/spring/ or g.springframew or k.boot.autoconfigure.AutoConfiguration.imp or ts

 

و کافی است کلاس خود را به سادگی در فایل فهرست کنید:

 

com.example.LoggingAutoConfiguration

 

گام سوم: استفاده از آن

حالا این پروژه را به یک JAR بسته‌بندی کنید (مثلاً logging-starter.jar) و در یک پروژه دیگر اسپرینگ‌بوت اضافه کنید.

بدون نوشتن حتی یک خط پیکربندی، آن پروژه به‌صورت خودکار یک LoggerService Bean آماده برای تزریق (Inject) خواهد داشت.

 

@RestController
public class HelloController {
private final LoggerService logger;
  public HelloController(LoggerService logger) {
    this.logger = logger;
  }
  
  @GetMapping("/hello")
  public String hello() {
    logger.log("Hello endpoint called");
    return "Hello W or ld!";
  }
}

 

 

هیچ پیکربندی اضافه‌ای لازم نیست.
هیچ تکراری در تنظیمات وجود ندارد.

فقط کافی است وابستگی (Dependency) را اضافه کنید و همه‌چیز به‌صورت خودکار کار می‌کند.

چرا این کار قدرتمند است؟

استانداردسازی لاگینگ، مانیتورینگ یا امنیت در تمام سرویس‌های شرکت

کاهش کدهای تکراری (Boilerplate) برای هر میکروسرویس جدید

کپسوله‌سازی بهترین روش‌ها (Best Practices) تا توسعه‌دهندگان مجبور نباشند دوباره چرخ را اختراع کنند

این دقیقاً همان روشی است که خود اسپرینگ‌بوت ساخته شده است — Starterهای درون‌ساخته مثل spring-boot-starter-data-jpa یا spring-boot-starter-web دقیقاً از همین مکانیزم استفاده می‌کنند.

۶. تست قدرتمند با Testcontainers

وقتی در محیط واقعی از PostgreSQL، Kafka یا Redis استفاده می‌کنید، دیگر قانع نشوید به استفاده از Mockهای ساده مثل H2.

با Testcontainers می‌توانید سرویس‌های واقعی را داخل Docker و به صورت درلحظه (On-demand) بالا بیاورید.

 

@SpringBootTest
@Testcontainers
public class UserReposit or yTest {
  @Container
  static PostgreSQLContainer<?> postgres = 
        new PostgreSQLContainer<>("postgres:15");
  
 @DynamicPropertySource
 static void registerProps(DynamicPropertyRegistry registry) {
        registry.add("spring.datasource.url", postgres::getJdbcUrl);
        registry.add("spring.datasource.username", postgres::getUsername);
        registry.add("spring.datasource.passw or d", postgres::getPassw or d);
 }
 
 @Autowired
 private UserReposit or y reposit or y;
 
 @Test
 void shouldSaveUser() {
   reposit or y.save(new User("Alice"));
   assertThat(reposit or y.findAll()).hasSize(1);
  }
}

 

تست‌های شما روی زیرساخت واقعی اجرا می‌شوند، نه فقط روی Mockها.

۷. کدنویسی رویدادمحور با @EventListener

به‌جای اینکه سرویس‌ها را با فراخوانی مستقیم به هم زنجیر کنید، از رویدادهای اسپرینگ برای جداسازی اجزای سیستم استفاده کنید.

 

// Publisher
@Component
public class or derService {

@Autowired
private ApplicationEventPublisher publisher;

public void place or der( or der or der) {
// ذخیره سفارش
publisher.publishEvent(new or derPlacedEvent( or der));
}
}

// Listener
@Component
public class NotificationHandler {
@EventListener
public void handle or derPlaced( or derPlacedEvent event) {
System.out.println("ارسال ایمیل برای سفارش: " +
event.get or der().getId());
}
}

 

این رویکرد باعث کاهش وابستگی‌ها می‌شود و کد شما را ماژولارتر و تست‌پذیرتر می‌کند.

۸. اندپوینت‌های مخفی Actuat or برای Debug

بیشتر افراد فقط از /actuat or /health استفاده می‌کنند.
اما Actuat or چند اندپوینت قدرتمند برای اشکال‌زدایی دارد:

/actuat or /conditions → ببینید چرا یک Bean ساخته شد یا نشد.
/actuat or /configprops → تمام تنظیمات Bind‌شده را یکجا بررسی کنید.
/actuat or /mappings → همه‌ی اندپوینت‌های REST را لیست کنید.

 

نمونه پیکربندی:

 

management:
endpoints:
web:
exposure:

include: health,info,conditions,configprops,mappings

 

این ویژگی یک نجات‌دهنده زمان واقعی در هنگام دیباگ مشکلات بارگذاری Beanهاست.

 

کنترل دقیق‌تر با ApplicationRunner Events

گاهی لازم است در زمان استارتاپ منطق سفارشی اجرا کنید.
خیلی از توسعه‌دهندگان سراغ @PostConstruct می‌روند، اما همیشه ابزار مناسبی نیست:

@PostConstruct قبل از آماده‌شدن کامل کانتکست اجرا می‌شود، بنابراین ممکن است NullPointerException بگیرید اگر بعضی Beanها هنوز مقداردهی نشده باشند.
کنترل دقیقی روی زمان اجرای منطق شما نسبت به چرخه حیات اپلیکیشن نمی‌دهد.

 

راه‌حل: استفاده از ApplicationRunner
ApplicationRunner بعد از استارتاپ کانتکست و زمانی که تمام Beanها آماده هستند اجرا می‌شود.

 

@Component
public class WarmupRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) {
System.out.println("Warming up caches...");
// Call DB, load configs, or prime caches here
}
}

 

حتی می‌توانید هنگام اجرای برنامه آرگومان‌ها را پاس بدهید:

 

java -jar app.jar--seed-data=true

@Override
public void run(ApplicationArguments args) {
if (args.containsOption("seed-data")) {
System.out.println("Seeding initial data...");
}
}

 

این دقیقاً مناسب وظایف اولیه‌ای است که به Beanهای کاملاً مقداردهی‌شده وابسته‌اند.

۱۰. گروه‌بندی پروفایل‌ها برای پیکربندی تمیزتر

معمولاً پروفایل‌ها را یکی‌یکی فعال می‌کنید با:

 

- - spring.profiles.active=dev

 

و در application.yml ممکن است داشته باشید:

 

spring:
profiles: dev
spring:
profiles: h2

spring:
profiles: debug

 

 

اگر بخواهید مد توسعه (dev) با دیتابیس درون‌حافظه‌ای H2 و لاگ‌های دیباگ داشته باشید، باید به این شکل اجرا کنید:

 

- - spring.profiles.active=dev,h2,debug

 

این کار هم تکراری است و هم مستعد خطاست.

اینجاست که Profile Groups نجات‌بخش هستند
از نسخه ۲.۴ به بعد، اسپرینگ‌بوت گروه‌های پروفایل را معرفی کرده که در آن یک پروفایل می‌تواند به‌طور خودکار پروفایل‌های دیگر را هم فعال کند.

 

spring:
profiles:
group:
dev: [h2,debug]
prod: [mysql,logging]

 

این یعنی:
وقتی dev را فعال می‌کنید، اسپرینگ‌بوت در پشت صحنه h2 و debug را هم فعال می‌کند.
وقتی prod را فعال می‌کنید، mysql و logging هم فعال می‌شوند.

پس فقط کافی است اجرا کنید:

 

- - spring.profiles.active=dev

 

و اپلیکیشن شما درست مثل این عمل خواهد کرد:

 

- - spring.profiles.active=dev,h2,debug

 

 

چرا این مفید است؟
بدون تکرار: لازم نیست هر بار به خاطر بسپارید dev = dev + h2 + debug.
سازگاری: همه اعضای تیم هنگام اجرای dev دقیقاً همان مجموعه پروفایل را می‌گیرند.
انعطاف‌پذیری: می‌توانید محیط‌های پیچیده بسازید بدون اینکه فایل application.yml شلوغ شود.

مثال:
فرض کنید روی یک میکروسرویس کار می‌کنید:
در dev می‌خواهید محیط سبک داشته باشید → دیتابیس H2 و لاگ‌های دیباگ اضافه.
در prod می‌خواهید محیط کامل داشته باشید → MySQL و لاگ‌های سطح تولید.

 

با استفاده از profile groups:

 

spring:
profiles:
group:
dev: [h2,debug]
prod: [mysql,logging]

 

حالا:
وقتی محلی با

 

- - spring.profiles.active=dev

 

اجرا می‌کنید، به‌طور خودکار به H2 وصل می‌شود و لاگ‌های دیباگ فعال می‌شوند.
وقتی با

- - spring.profiles.active=prod

 

اجرا می‌کنید، به‌طور خودکار به MySQL وصل می‌شود و لاگ‌های تولیدی فعال می‌شوند.

توسعه‌دهندگان دیگر لازم نیست چندین پروفایل را به یاد داشته باشند — یک کلمه کلیدی کافی است.

 

جمع‌بندی

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

  • شرط‌های سفارشی برای Beanهای تطبیقی
  • Lazy initialization برای استارتاپ سریع‌تر
  • معماری رویدادمحور با @EventListener
  • Starterهای داخلی برای استانداردسازی تنظیمات رایج
  • تست زیرساخت واقعی با Testcontainers
  • اندپوینت‌های مخفی Actuat or برای دیباگ حرفه‌ای

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

 

منبع: نوشته شده توسط Ujjawal Rohra

 

 

 


کاربران جاواپرو که علاقه‌مند به یادگیری Spring Boot هستند، در دوره‌های زیر ثبت‌نام کرده‌اند:

 

 

 

نظرات کاربران
*نام و نام خانوادگی
* پست الکترونیک
* متن پیام

بستن
*نام و نام خانوادگی
* پست الکترونیک
* متن پیام

0 نظر
هدر سایت
جشنواره تخفیفات 60% پایان فصل جاواپرو | مشاهده لیست دوره ها [اینجا کلیک کنید]
دوره جامع نخبگان معماری میکروسرویس ها با Java و Spring Boot
دوره برنامه نویسی Spring Core
مشاهده سرفصل ها و ثبت نام در دوره Spring Boot جاواپرو  [کلیک کنید]
آموزش پروژه محور اسپرینگ بوت(Spring Boot)-سیستم دانشگاه
ثبت نام در دوره آموزش Spring security
دوره پرتاب | آموزش پیش نیازهای برنامه نویسی
دوره آموزش مبانی زبان برنامه نویسی جاوا
دوره آموزش مفاهیم پیشرفته زبان برنامه نویسی جاوا
مقدمه ای از زبان برنامه نویسی جاوا(java)
آموزش زبان برنامه نویسی جاوا
آموزش گرافیک در زبان برنامه نویسی جاوا
آموزش مدیریت چیدمان گرافیکی در زبان جاوا
آموزش ساخت بازی دوبعدی در زبان جاوا
Collection ها در زبان برنامه نویسی جاوا
آموزش پروژه محور ساخت برنامه مدیریت بانک با JavaFX
نمونه پروژه های رایگان زبان جاوا
آموزش دیتابیس در زبان برنامه نویسی جاوا
نمونه مثال پایه ای زبان برنامه نویسی جاوا
نمونه مثال String در زبان برنامه نویسی جاوا
آموزش جامع برنامه نویسی JavaFX
آموزش ساخت برنامه آزمون تستی در JavaFX
آموزش برنامه نویسی سوکت در جاوا
آموزش ساخت برنامه دفترچه تلفن با JavaFX
آموزش ساخت ربات ساده تلگرام با زبان جاوا
آموزش ساخت برنامه ماشین حساب با JavaFX
آموزش ساخت برنامه ساده مدیریت ایمیل ها با JavaFX
دوره آموزش Spring Boot
سفارش انجام پروژه زبان برنامه نویسی جاوا(JAVA)
سفارش انجام پروژه برنامه نویسی متلب(MATLAB) با قیمت منصفانه و تحویل به موقع
سفارش انجام پروژه زبان برنامه نویسی سی شارپ (#C)
سفارش انجام پروژه زبان برنامه نویسی سی(C)
سفارش انجام پروژه زبان برنامه نویسی پایتون(Python)
سفارش انجام پروژه زبان برنامه نویسی PHP (پی اچ پی)
سفارش انجام پروژه زبان برنامه نویسی اسمبلی(Assembly)
سفارش انجام پروژه زبان برنامه نویسی جاوا اسکریپت (Javascript)
سفارش انجام پروژه هوش مصنوعی
سفارش انجام پروژه طراحی الگوریتم
سفارش انجام پروژه ساختمان داده ها
سفارش انجام پروژه مهندسی نرم افزار
سفارش انجام پروژه شبکه های کامپیوتری
سفارش انجام پروژه پایگاه داده: دیتابیس (database)
 سفارش انجام پروژه سیستم عامل
سفارش انجام پروژه پاورپوینت(PowerPoint)
سفارش انجام پروژه اکسل (Excel)
سفارش انجام تحقیق و تهیه مقاله
سوالات متداول برنامه نویسی
جدیدترین مطالب
طراحی توسط سایت ساز خبری
گفتگو را شروع کنید
مشاوره ،کلاس خصوصی آنلاین،پشتیبانی دوره های آکادمی جاواپرو و سفارش پروژه