Creating Bean with @Component, @Servic and @Repository
توضیحات جلسه
جزوه و مستندات
مفاهیم کلیدی
- Spring Bean
شیئی است که توسط کانتینر IoC در Spring نمونهسازی، پیکربندی، مدیریت و در طول چرخه حیات برنامه نگهداری میشود.
- Stereotype Annotations
انوتیشنهای سطح کلاسی شامل @Component، @Service، @Repository و @Controller که نقش و وظیفه معماری کلاس را در لایهبندی برنامه برای کانتینر Spring مشخص میکنند.
@Component
انوتیشن پایه و عمومی از نوع Stereotype که کلاس را بهعنوان یک Spring Bean معرفی میکند تا توسط فرآیند Component Scanning شناسایی و رجیستر شود.
@Service
فرم تخصصییافته از انوتیشن @Component که برای لایه منطق تجاری (Business Logic) و پیادهسازی سرویسها و تراکنشها استفاده میشود و معنای لایهای واضحتری به کد میدهد.
@Repository
فرم تخصصییافته از انوتیشن @Component برای لایه دسترسی به داده (Data Access Layer یا DAO) که علاوه بر ثبت bean، خطاهای دسترسی به داده مربوط به پلتفرم را به سلسلهمراتب خطای یکپارچه DataAccessException در Spring ترجمه میکند (Exception Translation).
- Component Scanning
مکانیزمی در Spring که پکیجهای مشخصشده را برای کشف خودکار کلاسهای دارای انوتیشنهای Stereotype اسکن کرده و آنها را در ApplicationContext ثبت میکند.
- Separation of Concerns (SoC)
یک اصل معماری که بر اساس آن سیستم به لایههای مجزا با وظایف مشخص (مانند لایه وب، منطق تجاری و دسترسی به پایگاهداده) تقسیم میشود.
موارد مصاحبه ای
- توسعه برنامه جاوا بدون سیستم مدیریت Bean توسط فریمورک با چه چالشهایی مواجه است؟
ایجاد Tight Coupling به دلیل مدیریت دستی نمونهسازی با کلمه کلیدی new، دشواری در تستپذیری (Unit Testing)، عدم مدیریت متمرکز چرخه حیات اشیاء و نقض اصل Inversion of Control.
- تفاوت فنی انوتیشن
@Componentبا@Serviceو@Repositoryچیست؟
از لحاظ ساختاری، هر دو انوتیشن @Service و @Repository با @Component مشتق شدهاند؛ اما @Repository مکانیزم خودکار Exception Translation را برای خطاهای دیتابیس فعال میکند و @Service از لحاظ مفهومی نشاندهنده لایه تجاری برنامه است و پردازشهای تجاری مانند @Transactional روی آن قرار میگیرد.
- قابلیت Exception Translation در انوتیشن
@Repositoryچگونه کار میکند؟
این انوتیشن خطاهای بومی پایگاهداده (مانند خطاهای SQLException یا کدهای خطای Hibernate) را گرفته و آنها را به خطاهای کنترلشده و ساختاریافته فریمورک Spring تحت زیرمجموعه DataAccessException تبدیل میکند تا لایه سرویس به دیتابیس خاصی وابسته نباشد.
- اگر به جای
@Serviceیا@Repositoryاز@Componentاستفاده کنیم چه اتفاقی میافتد؟
برنامه از نظر کانتینر IoC کار میکند و کلاس بهعنوان bean شناخته میشود، اما قابلیتهای اختصاصی مثل مدیریت خطاهای دیتابیس در لایه دسترسی به داده اعمال نمیشود و ساختار معماری لایهبندی تمیز برنامه آسیب میبیند.
- آیا استفاده از
@Serviceعملکرد متفاوتی در اسکن کامپوننتها نسبت به@Componentدارد؟
خیر، فرآیند Component Scanning هر دو را به یک شکل اسکن و نمونهسازی میکند، زیرا @Service در تعریف درونی خود دارای انوتیشن @Component است.
سناریو کاربردی
- پیادهسازی لایهبندی استاندارد Enterprise با تفکیک وظایف Beanها
در یک ساختار لایهای استاندارد، وظایف به شکل زیر بین انوتیشنها تقسیم میشوند:
۱. لایه دسترسی به داده (Repository):
@Repository
public class UserRepository {
public User findById(Long id) {
// عملیات واکشی از پایگاهداده با ترجمه خودکار خطاهای دیتابیس
return new User(id, "farzad");
}
}
۲. لایه منطق تجاری (Service):
@Service
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public User getUserProfile(Long id) {
// اعمال قوانین تجاری و اعتبارسنجی
return userRepository.findById(id);
}
}
۳. کلاسهای کمکی و ماژولهای عمومی (Component):
@Component
public class EmailNotificationSender {
public void sendWelcomeEmail(String email) {
// ارسال ایمیل یا عملیات مستقل عمومی خارج از لایههای وب و بیزینس
}
}
با این ساختار، هر کلاس وظیفه دقیق خود را دارد، تستپذیری به بالاترین حد میرسد و لایهها بهصورت Loose Coupling با تزریق وابستگی به یکدیگر متصل میشوند.
بیشتر بدانید
- بهترین روش تزریق وابستگی بین این لایهها
استفاده از Constructor Injection به همراه متغیرهای final به جای استفاده از فیلد @Autowired توصیه میشود تا کلاسها immutable و تستپذیر باقی بمانند.
- ترتیب قرارگیری لایهها در جریان داده
جریان داده همواره از سمت لایه کنترلر به سمت @Service و از لایه سرویس به سمت @Repository است؛ لایه دیتابیس هرگز نباید مستقیماً توسط کنترلر صدا زده شود.
- تکامل معماری و ماژولار بودن
استفاده از انوتیشنهای لایهای مناسب به ابزارهای مانیتورینگ، ابزارهای تحلیل کدهای استاتیک و جنبههای AOP این امکان را میدهد که رفتارهای خاص هر لایه (مانند لاگین یا متریکهای تراکنش) را بهصورت اختصاصی رصد کنند.
