เลิกใช้ @Value พร่ำเพรื่อ จัดระเบียบ Config ให้โปรด้วย Type-safe Configuration

เลิกใช้ @Value พร่ำเพรื่อ จัดระเบียบ Config ให้โปรด้วย Type-safe Configuration

February 03, 2026 · 2 min read · 3 views

หนึ่งในสิ่งที่ทำให้ Code ดู "สกปรก" และดูแลยากที่สุดใน Spring Boot คือการเห็น Annotation @Value("${...}") กระจายอยู่เต็มไปหมด

Code ที่ Dev ส่วนใหญ่คุ้นเคย:

java
@Service
public class PaymentService {

    @Value("${app.payment.gateway-url}")
    private String gatewayUrl;

    @Value("${app.payment.timeout}")
    private int timeout;

    @Value("${app.payment.api-key}")
    private String apiKey;

    @Value("${app.payment.retry-count}")
    private int retryCount;

    // Logic ยืดยาว...
}

ปัญหาคืออะไร? (The Impact)

Code นี้ทำงานได้ครับ แต่มันคือ ระเบิดเวลา:

  1. Stringly-typed: ถ้าคุณพิมพ์ Key ผิดแม้แต่ตัวเดียว (เช่น gateway-urll) แอปจะไม่ฟ้องตอน Compile แต่จะไป Crash ตอน Runtime
  2. Validation ยาก: ถ้าลืมใส่ค่า timeout ใน application.yml หรือใส่ค่าติดลบ Code นี้ก็รับเข้ามาดื้อๆ แล้วไปพังตอนใช้งานจริง
  3. กระจัดกระจาย: ถ้ามี 5 Services ที่ต้องใช้ gateway-url คุณก็ต้องก๊อปปี้ @Value ไปแปะทั้ง 5 ที่ วันไหนเปลี่ยน Key ก็ตามแก้กันตาแตก

ทางออก: รวมศูนย์ด้วย @ConfigurationProperties

Spring Boot สนับสนุนให้เรา Map ค่า Config จาก application.yml เข้ามาใส่ใน Java Class (POJO) โดยตรง วิธีนี้เรียกว่า Type-safe Configuration

เปลี่ยน Code เป็นแบบนี้:

1. ใน application.yml ใส่ข้อมูลไว้ประมาณนี้

yaml
# application.yml

app:
  payment:
    gateway-url: https://api.stripe.com  
    timeout: 5000
    api-key: sk_test_123456               
    retry-count: 3

2. สร้าง Class สำหรับเก็บ Config โดยเฉพาะ:

java
@Configuration
@ConfigurationProperties(prefix = "app.payment")
@Validated // ทีเด็ดอยู่ตรงนี้!
@Data
public class PaymentProperties {

    @NotBlank // บังคับว่าห้ามว่าง
    private String gatewayUrl;

    @Min(1000) // บังคับว่าต้องมากกว่า 1000ms
    private int timeout = 5000; // set default ได้ด้วย

    @NotBlank
    private String apiKey;

    private int retryCount;
}

3. Inject Class นี้เข้าไปใช้ใน Service แทน:

java
@Service
@RequiredArgsConstructor
public class PaymentService {

    // Inject ก้อนเดียวจบ สะอาดตา
    private final PaymentProperties properties;

    public void process() {
        // เรียกใช้แบบ Type-safe สบายใจ
        String url = properties.getGatewayUrl();
        int timeout = properties.getTimeout();
    }
}

ความแตกต่างของผลลัพธ์ที่ได้

  1. Fail-Fast (พังตั้งแต่เริ่ม): ด้วย @Validated ถ้าคุณลืมใส่ Config หรือใส่ค่าผิด Format แอปจะ Throw Error ตั้งแต่ตอน Start ทำให้เรารู้ตัวทันที ไม่ต้องรอไปพังหน้างาน
  2. IDE Autocomplete: นี่คือ Killer Feature! เมื่อคุณประกาศ Class นี้ปุ๊บ เวลาคุณไปพิมพ์ในไฟล์ application.yml IDE (IntelliJ/VS Code) จะเด้ง Autocomplete ให้ทันที เพราะมันรู้โครงสร้างจาก Java Class แล้ว
  3. Refactor ง่าย: วันหนึ่งอยากเปลี่ยนชื่อ Key จาก api-key เป็น token คุณแก้ที่ Java Class จุดเดียว มันจะ Link ไปถึงทุกที่ที่เรียกใช้ ไม่ต้อง Find & Replace ให้เสียวไส้

บทสรุป

@Value เหมาะสำหรับค่าเล็กๆ น้อยๆ ที่ใช้ที่เดียว แต่สำหรับ Config ที่เป็นเรื่องเป็นราว หรือมีการจับกลุ่มกัน (เช่น Database config, Mail config, 3rd party API) การใช้ @ConfigurationProperties คือมาตรฐานที่ทำให้โปรเจกต์ของคุณดูเป็นมืออาชีพและ Robust ขึ้นทันทีครับ

Responses (0)

No responses yet. Be the first to respond.