หมวดหมู่: Spring Boot

Java: Class Name, Bean ID ชนกันJava: Class Name, Bean ID ชนกัน

เรื่อง Class Name Collision, Bean ID Collision ( ชนกัน )


📘 Class Name Collision vs. Bean ID Collision: ความเหมือนที่แตกต่างในโลกของ Spring

ในโปรเจกต์ขนาดใหญ่ ( Enterprise Project ) การมีไฟล์จำนวนมหาศาลมักนำไปสู่สถานการณ์ที่ “ชื่อซ้ำ” แต่ในทางเทคนิคของ Java และ Spring นั้น “ชื่อคลาสซ้ำ” ไม่เท่ากับ “Bean ชนกัน” เสมอไป


Class Name Collision ( ความซ้ำซ้อนระดับ Java )

นิยาม: คือการที่คุณมีคลาส 2 คลาส ( หรือมากกว่า ) ที่ใช้ชื่อเดียวกันเป๊ะ แต่ตั้งอยู่ใน Package ที่ต่างกัน

  • ตัวอย่าง *
    • com.plusmagi.inscode.MyService
    • com.plusmagi.cbscenter.MyService

ผลกระทบ

  • ระดับ Compile: ไม่มีปัญหา เพราะ Java แยกแยะคลาสด้วย Full Qualified Name ( ชื่อ Package + ชื่อคลาส )
  • ระดับ Developer: สร้างความสับสนอย่างมาก เวลาจะ import คลาสใน IDE หากเลือกผิดตัวอาจทำให้ Logic ผิดพลาดได้
  • ระดับ Spring: หากคลาสเหล่านี้ ไม่ถูกประกาศเป็น @Component ( เป็นแค่ POJO หรือ TO ) Spring จะไม่สนใจเลย และไม่เกิดปัญหาใด ๆ ตอน Start Server

Bean ID Collision ( ความซ้ำซ้อนระดับ Spring Context )

นิยาม: คือการที่ Spring พยายามลงทะเบียน Object ( Bean ) สองตัวลงใน “ถัง” ( Context ) เดียวกันโดยใช้ “ชื่อเรียก ( Bean ID )” ซ้ำกัน

กลไกการเกิด ตามปกติถ้าเราใส่ @Component เฉย ๆ Spring จะเอาชื่อคลาสมาทำเป็นตัวเล็กตัวแรกเพื่อตั้งเป็น Bean ID ( เช่น คลาส MyService จะได้ ID ว่า myService )

  1. 1 ( Implicit Collision ): ถ้าคุณมี MyService สองคลาสในต่าง package และทั้งคู่ติด @Component เฉยๆ -> Spring จะ Crash ทันที เพราะมันพยายามสร้าง Bean ชื่อ myService ซ้ำกัน
  2. กรณีที่ 2 ( Explicit Resolution ): หากคุณระบุชื่อใน Annotation ต่างกัน เช่น
    • คลาส 1: @Component("serviceInscode")
    • คลาส 2: @Component("serviceCbsCenter")
    • ผลลัพธ์: แม้ชื่อคลาสจะซ้ำ แต่ Bean ID ไม่ซ้ำ Application จะรันได้ปกติ ✅

ตารางเปรียบเทียบความแตกต่าง

หัวข้อเปรียบเทียบClass Name CollisionBean ID Collision
ขอบเขตปัญหาโครงสร้างภาษา Java ( OOP )การจัดการภายใน Spring Container
สาเหตุหลักตั้งชื่อคลาสเหมือนกันในต่าง Packageใช้ชื่อ Bean ID ซ้ำกันใน Context เดียวกัน
การตรวจจับIDE เตือนตอน Import / สแกนด้วยสคริปต์App Crash ตอน Startup ( Runtime Error )
ผลกระทบDev สับสน, โค้ดอ่านยากโปรเจกต์รันไม่ขึ้น ( Fatal )
สถานะ Spring Beanอาจจะเป็นหรือไม่เป็น Bean ก็ได้ต้องเป็น Bean ทั้งคู่ถึงจะชนกัน

วิธีการแก้ปัญหาและการนำไปใช้งาน ( Best Practices )

เมื่อคุณรันสคริปต์ check-beans-all-repos.sh แล้วเจอความซ้ำซ้อน นี่คือแนวทางจัดการครับ

✅ การแก้ Bean ID Collision

  1. ระบุชื่อให้ชัดเจน ( Explicit Naming ): อย่าปล่อยให้ Spring ตั้งชื่ออัตโนมัติหากคลาสนั้นมีโอกาสซ้ำ ให้ระบุชื่อที่สื่อถึง Module เช่น @Service("inscodeDescriptionClient")
  2. ใช้ @Primary: หากมี Bean ประเภทเดียวกัน 2 ตัว แต่ต้องการให้ตัวหนึ่งเป็นตัวหลักที่ถูกเลือกใช้เสมอ
  3. ใช้ @Qualifier: ในจุดที่ฉีด Bean (@Autowired) ให้ระบุชื่อ ID ที่ต้องการเพื่อลดความคลุมเครือ

✅ การจัดการ Class Name Collision ( แม้จะไม่ใช่ Bean )

  • Refactor: หากเป็นไปได้ควรเปลี่ยนชื่อคลาสให้สื่อสารชัดเจนขึ้น เช่น InscodePartnerTO และ CbsPartnerTO
  • Package Organization: จัดกลุ่ม Package ให้แยกขาดตาม Domain ของงาน ( เช่น inscode vs cbscenter )

อ่านเพิ่มเติม