Dependency Injection в Javaна примере эволюцииSpring – Guice – CDI/WeldСергей КошельВедущий разработчик Java23 мая 2013 года
Разрабатываем адаптерПреобразование2/36
Первая версияSimpleConverterFileSource DatabaseStorageAdapter3/36
Первая версия+ Работать будет− Невозможно написать unit-тестpublic class Adapter {public void processMessage() {final File...
Выделяем интерфейсыMockConverterMockSource MockStorageFileSourceSimpleConverterDatabaseStorageSourceConverterStorageAdapte...
И добавляем фабрикиpublic class Adapter {public void processMessage() {final Source source = SourceFactory.getSource();fin...
Пишем тест@Testpublic void processMessage() throws Exception {SourceFactory.setSource(new MockSource("Hello from test!"));...
Избавляемся от фабрикpublic class Adapter {private Source source;private Converter converter;private Storage storage;publi...
Переписываем тест@Testpublic void processMessage() throws Exception {final Adapter adapter = new Adapter();adapter.setSour...
Последний штрихpublic class Adapter {private final Source source;private final Converter converter;private final Storage s...
Dependency Injection (DI) Паттерн проектирования (design pattern) О компонентах и их зависимостях Позволяет отделить об...
Причем тут тесты? Тесты не самоцель, но… С одной стороны, практически,DI позволяет проще писатьтестопригодный код А с д...
Можно было пойти другим путемpublic class Adapter {public void processMessage() {final Source source = UniversalFactory.ge...
Паттерны DI и SLчасто противопоставляютсяDI зависимости определяет статически Проще разобраться в связях Компилятор мног...
IoC-контейнерАвтоматизирует DI Разрешает граф зависимостей Конструирует компоненты по метаописаниюзависимостейИ привноси...
DisclaimerАвтор не в коем случае не имеетцели принизить один фреймворкза счет другого16/36
Spring Framework17/36
Описываем зависимости<?xml version="1.0" encoding="UTF-8"?><beans …><bean id="adapter" class="custis.seminars.diinjava.spr...
Запускаем контейнерfinal ApplicationContext applicationContext= new ClassPathXmlApplicationContext("spring-config.xml");ad...
Autowiring<bean id="adapter" class="custis.seminars.diinjava.autowiring.Adapter"autowire="byType" />20/36
Lifecycle Management singleton – создается один экземпляр prototype – создается отдельный экземплярпри каждом обращении<...
Метаданные в компоненте@Scope(SCOPE_SINGLETON)public class Adapter {private Source source;private Converter converter;priv...
Выбормежду несколькими реализациями23/36<bean id="source" class="custis.seminars.diinjava.autowiring.FileSource" />@Autowi...
Google Guice24/36
Pure Java configpublic class AdapterModule extends AbstractModule {@Overrideprotected void configure() {bind(SimpleConvert...
Annotation based@Singletonpublic class Adapter {private final Source source;private final Converter converter;private fina...
Pure Java configpublic class AdapterModule extends AbstractModule {@Overrideprotected void configure() {…}@ProvidesSource ...
Provider interfacepublic interface Provider <T> {T get();}bind(Validator.class).to(SimpleValidator.class);public class Ada...
Provider interfaceКогда нужно… отложить создание (тяжелое, условное) много экземпляров (the new «new») вложить более уз...
Выбормежду несколькими реализациями30/36@BindingAnnotation@Target({ FIELD, PARAMETER, METHOD }) @Retention(RUNTIME)public ...
CDI/WeldJSR 299: Contexts and Dependency Injectionfor the Java EE platformWeld – reference implementationfor JSR-29931/36
CDI Конфигурация похожа на Guice Нет DSL — используется @Produceи сканирование classpath Стандартизирует @Inject, @Seng...
Instance – Provider на стероидах Расширяет возможности ProviderInstance<T> extends Provider<T> …опциональные зависимости...
Event<T>public class Adapter {@InjectEvent<AdapterStarted> adapterStartedEvent;@PostConstructpublic void init() {adapterSt...
О чем не рассказал AOP и method intercepting Генерализованные типы зависимостей Многозначные зависимости Scopes …35/36
Спасибо!Вопросы?Сергей Кошельskoshel@custis.ru36/36
Upcoming SlideShare
Loading in …5
×

Dependency Injection в Java на примере эволюции Spring — Guice — CDI/Weld

1,029 views

Published on

Открытый семинар для студентов в компании CUSTIS (23 мая 2013 года).

Лектор: Сергей Кошель, ведущий разработчик Java, аналитик.

Аннотация: Из этого семинара вы узнаете о практическом применении паттерна Dependency Injection в мире Java и предоставляемых им возможностях на примере развития DI-фреймворков: от Spring и Guice до CDI/Weld. Формат встречи – динамичный с элементами Live Coding и демонстрацией особенностей реализации.

Видеозапись семинара: https://vimeo.com/67125102.

Published in: Education
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
1,029
On SlideShare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
7
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Dependency Injection в Java на примере эволюции Spring — Guice — CDI/Weld

  1. 1. Dependency Injection в Javaна примере эволюцииSpring – Guice – CDI/WeldСергей КошельВедущий разработчик Java23 мая 2013 года
  2. 2. Разрабатываем адаптерПреобразование2/36
  3. 3. Первая версияSimpleConverterFileSource DatabaseStorageAdapter3/36
  4. 4. Первая версия+ Работать будет− Невозможно написать unit-тестpublic class Adapter {public void processMessage() {final FileSource fileSource = new FileSource();final SimpleConverter simpleConverter = new SimpleConverter();final DatabaseStorage databaseStorage = new DatabaseStorage();final Message inputMessage = fileSource.getMessage();final Message convertedMessage = simpleConverter.convert(inputMessage);databaseStorage.store(convertedMessage);}}4/36
  5. 5. Выделяем интерфейсыMockConverterMockSource MockStorageFileSourceSimpleConverterDatabaseStorageSourceConverterStorageAdapter 5/36
  6. 6. И добавляем фабрикиpublic class Adapter {public void processMessage() {final Source source = SourceFactory.getSource();final Converter converter = ConverterFactory.getConverter();final Storage storage = StorageFactory.getStorage();final Message inputMessage = source.getMessage();final Message convertedMessage = converter.convert(inputMessage);storage.store(convertedMessage);}}6/36
  7. 7. Пишем тест@Testpublic void processMessage() throws Exception {SourceFactory.setSource(new MockSource("Hello from test!"));StorageFactory.setStorage(new MockStorage());final Adapter adapter = new Adapter();adapter.processMessage();// assert that...}+ Получилось написать тест− Статический (глобальный) контекст− Много бойлерплейта− Зависимости неочевидны7/36
  8. 8. Избавляемся от фабрикpublic class Adapter {private Source source;private Converter converter;private Storage storage;public void setSource(Source source) {…}public void setConverter(Converter converter) {…}public void setStorage(Storage storage) {…}public void processMessage() {final Message inputMessage = source.getMessage();final Message convertedMessage = converter.convert(inputMessage);storage.store(convertedMessage);}}8/36
  9. 9. Переписываем тест@Testpublic void processMessage() throws Exception {final Adapter adapter = new Adapter();adapter.setSource(new MockSource("Hello from test!"));adapter.setConverter(new SimpleConverter());adapter.setStorage(new MockStorage());adapter.processMessage();// assert that...}+ Получилось:Setter based Dependency Injection by Hand9/36
  10. 10. Последний штрихpublic class Adapter {private final Source source;private final Converter converter;private final Storage storage;public Adapter(Source source, Converter converter, Storage storage) {this.source = source;this.converter = converter;this.storage = storage;}public void processMessage() {…}}10/36
  11. 11. Dependency Injection (DI) Паттерн проектирования (design pattern) О компонентах и их зависимостях Позволяет отделить объявлениезависимости от разрешения зависимости(и в пространстве, и во времени) Является частью более общего принципаInversion of Control (Hollywood principle –«Dont call us, well call you».)11/36
  12. 12. Причем тут тесты? Тесты не самоцель, но… С одной стороны, практически,DI позволяет проще писатьтестопригодный код А с другой стороны, концептуально,тесторигодность кода являетсяиндикатором хорошей слабосвязаннойархитектуры (loose coupling) В конечном итоге DI помогает удобнееписать слабосвязный код12/36
  13. 13. Можно было пойти другим путемpublic class Adapter {public void processMessage() {final Source source = UniversalFactory.get("source", Source.class);final Converter converter = UniversalFactory.get("converter",Converter.class);final Storage storage = UniversalFactory.get("storage", Storage.class);final Message inputMessage = source.getMessage();final Message convertedMessage = converter.convert(inputMessage);storage.store(convertedMessage);}}+ Получилось: Service Locator13/36
  14. 14. Паттерны DI и SLчасто противопоставляютсяDI зависимости определяет статически Проще разобраться в связях Компилятор многое может проверитьи подсказать Но иногда это является ограничениемSL – динамически Взаимосвязи запутаны, проще ошибиться Но иногда без этого не обойтись14/36
  15. 15. IoC-контейнерАвтоматизирует DI Разрешает граф зависимостей Конструирует компоненты по метаописаниюзависимостейИ привносит еще много полезностей Управление жизненным циклом Управление конфигурацией AOP …15/36
  16. 16. DisclaimerАвтор не в коем случае не имеетцели принизить один фреймворкза счет другого16/36
  17. 17. Spring Framework17/36
  18. 18. Описываем зависимости<?xml version="1.0" encoding="UTF-8"?><beans …><bean id="adapter" class="custis.seminars.diinjava.spring.Adapter" ><property name="source" ref="source"/><property name="converter" ref="converter"/><property name="storage" ref="storage"/></bean><bean id="source" class="custis.seminars.diinjava.spring.FileSource" /><bean id="converter" class="custis.seminars.diinjava.spring.SimpleConverter"/><bean id="storage" class="custis.seminars.diinjava.spring.DatabaseStorage"/></beans>* Похоже на императив, но это декларатив18/36
  19. 19. Запускаем контейнерfinal ApplicationContext applicationContext= new ClassPathXmlApplicationContext("spring-config.xml");adapter = applicationContext.getBean("adapter", Adapter.class);+ Код адаптера не изменился+ …нет зависимости от Spring’а+ …не надо его писать в каком-либоспециальном стиле19/36
  20. 20. Autowiring<bean id="adapter" class="custis.seminars.diinjava.autowiring.Adapter"autowire="byType" />20/36
  21. 21. Lifecycle Management singleton – создается один экземпляр prototype – создается отдельный экземплярпри каждом обращении<bean id="adapter" class="custis.seminars.diinjava.autowiring.Adapter"autowire="byType"scope="singleton"init-method="init"destroy-method="close" />[…]applicationContext.destroy();21/36
  22. 22. Метаданные в компоненте@Scope(SCOPE_SINGLETON)public class Adapter {private Source source;private Converter converter;private Storage storage;@Autowiredpublic void setSource(Source source) {…}@Autowiredpublic void setConverter(Converter converter) {…}@Autowired(required = false)public void setStorage(Storage storage) {…}@PostConstructpublic void init() {…}@PreDestroypublic void close() {…}} 22/36
  23. 23. Выбормежду несколькими реализациями23/36<bean id="source" class="custis.seminars.diinjava.autowiring.FileSource" />@Autowired@Qualifier("source")public void setSource(Source source) {…}− Легко ошибиться, и проявится это только в рантайме
  24. 24. Google Guice24/36
  25. 25. Pure Java configpublic class AdapterModule extends AbstractModule {@Overrideprotected void configure() {bind(SimpleConverter.class);bind(Source.class).to(FileSource.class);bind(Storage.class).toInstance(new DatabaseStorage());}}final Injector injector = Guice.createInjector(new AdapterModule());adapter = injector.getInstance(Adapter.class);25/36
  26. 26. Annotation based@Singletonpublic class Adapter {private final Source source;private final Converter converter;private final Storage storage;@Injectpublic Adapter(Source source, Converter converter, Storage storage) {this.source = source;this.converter = converter;this.storage = storage;}public void processMessage() {…}}* Зависимость от аннотаций, но они стандартные26/36
  27. 27. Pure Java configpublic class AdapterModule extends AbstractModule {@Overrideprotected void configure() {…}@ProvidesSource fileSource() {return new FileSource();}}* В Spring 3.0 появился JavaConfig27/36
  28. 28. Provider interfacepublic interface Provider <T> {T get();}bind(Validator.class).to(SimpleValidator.class);public class Adapter {private Provider<Validator> validator;@Injectpublic void setValidator(Provider<Validator> validator) {…}public void processMessage() {...validator.get().validate(inputMessage);...}}28/36
  29. 29. Provider interfaceКогда нужно… отложить создание (тяжелое, условное) много экземпляров (the new «new») вложить более узкий скоуп в широкий29/36
  30. 30. Выбормежду несколькими реализациями30/36@BindingAnnotation@Target({ FIELD, PARAMETER, METHOD }) @Retention(RUNTIME)public @interface FileBased {}@Injectpublic Adapter(@FileBased Source source, Converter converter, Storage storage) {…}bind(Source.class).annotatedWith(FileBased.class).to(FileSource.class);+ Typesafe – компилятор проверит
  31. 31. CDI/WeldJSR 299: Contexts and Dependency Injectionfor the Java EE platformWeld – reference implementationfor JSR-29931/36
  32. 32. CDI Конфигурация похожа на Guice Нет DSL — используется @Produceи сканирование classpath Стандартизирует @Inject, @Sengleton,Provider<T> и т. д. Тесно интегрируется с EJB-контейнером32/36
  33. 33. Instance – Provider на стероидах Расширяет возможности ProviderInstance<T> extends Provider<T> …опциональные зависимостиif (instance.isUnsatisfied()) {…} …многозначные зависимостиif (instance.isAmbiguous()) {for (T t : instance) {...}} …динамическое разрешение зависимостей (SL)adapter = instance.select(Adapter.class).get();33/36
  34. 34. Event<T>public class Adapter {@InjectEvent<AdapterStarted> adapterStartedEvent;@PostConstructpublic void init() {adapterStartedEvent.fire(new AdapterStarted());}}public class AnyOtherManagedBean{public void onAdapterStart(@Observes AdapterStarted adapterStarted) {…}}34/36
  35. 35. О чем не рассказал AOP и method intercepting Генерализованные типы зависимостей Многозначные зависимости Scopes …35/36
  36. 36. Спасибо!Вопросы?Сергей Кошельskoshel@custis.ru36/36

×