مثال تعليمي حول حقن التبعية في Google Guice

جوجل جوس هو الإطار لتلقائي حقن الاعتماد في التطبيقات. إذا كنت قد وصلت هنا مباشرة، فأنا أوصي بفحص مثال حقن الاعتماد حيث تعرفنا على المشاكل مع النهج التقليدي لإنشاء الكائنات وفوائد تنفيذ حقن الاعتماد. في الدرس السابق، تعلمنا كيف يمكننا تنفيذ حقن الاعتماد في التطبيقات يدوياً. ولكن عندما يزداد عدد الفئات في التطبيق، فمن الأفضل البحث عن بعض الأطر لتلقين هذه المهمة تلقائياً. جوجل جوس هو أحد الأطر الرائدة التي تعمل أساساً على توفير تنفيذ تلقائي لحقن الاعتماد. سنعمل على نفس المثال من المنشور السابق ونتعلم كيف يمكننا استخدام جوجل جوس لتلقين عملية التنفيذ لحقن الاعتماد. تعتمد جوجل جوس على التبعيات المتاحة على مركز مافن، لذا لمشاريع المافن يمكنك إضافة التبعية التالية لها.

<dependency>
	<groupId>com.google.inject</groupId>
	<artifactId>guice</artifactId>
	<version>3.0</version>
</dependency>

إذا كان لديك تطبيق جافا بسيط، يمكنك تنزيل ملف جار من صفحة جوجل جوس الرئيسية على Google Code. لاحظ أنه في هذه الحالة ستحتاج أيضاً إلى وجود التبعيات العابرة في مسار الفئة وإلا ستحصل على استثناء في وقت التشغيل. بالنسبة لمثالي، لدي مشروع مافن ويبدو هيكله كما في الصورة أدناه. لنرى كل من العناصر واحداً تلو الآخر.

فئات الخدمة

package com.journaldev.di.services;

public interface MessageService {

	boolean sendMessage(String msg, String receipient);
}

MessageService توفر واجهة العقد الأساسي للخدمات.

package com.journaldev.di.services;

import javax.inject.Singleton;

//import com.google.inject.Singleton;

@Singleton
public class EmailService implements MessageService {

	public boolean sendMessage(String msg, String receipient) {
		//some fancy code to send email
		System.out.println("Email Message sent to "+receipient+" with message="+msg);
		return true;
	}

}

EmailService هو أحد تنفيذات MessageService. لاحظ أن الفئة محددة بالتحديد بالتعليق @Singleton. نظرًا لأن كائنات الخدمة سيتم إنشاؤها من خلال فئات المحقن، يتم توفير هذا التعليق لإعلامهم بأن فئات الخدمة يجب أن تكون كائنات مفردة. أضاف Google Guice 3.0 دعمًا لـ JSR-330 ويمكننا استخدام التعليقات من com.google.inject أو javax.inject. لنفترض أن لدينا تنفيذًا آخر للخدمة لإرسال رسائل Facebook.

package com.journaldev.di.services;

import javax.inject.Singleton;

//import com.google.inject.Singleton;

@Singleton
public class FacebookService implements MessageService {

	public boolean sendMessage(String msg, String receipient) {
		//some complex code to send Facebook message
		System.out.println("Message sent to Facebook user "+receipient+" with message="+msg);
		return true;
	}

}

فئة المستهلك

نظرًا لأننا نقوم بتنفيذ حقن الاعتماد في تطبيقنا، فلن نقوم بتهيئة فئة الخدمة في التطبيق. يدعم Google Guice كل من الحقن القائم على المعيار setter-based و constructor-based. تبدو فئة التطبيق الخاصة بنا التي تستهلك الخدمة على النحو التالي.

package com.journaldev.di.consumer;

import javax.inject.Inject;

//import com.google.inject.Inject;
import com.journaldev.di.services.MessageService;

public class MyApplication {

	private MessageService service;
	
// تضمين الإدخال
//constructor based injector
// تضمين بناء الأجهزة
@Inject
// تضمين
//public MyApplication(MessageService svc){
//		this.service=svc;
//	}
	
	// تطبيقي الخاص
//setter method injector
	@Inject
	public void setService(MessageService svc){
		this.service=svc;
	}
	
	public boolean sendMessage(String msg, String rec){
		// تضمين طريقة المعالج
//some business logic here
		return service.sendMessage(msg, rec);
	}
}

بعض المنطق التجاري هنا
لاحظ أنني قمت بتعليق الشفرة للحقن القائم على المنشئ ، هذا يأتي بمساعدة عندما يوفر تطبيقك بعض الميزات الأخرى التي لا تحتاج إلى كائن فئة الخدمة. لاحظ أيضًا الشرح @Injector ، سيتم استخدامه بواسطة Google Guice لحقن فئة تنفيذ الخدمة. إذا لم تكن على دراية بالتوجيهات ، تحقق من تعليمات الوسوم جافا.

