เรื่อง 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.MyServicecom.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 ( Implicit Collision ): ถ้าคุณมี
MyServiceสองคลาสในต่าง package และทั้งคู่ติด@Componentเฉยๆ -> Spring จะ Crash ทันที เพราะมันพยายามสร้าง Bean ชื่อmyServiceซ้ำกัน - กรณีที่ 2 ( Explicit Resolution ): หากคุณระบุชื่อใน Annotation ต่างกัน เช่น
- คลาส 1:
@Component("serviceInscode") - คลาส 2:
@Component("serviceCbsCenter") - ผลลัพธ์: แม้ชื่อคลาสจะซ้ำ แต่ Bean ID ไม่ซ้ำ Application จะรันได้ปกติ ✅
- คลาส 1:
ตารางเปรียบเทียบความแตกต่าง
| หัวข้อเปรียบเทียบ | Class Name Collision | Bean 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
- ระบุชื่อให้ชัดเจน ( Explicit Naming ): อย่าปล่อยให้ Spring ตั้งชื่ออัตโนมัติหากคลาสนั้นมีโอกาสซ้ำ ให้ระบุชื่อที่สื่อถึง Module เช่น
@Service("inscodeDescriptionClient") - ใช้ @Primary: หากมี Bean ประเภทเดียวกัน 2 ตัว แต่ต้องการให้ตัวหนึ่งเป็นตัวหลักที่ถูกเลือกใช้เสมอ
- ใช้ @Qualifier: ในจุดที่ฉีด Bean (
@Autowired) ให้ระบุชื่อ ID ที่ต้องการเพื่อลดความคลุมเครือ
✅ การจัดการ Class Name Collision ( แม้จะไม่ใช่ Bean )
- Refactor: หากเป็นไปได้ควรเปลี่ยนชื่อคลาสให้สื่อสารชัดเจนขึ้น เช่น
InscodePartnerTOและCbsPartnerTO - Package Organization: จัดกลุ่ม Package ให้แยกขาดตาม Domain ของงาน ( เช่น
inscodevscbscenter)
อ่านเพิ่มเติม