Dieser Artikel beschreibt, wie der Google Guice Injector und sein Bestandteil Injector Holder in OpenAM verwendet werden. Der entsprechende Code befindet sich in einem Paket namens Guice Core von ForgeRock. Der Quellcode lautet ** hier ** ) Kann referenziert werden. Beginnen wir mit einer grundlegenden Erklärung des Guice Injector.
Es ist fast Weihnachten / Jahresende, daher erkläre ich die Verwendung von zwei Klassen, "ChristmasGreeting" und "NewYearGreeting", die die "SeasonsGreeting" -Schnittstelle implementieren.
Was Sie beachten sollten, ist der Teil, in dem die Methode "Guice # createInjector (Module ...)" eine Instanz von "Injector" erhält.
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
public class Example01 {
public interface SeasonsGreeting {
void greeting();
}
public static class ChristmasGreeting implements SeasonsGreeting {
@Override
public void greeting() {
System.out.println("Merry Christmas!");
}
}
public static class NewYearGreeting implements SeasonsGreeting {
@Override
public void greeting() {
System.out.println("Happy New Year!");
}
}
public static void main(String[] args) {
Injector injector = Guice.createInjector(new AbstractModule() {
@Override protected void configure() {
bind(SeasonsGreeting.class).to(ChristmasGreeting.class);
}
});
SeasonsGreeting sg = injector.getInstance(SeasonsGreeting.class);
sg.greeting();
}
}
Die Methode configure ()
verbindet die Schnittstelle SeasonsGreeting
mit ihrer Implementierung ChristmasGreeting
. Der entsprechend erzeugte "Injektor" gibt eine Instanz von "ChristmasGreeting" zurück.
Ausführungsergebnis
Merry Christmas!
Im obigen Beispiel hatte "Guice # createInjector (Module ...)" nur ein Argument, aber Sie können mehrere Argumente angeben, wie unten gezeigt.
public static Injector createInjector(java.lang.Iterable<? extends Module> modules)
Damit ist es möglich, mehrere Einstellungen zu lesen, die in einer Klasse angegeben sind, die "Modul" gleichzeitig erweitert. Der unten beschriebene InjectorHolder bietet einen festen "Platz" für die wiederholte Verwendung der auf diese Weise erstellten "Injector" -Instanz.
Aus dem Namen "Holder" von InjectorHolder geht hervor, dass die generierte Instanz von "Injector" gespeichert und herausgenommen und nach Bedarf verwendet werden soll. In der Realität wird "Injector" jedoch in "InjectorHolder" generiert und intern verwendet. Es kann näher an der Realität sein, wenn Sie es einen Rapper nennen, weil Sie nicht herausgenommen werden.
Im folgenden Code wird der Aufzählungstyp von Anfang an ausgegeben. So implementieren Sie einen Singleton mithilfe einer Aufzählung mit nur einem Element (INSTANCE
)
Eingeführt in Punkt 3 von Effective Java 3rd Edition Es ist gewesen. Hier verwenden wir es, um "InjectorHolder" als Singleton zu definieren.
Beachten Sie den Teil des privaten Konstruktors, der "InjectorFactory" verwendet, um "Injector" zu generieren.
public enum InjectorHolder {
/**
* The Singleton instance of the InjectorHolder.
*/
INSTANCE;
private Injector injector;
/**
* Constructs an instance of the InjectorHolder and initialises the Guice Injector.
*/
private InjectorHolder() {
InjectorFactory injectorFactory = new InjectorFactory(new GuiceModuleCreator(),
new GuiceInjectorCreator(), InjectorConfiguration.getGuiceModuleLoader());
try {
injector = injectorFactory.createInjector(InjectorConfiguration.getModuleAnnotation());
} catch (Exception e) {
e.printStackTrace();
throw new IllegalStateException(e);
}
}
/**
* @param clazz The class to get an instance of.
* @param <T> The type of class to get.
* @return A non-null instance of the class.
*/
public static <T> T getInstance(Class<T> clazz) {
return INSTANCE.injector.getInstance(clazz);
}
Die endgültige Methode "getInstance (Class
Nun wollen wir sehen, wie InjectorFactory
eine Instanz von Injector
erstellt.
Wie bereits erwähnt, können Sie beim Erstellen eines "Injectors" mehrere Instanzen einer Klasse angeben, die "Module" erweitert. Jede Erweiterungsklasse überschreibt die Configure () -Methode mit unterschiedlichen Einstellungen. Die Annotation "@ GuiceModule" wird verwendet, um zu bestimmen, welche Erweiterungsklasse geladen werden soll. Insbesondere die Injector Factory
Module
, die mit @ GuiceModule
versehen ist.Wir machen die Verarbeitung. Der folgende Code ist der einleitende Teil. Andere Teile werden weggelassen, weil sie lang sind. Weitere Informationen finden Sie unter Öffentlicher Code. Siehe InjectorFactory.java).
final class InjectorFactory {
/**
* Creates a new Guice injector which is configured by all modules found by the {@link GuiceModuleLoader}
* implementation.
*
* @param moduleAnnotation The module annotation.
* @return A non-null Guice injector.
*/
Injector createInjector(Class<? extends Annotation> moduleAnnotation) {
/*
This does not need to by synchronized as it is only ever called from the constructor of the
InjectorHolder enum, which is thread-safe so no two threads can create an injector at the same time.
This does mean that this method MUST not be called/used by another other class!
*/
return injectorCreator.createInjector(createModules(moduleAnnotation));
}
Wir haben gesehen, wie der Injektorhalter funktioniert. Im Folgenden werden wir uns ansehen, wie es in OpenAM verwendet wird.
Die Arbeit, OpenAM mit Google Guice kompatibel zu machen, wurde vor langer Zeit durchgeführt. Im Allgemeinen ist es nicht einfach, große Software wie OpenAM mit Google Guice kompatibel zu machen. Sie beginnen mit einem einfachen Teilbaum, der näher an den Zweigen und Blättern des Abhängigkeitsbaums liegt, und folgen dem Baum dann in Richtung komplexerer Objekte. In einem komplizierten Baum ist es möglicherweise nicht möglich, sofort neu zu schreiben. Platzieren Sie in einem solchen Fall den InjectorHolder an der "Grenze" zwischen der Klasse, die neu geschrieben wurde, und der Klasse, die nicht neu geschrieben wurde. Erstellen Sie mit InjectorHolder in der unvollständigen Klasse ein Objekt der neu geschriebenen Klasse. Die Lösung der Abhängigkeit danach bleibt Google Guice überlassen. Während des Umschreibens bewegt sich auch der Injektorhalter. Auf diese Weise kann auch komplizierte Software schrittweise neu geschrieben werden.
Erstens ist es möglicherweise nicht möglich, Google Guice zu unterstützen, oder es gibt keinen Grund, es zu unterstützen. Bei OpenAM ist dies der Authentifizierungsdienst. OpenAM verfügt über einen Mechanismus zum unabhängigen Verwalten verschiedener Instanzen von Authentifizierungsmodulen für die Multi-Faktor-Authentifizierung. Da es schwierig ist, dies mit Google Guice kompatibel zu machen, verwendet Injector Holder es auf der Ebene einzelner Authentifizierungsmodule.
Bei OpenAM haben wir gesehen, dass der Injektorhalter an der "Grenze" zwischen "Nicht-Guice-Welt" und "Guice-Welt" platziert ist. Wenn Sie interessiert sind, lesen Sie bitte den Quellcode, der im OpenAM-Konsortium veröffentlicht wurde.
Recommended Posts