الفصل 1: Annotations Core Spring
1. @SpringBootApplication
التعليمة التوضيحية لبدء التشغيل التي تجمع بين ثلاث تعليمات توضيحية في واحدة.
@SpringBootApplication
public class MonApplication {
public static void main(String[] args) {
SpringApplication.run(MonApplication.class, args);
}
}
ما يعادل:
@SpringBootConfiguration // يشير إلى فئة تكوين
@EnableAutoConfiguration // يُفعّل التكوين التلقائي لـ Spring Boot
@ComponentScan // يفحص المكونات في الحزمة الحالية والحزم الفرعية
2. Annotations de Stéréotype
تحدد هذه التعليمات التوضيحية دور الفئة في البنية.
@Component
تعليمة توضيحية عامة لأي bean في Spring.
@Component
public class EmailValidator {
public boolean isValid(String email) {
return email != null && email.contains("@");
}
}
@Service
تشير إلى فئة منطق الأعمال (طبقة الخدمة).
@Service
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public User findById(Long id) {
return userRepository.findById(id)
.orElseThrow(() -> new RuntimeException("المستخدم غير موجود"));
}
}
@Repository
تشير إلى فئة الوصول إلى البيانات. تُفعّل الترجمة التلقائية لاستثناءات SQL إلى استثناءات Spring.
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByEmail(String email);
}
@Controller
تشير إلى وحدة تحكم MVC (تُرجع مشاهد HTML).
@Controller
public class PageController {
@GetMapping("/accueil")
public String accueil(Model model) {
model.addAttribute("message", "مرحبًا!");
return "accueil"; // يُرجع اسم المشهد (القالب)
}
}
@RestController
مزيج من @Controller + @ResponseBody. تُرجع كل طريقة JSON/XML مباشرة.
@RestController
@RequestMapping("/api/users")
public class UserController {
@GetMapping
public List<User> getAll() {
return userService.findAll(); // يُرجع JSON تلقائيًا
}
}
Résumé des stéréotypes
| Annotation | Couche | Rôle |
|---|---|---|
@Component | عام | أي Bean في Spring |
@Service | خدمة | منطق الأعمال |
@Repository | بيانات | الوصول إلى قاعدة البيانات |
@Controller | ويب | وحدة تحكم MVC (مشاهد) |
@RestController | ويب | وحدة تحكم REST (JSON) |
3. Annotations d'Injection de Dépendances
@Autowired
حقن تلقائي لـ Spring bean.
@Service
public class OrderService {
// حقن عبر المنشئ (موصى به)
private final ProductService productService;
@Autowired // اختياري إذا كان هناك منشئ واحد فقط
public OrderService(ProductService productService) {
this.productService = productService;
}
}
@Service
public class NotificationService {
// حقن عبر الحقل (غير موصى به ولكنه شائع)
@Autowired
private EmailService emailService;
// حقن عبر setter
@Autowired
public void setEmailService(EmailService emailService) {
this.emailService = emailService;
}
}
يفضل دائمًا الحقن عبر المنشئ. يجعل التبعيات واضحة ويسهل الاختبار.
@Qualifier
يحل الالتباسات عندما تقوم عدة beans بتنفيذ نفس الواجهة.
public interface NotificationSender {
void send(String message);
}
@Component("emailSender")
public class EmailNotification implements NotificationSender {
public void send(String message) { /* إرسال البريد الإلكتروني */ }
}
@Component("smsSender")
public class SmsNotification implements NotificationSender {
public void send(String message) { /* إرسال الرسائل القصيرة */ }
}
@Service
public class AlertService {
private final NotificationSender sender;
public AlertService(@Qualifier("emailSender") NotificationSender sender) {
this.sender = sender;
}
}
@Primary
يحدد bean الافتراضي عندما توجد عدة مرشحين.
@Primary
@Component
public class EmailNotification implements NotificationSender {
// سيتم حقن هذا bean افتراضيًا
}
@Value
يحقن القيم من ملفات التكوين.
@Service
public class AppConfig {
@Value("${app.name}")
private String appName;
@Value("${app.max-retry:3}") // القيمة الافتراضية = 3
private int maxRetry;
@Value("${server.port}")
private int port;
@Value("#{2 + 3}") // SpEL (Spring Expression Language)
private int calculated;
}
# application.yml
app:
name: MonApplication
max-retry: 5
server:
port: 8080
@Lazy
يؤخر تهيئة bean حتى يتم استخدامه لأول مرة.
@Service
@Lazy
public class HeavyService {
public HeavyService() {
// لن يتم استدعاء هذا المنشئ إلا عند استخدام bean
}
}
4. Annotations de Configuration
@Configuration
يعلن عن فئة تكوين Spring (ما يعادل XML).
@Configuration
public class AppConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
@Bean
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
return mapper;
}
}
@Bean
يعلن عن bean يُدار بواسطة حاوية Spring. يُستخدم في الفئات @Configuration.
@Configuration
public class SecurityConfig {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public AuthenticationManager authManager(AuthenticationConfiguration config)
throws Exception {
return config.getAuthenticationManager();
}
}
@ConfigurationProperties
يربط مجموعة من الخصائص بكائن Java.
@Configuration
@ConfigurationProperties(prefix = "app.mail")
public class MailProperties {
private String host;
private int port;
private String username;
private String password;
// Getters و setters إلزامية
public String getHost() { return host; }
public void setHost(String host) { this.host = host; }
// ...
}
# application.yml
app:
mail:
host: smtp.gmail.com
port: 587
username: user@gmail.com
password: secret
@PropertySource
يحمّل ملف خصائص إضافي.
@Configuration
@PropertySource("classpath:custom-config.properties")
public class CustomConfig {
@Value("${custom.property}")
private String customProp;
}
@Import
يستورد فئات تكوين أخرى.
@Configuration
@Import({SecurityConfig.class, DatabaseConfig.class})
public class AppConfig {
}
5. Annotations de Scope et Lifecycle
@Scope
يحدد نطاق bean.
@Component
@Scope("prototype") // مثيل جديد في كل حقن
public class ShoppingCart {
private List<Item> items = new ArrayList<>();
}
| Scope | Description |
|---|---|
singleton | مثيل واحد (افتراضي) |
prototype | مثيل جديد في كل طلب |
request | مثيل واحد لكل طلب HTTP |
session | مثيل واحد لكل جلسة HTTP |
application | مثيل واحد لكل ServletContext |
@PostConstruct
ينفذ طريقة بعد حقن جميع التبعيات.
@Service
public class CacheService {
private Map<String, Object> cache;
@PostConstruct
public void init() {
cache = new HashMap<>();
// تحميل البيانات الأولية
}
}
@PreDestroy
ينفذ طريقة قبل تدمير bean.
@Service
public class ConnectionPool {
@PreDestroy
public void cleanup() {
// إغلاق جميع الاتصالات
}
}
6. Annotations de Profil et Conditions
@Profile
يُفعّل bean فقط لبعض ملفات التعريف.
@Configuration
@Profile("dev")
public class DevDatabaseConfig {
@Bean
public DataSource dataSource() {
// H2 في الذاكرة للتطوير
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.build();
}
}
@Configuration
@Profile("prod")
public class ProdDatabaseConfig {
@Bean
public DataSource dataSource() {
// PostgreSQL للإنتاج
HikariDataSource ds = new HikariDataSource();
ds.setJdbcUrl("jdbc:postgresql://localhost:5432/mydb");
return ds;
}
}
# تفعيل ملف شخصي
java -jar app.jar --spring.profiles.active=prod
@ConditionalOnProperty
يُفعّل bean بناءً على قيمة خاصية.
@Configuration
@ConditionalOnProperty(name = "app.feature.email", havingValue = "true")
public class EmailConfig {
@Bean
public EmailService emailService() {
return new SmtpEmailService();
}
}
@ConditionalOnClass
يُفعّل bean إذا كانت فئة موجودة في classpath.
@Configuration
@ConditionalOnClass(name = "org.postgresql.Driver")
public class PostgresConfig {
// يتم تكوينه تلقائيًا إذا كان برنامج تشغيل PostgreSQL متاحًا
}
@ConditionalOnMissingBean
يُفعّل bean فقط إذا لم يكن هناك أي bean آخر من نفس النوع موجود.
@Bean
@ConditionalOnMissingBean
public ObjectMapper objectMapper() {
return new ObjectMapper();
}
7. Annotations Lombok (Bonus)
Lombok يُولّد الكود تلقائيًا عند التجميع.
@Data
يُولّد getters، setters، toString، equals، hashCode.
@Data
public class UserDto {
private Long id;
private String name;
private String email;
}
@Getter / @Setter
@Getter @Setter
public class Product {
private Long id;
private String name;
private BigDecimal price;
}
@NoArgsConstructor / @AllArgsConstructor / @RequiredArgsConstructor
@NoArgsConstructor
@AllArgsConstructor
public class Address {
private String street;
private String city;
private String zipCode;
}
@RequiredArgsConstructor // منشئ للحقل النهائي
@Service
public class UserService {
private final UserRepository userRepository; // يتم حقنه تلقائيًا
private final PasswordEncoder passwordEncoder;
}
@Builder
يُنفّذ نمط Builder.
@Builder
@Data
public class UserDto {
private Long id;
private String name;
private String email;
}
// الاستخدام
UserDto user = UserDto.builder()
.id(1L)
.name("Jean")
.email("jean@example.com")
.build();
@Slf4j
يضيف مسجل SLF4J تلقائيًا.
@Slf4j
@Service
public class PaymentService {
public void processPayment(Payment payment) {
log.info("معالجة الدفع: {}", payment.getId());
log.debug("المبلغ: {}", payment.getAmount());
}
}
Résumé Rapide
| Annotation | Rôle |
|---|---|
@SpringBootApplication | نقطة دخول التطبيق |
@Component | Bean عام |
@Service | طبقة الخدمة (منطق الأعمال) |
@Repository | طبقة البيانات (الوصول إلى قاعدة البيانات) |
@Controller | وحدة تحكم MVC |
@RestController | وحدة تحكم REST |
@Autowired | حقن التبعية |
@Qualifier | اختيار bean للحقن |
@Value | حقن قيمة التكوين |
@Configuration | فئة التكوين |
@Bean | إعلان يدوي عن bean |
@ConfigurationProperties | ربط الخصائص |
@Profile | التفعيل حسب ملف التعريف |
@PostConstruct | التهيئة بعد الحقن |
@PreDestroy | التنظيف قبل التدمير |
➡️ الفصل 2: Annotations Web et REST