AgE 2.4 : MechanizmWstrzykiwaniaZaleznosci

TODO: This page is seriously outdated and needs to be rewriten

Mechanizm wstrzykiwania zależności

Mechanizm wstrzykiwania zależności platformy AgE wykorzystuje kontener IoC dostarczony przez technologię PicoContainer. Aby dostosować sposób dostarczania zależności, korzystając z kontenera Pico, należy zaimplementować własny adapter.


Rysunek: Implementacja mechanizmu wstrzykiwania zależności

Powyższy rysunek pokazuje diagram klas odpowiedzialnych za wstrzykiwanie zależności. Głównym elementem jest klasa CoreComponentAdapter, która rozszerza abstrakcyjną klasę AbstractComponentAdapter. Dzięki temu może zostać wykorzystana przez kontener Pico do dostarczania instancji komponentów. Metoda getComponentInstance jest wywoływana przez kontener w przypadku, kiedy do kontenera przyszło żądanie uzyskania referencji do danego komponentu.
Kontener zawiera dwie metody: getComponentInstance(String) o getComponentInstanceOfType(Class<?>), które pełnią rolę zewnętrznego interfejsu dla klienta. Umożliwiają one dostarczenie instancji komponentu identyfikowanego po zarejestrowanej wcześniej nazwie lub po jego typie.

Adapter deleguje proces tworzenia instancji komponentu do jego definicji, za pomocą metody createInstance. A zatem odpowiedzialność utworzenia komponentu spoczywa na jego definicji. W przypadku klasy ComponentDefinition, instancjonowanie obiektu odbywa się na podstawie informacji opisujących argumenty konstruktorów oraz inicjalizatory właściwości PropertyInitilizers). Argumenty konstruktorów reprezentowane są przez listę obiektów typu IValueProvider, odpowiedzialnych za dostarczenie wartości, które reprezentują. Używane są podczas wstrzykiwania przez konstruktor. Inicjalizatory właściwości wykorzystywane są podczas wstrzykiwania za pomocą adnotowanych metod lub pól. Każdy obiekt klasy PropertyInitializer zawiera nazwę właściwości oraz jej wartość, która ma zostać wstrzyknięta podczas inicjalizacji, reprezentowaną przez obiekt typu IValueProvider.

Należy zauważyć, że z poziomu definicji obiekty CoreComponentAdapter są widoczne przez interfejs IComponentInstanceProvider. Takie rozwiązanie uniezależnia model konfiguracji od konkretnej technologii komponentowej.

Interfejs IComponentInstanceProvider zawiera trzy metody odpowiedzialne za dostarczanie instancji komponentów. Metoda getInstance(String) zwraca obiekt identyfikowany po nazwie zarejestrowanej w kontenerze. W przypadku nieznalezienia obiektu o podanej nazwie zwracana jest wartość null. Metoda getInstance(Class<?>) wyszykuje w kontenerze IoC implementację typu podanego jako parametr. Aby taka instancja mogła zostać dostarczona, musi być zarejestrowana dokładnie jedna implementacja żądanego typu. W przeciwnym wypadku zostanie zwrócona wartość null. Ostatnia bezparametrowa metoda, getInstance(), odpowiedzialna jest za dostarczenie obiektu, którego definicja jest skojarzona z instancją IComponentInstanceProvider. Metoda ta wykorzystywana jest na przykład podczas klonowania agentów. Agent wysyła żądanie utworzenia swojej kopii, która następnie zostanie włączona do struktury agentów.

Wstrzykiwanie przez konstruktor


Rysunek: Diagram sekwencji procesu wstrzykiwania przez konstruktor

Powyższy rysunek przedstawia diagram sekwencji tworzenia instancji komponentu za pomocą wstrzykiwania przez konstruktor 1. Obiekt CoreComponentAdapter deleguje instancjonowanie komponentu do przechowywanej definicji, przekazują wskazanie na siebie (przez interfejs IComponentInstanceProvider). Definicja komponentu, na podstawie listy constructorArguments, tworzy wszystkie obiekty (lub wartości proste) potrzebne do inicjalizacji komponentu. Za ich utworzenie odpowiedzialne są implementacje interfejsu IValueProvider opisane na stronie Interfejs IValueProvider.

Jeśli pobieranie wszystkich zależności przebiegnie poprawnie, mechanizm wyszukuje odpowiedni konstruktor. Konstruktor musi być publiczny oraz posiadać listę parametrów formalnych odpowiadającą dokładnie typom zawartym w tablicy argumentTypes, w kolejności zapisanej w tablicy. Nowy obiekt reprezentujący komponent jest tworzony za pomocą znalezionego konstruktora.

Wstrzykiwanie za pomocą adnotowanych pól lub metod


Rysunek: Diagram sekwencji procesu wstrzykiwania za pomocą adnotowanych pól lub metod

Rysunek przedstawia diagram sekwencji tworzenia instancji komponentu z wykorzystaniem wstrzykiwania za pomocą adnotowanych pól lub metod 2. Pierwszym krokiem jest stworzenie nowego obiektu za pomocą domyślnego konstruktora lub, w przypadku mieszanego wstrzykiwania, otrzymanie obiektu po zakończonym procesie wstrzykiwania przez konstruktor. Klasa tworzonego obiekt musi implementować interfejs IPropertyContainer. Wykorzystując mechanizm właściwości obiektów opisany na stronie Właściwości obiektów, z obiektu pobierane są wszystkie właściwości (obiekty typu Property). Mechanizm ten wykorzystywane jest również do ustawiania wartości właściwości (metoda Property.setValue(Object)). W zależności od tego czy właściwości będą implementowane przez klasę ClassFieldProperty lub ClassGetterSetterProperty, wstrzykiwanie będzie odbywało się za pomocą adnotowanych pól lub metod.

Jeśli dla danej właściwości istnieje odpowiedni obiekt typu PropertyInitializer, to właśnie z niego pobierana jest wartość do wstrzyknięcia. Zawiera on obiekt IValueProvider, który dostarcza odpowiednią referencję lub wartość prostą (więcej na temat implementacji providerów w na stronie Interfejs IValueProvider.

W przeciwnym wypadku rozpoczyna działanie mechanizm auto-wiring, który pobiera z właściwości jej typ i próbuje pobrać z IComponentInstanceProvider pasującą referencję. Warunkiem pobrania obiektu jest istnienie w kontenerze IoC dokładnie jednej implementacji szukanego typu. Mechanizm auto-wiring działa wyłącznie dla typów złożonych.


1 Rysunek przedstawia tylko fragment sekwencji zaczynający się od obiektu typu CoreComponentAdapter. Jak opisano wcześniej, klient kieruje żądanie uzyskania komponentu do kontenera IoC, który to deleguje żądanie do obiektu CoreComponentAdapter.

2 Patrz poprzedni przypis.

Attachments: