Pobierz
Transkrypt
Pobierz
Kontenery IoC dla Java Guice 3.0 20 maja 2014 Kamil Piętak [email protected] Agenda Przegląd implementacji kontenerów IoC Guice 3.0 Wprowadzenie – pierwsze kroki Definicja zależności Rodzaje wiązań (ang. bindings) Kontrola instancjonowania Copyright © 2014 IISG Implementacje kontenerów IoC Źródło: http://picocontainer.org/inversion-of-control-history.html Copyright © 2014 IISG Implementacje kontenerów IoC Spring Wszystkie sposoby wstrzykiwania – zalecane wstrzykiwanie przez metody typu „set” – jednostką składania są bean’y Konfiguracja kontenera za pomocą pliku XML (w nowszych wersja możliwe jest wykorzystanie adnotacji) Zasięgi prototype i singleton (jedna instancja w obrębie kontenera, a nie całego systemu!); dedykowane zasięgi dla aplikacji webowych (request, session, global session) Aktualnie – rozbudowany framework wspomagający tworzenie aplikacji Copyright © 2014 IISG Implementacje kontenerów IoC PicoContainer Wszystkie sposoby wstrzykiwania – zalecane wstrzykiwanie przez konstruktor Konfiguracja kontenera za pomocą API; projekt PicoContainer Script – odczyt konfiguracji z zewnętrznych formatów Zasięgi prototype, cached (odpowiednik zasięgu singleton), thread-cached; dedykowane zasięgi dla aplikacji webowych Prace nad wersją 3.0, projekt wygląda na nieaktywny Copyright © 2014 IISG Implementacje kontenerów IoC Guice Wszystkie sposoby wstrzykiwania – w każdym przypadku wymagane adnotacje Konfiguracja kontenera za pomocą fluent API – moduły konfiguracyjne Zasięgi prototype, singleton; dedykowane zasięgi dla aplikacji webowych; możliwość tworzenia własnych zasięgów Nacisk na sprawdzanie zgodności typów Prace nad wersją 4.0, zgodną z Java 8. Copyright © 2014 IISG Tendencja rozwoju bibliotek IoC Kontener IoC jako element większych środowisk wspomagających tworzenie aplikacji Spring Framework Eclipse RCP 4.x Copyright © 2014 IISG Guice 3.0 Pierwsze kroki Przykład Copyright © 2014 IISG Manulane składanie zależności class Starter { public Starter() { IPM pm = new DatabasePersistenceManager(); this.invCatalogue = new InvoicesCatalogue(pm); } } Copyright © 2014 IISG Metoda fabryczna class Starter { public Starter() { this.invCatalogue = Factory.getInvCatalogue(); } } class Factory { public InvoicesCatalogue getInvCatalogue() { return new InvoicesCatalogue(new DatabasePM()); } } Copyright © 2014 IISG Odwrócenie sterowania class Starter { public Starter() { this.invCatalogue = IoC.getInstance( InvoicesCatalogue.class); } } class InvoicesCatalogue { @Inject public InvoicesCatalogue(IPersistenceManager pm) { this.pm = pm; } } Copyright © 2014 IISG Pierwsze kroki Kontener IoC (Injector) tworzy obiekt InvoicesCatalogue wraz z wymaganymi zależnościami InvoicesCatalogue DatabasePersistenceManager Konfiguracja Konfiguracja Injector Działający katalog z wypełnioną listą faktur Copyright © 2014 IISG Pierwsze kroki 1) Definicja zależności public class InvoicesCatalogue { private IPersistenceManager manager; Adnotacja konstruktora wskazujaca ze konstruktor moze byc wykorzystany przez kontener IoC do tworzenia obiektu @Inject public InvoicesCatalogue(IPersistenceManager manager) { this.manager = manager; ... } ... } Copyright © 2014 IISG Pierwsze kroki 2) Konfiguracja kontenera IoC – Moduł (ang. module) Opisuje sposób składania aplikacji Wskazuje typy lub obiekty, które mają być Rozszerzamy „wstrzykniętę” abstrakcyjny moduł public class InvoicesModule extends AbstractModule { Implementujemy @Override metodę configure protected void configure() { definiując wiązania bind(IPersistenceManager.class) .to(DatabasePersistenceManager.class); ... } } Copyright © 2014 IISG Pierwsze kroki 3) Wiązania (ang. bindings) Skojarzenie interfejsu z konkretną implementacją API powiązanie interfejsu IPersistenceManager z implementację bazodanową bind(IPersistenceManager.class).to(DatabasePersistenceManager.class); Copyright © 2014 IISG Pierwsze kroki 4) Tworzenie kontenera IoC Injector injector = Guice.createInjector(new InvoicesModule()); 5) Pobranie zainicjalizowanego obiektu z kontenera InvoicesCatalogue invoices = injector.getInstance(InvoicesCatalogue.class); invoices.addInvoice(...); Copyright © 2014 IISG Definicja zależności Przez konstruktor public class InvoicesCatalogue { private IPersistenceManager manager; private ILogger logger; @Inject public InvoicesCatalogue(IPersistenceManager manager, ILogger logger) { this.manager = manager; this.logger = logger; } } Uwaga: Adnotacja @Inject nie jest wymagana dla bezargumentowych konstruktorów publicznych. Copyright © 2014 IISG Definicja zależności Przez metodę public class InvoicesCatalogue { private IPersistenceManager manager; private ILogger logger; @Inject public setPM(IPersistenceManager manager) { this.manager = manager; } @Inject public setLogger(ILogger logger) { this.logger = logger; } Adnotacja @Inject jest wymagana dla każdej metody } Copyright © 2014 IISG Definicja zależności Przez pole public class InvoicesCatalogue { @Inject private IPersistenceManager manager; @Inject private ILogger logger; } Opcjonalne zależności public class DatabasePersistenceManager { @Inject(optional=true) public void setUrl(String url) { ... Copyright © 2014 IISG Rodzaje wiązań (bindings) 1) Linked bindings Copyright © 2014 IISG Rodzaje wiązań (bindings) 1) Linked bindings public class InvoicesModule extends AbstractModule { @Override protected void configure() { Skojarzenie intefejsu bind(ILogger.class).to(FileLogger.class); ILogger z klasą FileLogger bind(IPersistenceManager.class) .to(DatabasePersistenceManager.class); bind(DatabasePersistenceManager.class) .to(MySqlPersistenceManager.class); } Linked bindings mogą być łączone w łańcuchy } Copyright © 2014 IISG Rodzaje wiązań (bindings) 2) Nazwane wiązania (ang. named bindings) bind(ILogger.class).to(FileLogger.class); bind(ILogger.class).to(ConsoleLogger.class); Błąd: Kontener nie wie, której implementacji użyć!!! Copyright © 2014 IISG Rodzaje wiązań (bindings) 2) Nazwane wiązania (ang. named bindings) W definicji typu dodajemy dodatkowy „klucz-nazwę” dla zależności: public class InvoicesCatalogue { @Inject @Named(„Invoices") ILogger logger; } Następnie, aby powiązać nazwaną zależność z typem należy wykorzystać metodę annotatedWith jak pokazano niżej: bind(ILogger.class).annotatedWith(Names.named(„Invoices")) .to(ConsoleLogger.class); bind(ILogger.class).annotatedWith(Names.named(„GUI")) .to(FileLogger.class); Copyright © 2014 IISG Rodzaje wiązań (bindings) 3) Providers Zależność do klasy dostarczonej z zewnętrznej biblioteki np. brak adnotacji @Inject na konstruktorze, metodach typu „set”, etc. Dodatkowa inicjalizacja PersistenceManager = manager = new DatabasePersistenceManager(); manager.setJdbcUrl(”jdbc:mysql://localhost/db”); manager.setTheadPoolSize(30); Copyright © 2014 IISG Rodzaje wiązań (bindings) 3) Providers Metoda provides w module public class ExampleModule extends AbstractModule { @Provides IPersistenceManager providePersistenceManager() { DatabasePersistenceManager manager = new DatabasePersistenceManager(); manager.setJdbcUrl(”jdbc:mysql://localhost/db”); manager.setTheadPoolSize(30); return manager; } } Klasa rozszerzjąca interfejs IProvider<T> Copyright © 2014 IISG Rodzaje wiązań (bindings) 4) Just-In-Time bindings Domyślne implementacje typów @ImplementedBy(DatabasePersistenceManager.class) public interface IPersistenceManager { } Powyższy kod jest równoznaczny z: bind(IPersistenceManager.class).to(DatabasePersistenceManager.class) Domyślne wiązanie może być nadpisane w metodzie configure (np. w przypadku konfiguracji testowej) Copyright © 2014 IISG Kontrola instancjonowania Wybrane zasięgi: 1) Domyślnie zasięg prototype 2) Zasięg singleton Adnotacja @Singleton na implementacji @Singleton public class DatabasePersistenceManager implements IPersistenceManager Podczas definicji wiązania bind(IPersistenceManager.class) .to(DatabasePersistenceManager.class).in(Singleton.class); Uwaga: klasy o zasięgu singleton powinny być thread-safe! Copyright © 2014 IISG Bibliografia Dependency Injection, Design patterns using Spring and Guice, Dhanji R. Prasanna Google Guice Documentation, http://code.google.com/p/google-guice/wiki/GettingStarted Copyright © 2014 IISG