حقن التبعية في Java: من الألف إلى الياء عمليًا

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

حقن التبعية في Java: عمليًا

\n\n

حقن التبعية (Dependency Injection - DI) هو أحد المبادئ الأساسية في التطوير الحديث بلغة Java، ويشكل أساس أطر العمل مثل Spring و Jakarta EE. في هذه المقالة، سنشرح ما هو حقن التبعية، ولماذا هو مهم، والأهم من ذلك، كيفية تطبيقه عمليًا مع أمثلة الكود.

\n\n

ما هو حقن التبعية ولماذا هو مهم؟

\n\n

حقن التبعية هو نمط تصميم يتم فيه توفير التبعيات للكائن من الخارج، بدلاً من أن يقوم الكائن بإنشائها بنفسه. هذا يحقق مبدأ انعكاس التحكم (Inversion of Control - IoC). بدلاً من أن تدير الفئة تبعياتها بنفسها، يتم نقل التحكم إلى حاوية خارجية أو مصنع.

\n\n

تخيل أنك تكتب تطبيقًا لإرسال الإشعارات. بدون DI، قد يبدو الكود الخاص بك كالتالي:

\n\n
public class NotificationService {\n    private EmailSender emailSender = new EmailSender();\n\n    public void send(String message) {\n        emailSender.send(message);\n    }\n}
\n\n

المشكلة واضحة: NotificationService مرتبط بشكل صارم بـ EmailSender. إذا أردت إضافة إشعارات SMS أو Push، فسيتعين عليك إعادة كتابة الفئة بأكملها. مع حقن التبعية، يتم حل هذه المشكلة:

\n\n
public class NotificationService {\n    private final MessageSender messageSender;\n\n    // يتم تمرير التبعية عبر المُنشئ\n    public NotificationService(MessageSender messageSender) {\n        this.messageSender = messageSender;\n    }\n\n    public void send(String message) {\n        messageSender.send(message);\n    }\n}
\n\n

الآن تعتمد الفئة على التجريد MessageSender، وليس على تنفيذ محدد. هذا يجعل الكود مرنًا وقابلًا للاختبار وقابلًا للتوسع.

\n\n

طرق حقن التبعية في Java

\n\n

هناك ثلاث طرق رئيسية لتنفيذ DI في Java. دعنا نستعرض كل منها مع أمثلة.

\n\n

1. الحقن عبر المُنشئ (Constructor Injection)

\n\n

هذه هي الطريقة الأكثر تفضيلاً. يتم تمرير التبعيات عبر معاملات المُنشئ وعادةً ما يتم تعليمها كـ final.

\n\n
public class UserService {\n    private final UserRepository userRepository;\n    private final EmailService emailService;\n\n    public UserService(UserRepository userRepository, EmailService emailService) {\n        this.userRepository = userRepository;\n        this.emailService = emailService;\n    }\n\n    public void registerUser(User user) {\n        userRepository.save(user);\n        emailService.sendWelcomeEmail(user.getEmail());\n    }\n}
\n\n

المزايا:

\n
    \n
  • التبعيات الإلزامية واضحة بشكل صريح
  • \n
  • الكائن دائمًا في حالة صالحة
  • \n
  • مناسب جدًا للكائنات غير القابلة للتغيير (immutable)
  • \n
  • سهولة الاختبار —只需 تمرير كائنات وهمية (mock)
  • \n
\n\n

2. الحقن عبر الضابط (Setter Injection)

\n\n

يتم تعيين التبعيات عبر طرق الضابط (setter) بعد إنشاء الكائن.

\n\n
public class OrderService {\n    private PaymentGateway paymentGateway;\n\n    public void setPaymentGateway(PaymentGateway paymentGateway) {\n        this.paymentGateway = paymentGateway;\n    }\n\n    public void processOrder(Order order) {\n        paymentGateway.charge(order.getTotal());\n    }\n}
\n\n

متى تستخدم: للتبعيات الاختيارية أو عندما يمكن أن تتغير التبعيات خلال عمر الكائن. ومع ذلك، هذه الطريقة تجعل الكائن قابلًا للتغيير وأقل قابلية للتنبؤ.

\n\n

3. الحقن عبر الحقل (Field Injection)

\n\n

غالبًا ما يُستخدم مع أطر العمل من خلال التعليقات التوضيحية، مثل @Autowired في Spring.

\n\n
public class ReportService {\n    @Autowired\n    private DataSource dataSource;\n\n    public Report generateReport() {\n        return dataSource                

المدونات

توصيات الكتب