Автор оригинала: Pankaj Kumar.
Google Guice – это платформа для автоматизации внедрения зависимостей в приложения. Если вы столкнулись непосредственно здесь, я бы рекомендовал вам проверить Пример внедрения зависимостей , где мы узнали о проблемах с традиционным подходом к созданию объектов и преимуществах внедрения зависимостей.
В последнем уроке мы узнали, как можно внедрить внедрение зависимостей в приложения вручную. Но когда количество классов в приложении растет, лучше поискать какой-нибудь фреймворк для автоматизации этой задачи.
Google Guice-одна из ведущих платформ, основная работа которой заключается в обеспечении автоматической реализации внедрения зависимостей. Мы рассмотрим тот же пример из предыдущего поста и узнаем, как мы можем использовать Google Guice для автоматизации процесса внедрения внедрения зависимостей.
Зависимости Google Guice доступны в maven central, поэтому для проектов maven вы можете добавить для него зависимость ниже.
com.google.inject guice 3.0
Если у вас есть простое java-приложение, вы можете загрузить файл jar с домашней страницы Google Guice в Google Code. Обратите внимание, что в этом случае вам также потребуется указать переходные зависимости в пути к классу, иначе вы получите исключение во время выполнения.
Для моего примера у меня есть проект maven, структура проекта которого выглядит следующим образом.
Давайте рассмотрим каждый из компонентов по очереди.
Классы обслуживания
package com.journaldev.di.services; public interface MessageService { boolean sendMessage(String msg, String receipient); }
Служба сообщений
интерфейс предоставляет базовый контракт на услуги.
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; } }
Служба электронной почты
является одной из реализаций Службы сообщений
. Обратите внимание, что класс аннотирован аннотацией @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 поддерживает как на основе установщика
, так и на основе конструктора
внедрение зависимостей. Наш класс приложений, использующий сервис, выглядит следующим образом.
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 для внедрения класса реализации сервиса. Если вы не знакомы с аннотациями, ознакомьтесь с учебником по аннотациям java .
Внедрение службы привязки
Очевидно, что 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 the service to implementation class //bind(MessageService.class).to(EmailService.class); //bind MessageService to Facebook Message implementation bind(MessageService.class).to(FacebookService.class); } }
Как вы можете видеть, мы можем привязать любую реализацию к классу обслуживания. Например, если мы хотим перейти на службу электронной почты, нам просто нужно будет изменить привязки.
Клиентское приложение
Наша настройка готова, давайте посмотрим, как ее использовать с простым классом java.
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", "pankaj@abc.com"); } }
Реализация очень проста для понимания. Нам нужно создать Инжектор
объект, использующий метод класса Guice createInjector (), в котором мы передаем наш объект реализации класса инжектора. Затем мы используем инжектор для инициализации нашего потребительского класса. Если мы запустим выше класса, он выдаст следующий результат.
Message sent to Facebook user pankaj@abc.com with message=Hi Pankaj
Если мы изменим привязки к Почтовой службе
в Инжекторе приложений
классе, то он выдаст следующий вывод.
Email Message sent to pankaj@abc.com with message=Hi Pankaj
Тестовые случаи JUnit
Поскольку мы хотим протестировать мой класс приложений, нам не требуется создавать фактическую реализацию службы. У нас может быть простой класс реализации макетной службы, как показано ниже.
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", "pankaj@abc.com"));; } }
Обратите внимание, что я привязываю MockMessageService
класс к Службе сообщений
, используя анонимный класс реализацию Абстрактного модуля
. Это делается в методе setUp ()
, который выполняется перед методами тестирования.
Это все для примера учебника Google Guice. Использование Google Guice для внедрения внедрения зависимостей в приложение очень просто и делает это красиво. Он используется в API Google, поэтому мы можем предположить, что это хорошо протестированный и надежный код. Загрузите проект сверху и поиграйте с ним, чтобы узнать больше.