تقديم تنفيذ الخدمة

من الواضح أن جوجل جويس لن يعرف أي خدمة يجب استخدامها ، يجب علينا تكوينها عن طريق توسيع AbstractModule الفصيلة المجردة وتوفير تنفيذ ل configure() الأسلوب.

package com.journaldev.di.injector;

import com.google.inject.AbstractModule;
import com.journaldev.di.services.EmailService;
import com.journaldev.di.services.FacebookService;
import com.journaldev.di.services.MessageService;

public class AppInjector extends AbstractModule {

	@Override
	protected void configure() {
		// ربط الخدمة بفئة التنفيذ
		//bind(MessageService.class).to(EmailService.class);
		
		// ربط خدمة الرسائل بتنفيذ رسالة فيسبوك
		bind(MessageService.class).to(FacebookService.class);
		
	}

}

كما يمكنكم ملاحظة أنه يمكننا ربط أي من التنفيذات بفئة الخدمة. على سبيل المثال، إذا أردنا التغيير إلى EmailService، فإنه يكفي فقط تغيير الربط.

تطبيق العميل

إعدادنا جاهز، لنر كيفية استخدامه مع فئة جافا بسيطة.

package com.journaldev.di.test;

import com.google.inject.Guice;
import com.google.inject.Injector;

import com.journaldev.di.consumer.MyApplication;
import com.journaldev.di.injector.AppInjector;

public class ClientApplication {

	public static void main(String[] args) {
		Injector injector = Guice.createInjector(new AppInjector());		
		
		MyApplication app = injector.getInstance(MyApplication.class);
		
		app.sendMessage("Hi Pankaj", "[email protected]");
	}

}

التنفيذ سهل للغاية للفهم. نحتاج إلى إنشاء كائن Injector باستخدام طريقة createInjector() في فئة Guice حيث نمرر كائن تنفيذ فئتنا إلى المصدر. ثم نستخدم المصدر لتهيئة فئتنا المستهلكة. إذا قمنا بتشغيل الفئة أعلاه، ستنتج الناتج التالي.

Message sent to Facebook user [email protected] with message=Hi Pankaj

إذا قمنا بتغيير الروابط إلى EmailService في فئة AppInjector، فسينتج الناتج التالي.

Email Message sent to [email protected] with message=Hi Pankaj

حالات اختبار JUnit

نظرًا لأننا نريد اختبار فئة MyApplication، فليس من الضروري إنشاء تنفيذ فعلي للخدمة. يمكننا أن نملك فئة تنفيذ خدمة بسيطة كما هو موضح أدناه.

package com.journaldev.di.services;

public class MockMessageService implements MessageService{

	public boolean sendMessage(String msg, String receipient) {
		return true;
	}

}

فئتي اختبار JUnit 4 تبدو كما يلي.

package com.journaldev.di.test;


import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.journaldev.di.consumer.MyApplication;
import com.journaldev.di.services.MessageService;
import com.journaldev.di.services.MockMessageService;

public class MyApplicationTest {

	private Injector injector;
	
	@Before
	public void setUp() throws Exception {
		injector = Guice.createInjector(new AbstractModule() {
			
			@Override
			protected void configure() {
				bind(MessageService.class).to(MockMessageService.class);
			}
		});
	}

	@After
	public void tearDown() throws Exception {
		injector = null;
	}

	@Test
	public void test() {
		MyApplication appTest = injector.getInstance(MyApplication.class);
		Assert.assertEquals(true, appTest.sendMessage("Hi Pankaj", "[email protected]"));;
	}

}

لاحظ أنني أقوم بربط فئة MockMessageService بـ MessageService من خلال وجود تنفيذ لفئة الفئة المجهولة لـ AbstractModule. يتم ذلك في طريقة setUp() التي تعمل قبل طرق الاختبار.

تنزيل مشروع Google Guice

هذا كل شيء بالنسبة لبرنامج تعليمي عن مثال Google Guice. استخدام Google Guice لتنفيذ حقن الاعتماد في التطبيق سهل للغاية ويتم ذلك بشكل جميل. يتم استخدامه في واجهات برمجة التطبيقات الخاصة بـ Google لذا يمكننا أن نفترض أنها تحتوي على رمز موثوق وموثوق به للغاية. قم بتنزيل المشروع من الأعلى وقم بتجربته لتعلم المزيد.

Source:
https://www.digitalocean.com/community/tutorials/google-guice-dependency-injection-example-tutorial