Suche…


Grundlegende Abhängigkeitseinspritzung mit Jersey HK2

Jersey (2) verwendet HK2 als Abhängigkeitsinjektionssystem (DI). Wir können andere Injektionssysteme verwenden, aber seine Infrastruktur ist mit HK2 aufgebaut und ermöglicht es uns, sie auch in unseren Anwendungen zu verwenden.

Das Einrichten einer einfachen Abhängigkeitsinjektion mit Jersey erfordert nur wenige Codezeilen. Nehmen wir zum Beispiel an, wir haben einen Service, den wir in unsere Ressourcen einbringen möchten.

public class GreetingService {
    public String getGreeting(String name) {
        return "Hello " + name + "!";
    }
}

Und wir möchten diesen Service in eine Jersey-Ressource integrieren

@Path("greeting")
public class GreetingResource {

    @Inject
    public GreetingService greetingService;

    @GET
    public String get(@QueryParam("name") String name) {
        return this.greetingService.getGreeting(name);
    }
}

Damit die Injektion funktioniert, brauchen wir nur eine einfache Konfiguration

@ApplicationPath("/api")
public class AppConfig extends ResourceConfig {
    public AppConfig() {
        register(GreetingResource.class);
        register(new AbstractBinder() {
            @Override
            protected void configure() {
                bindAsContract(GreetingService.class);
            }
        });
    }
}

Hier möchten wir sagen, dass wir den GreetingService an das Einspritzsystem binden und als von derselben Klasse injizierbar ankündigen wollen. Die letzte Aussage bedeutet, dass wir sie nur als GreetingService und (wahrscheinlich offensichtlich) von keiner anderen Klasse einfügen können. Wie Sie später sehen werden, ist es möglich, dies zu ändern.

Das ist es. Das alles was du brauchst. Wenn Sie mit dieser ResourceConfig Konfiguration nicht vertraut sind (möglicherweise verwenden Sie web.xml), lesen Sie bitte das Thema zum Konfigurieren von JAX-RS in Jersey zu SO-Dokumenten.


Hinweis: Bei der obigen Injektion handelt es sich um eine Feldinjektion, bei der der Service in das Feld der Ressource injiziert wird. Eine andere Art der Injektion ist die Konstruktorinjektion, bei der der Dienst in den Konstruktor eingespritzt wird

private final GreetingService greetingService;

@Inject   
public GreetingResource(GreetingService greetingService) {
     this.greetingService = greetingService;
}

Dies ist wahrscheinlich der bevorzugte Weg im Gegensatz zur Feldinjektion, da die Ressource einfacher für den Komponententest ist. Die Konstruktorinjektion erfordert keine andere Konfiguration.


Ok, sagen wir jetzt, dass der GreetingService anstelle einer Klasse eine Schnittstelle ist, und wir haben eine Implementierung davon (was sehr häufig ist). Um dies zu konfigurieren, würden wir in der obigen configure Methode die folgende Syntax verwenden

@Override
protected void configure() {
    bind(NiceGreetingService.class).to(GreetingService.class);
}

Dies liest sich als " NiceGreetingService binden und als GreetingService ". Dies bedeutet, dass wir denselben Code in der GreetingResource oben verwenden können, da wir den Vertrag als GreetingService und nicht als NiceGreetingService . Die eigentliche Implementierung wird jedoch der NiceGreetingService .

Was ist nun mit dem Umfang? Wenn Sie jemals mit einem Injektionssystem gearbeitet haben, sind Sie auf das Konzept des Umfangs gestoßen, das die Lebensdauer des Dienstes bestimmt. Sie haben möglicherweise von einem "Request Scope" gehört, bei dem der Dienst nur für die gesamte Dauer der Anfrage aktiv ist. Oder ein "Singleton Scope", bei dem es nur eine Instanz des Dienstes gibt. Wir können diese Bereiche auch mit der folgenden Syntax konfigurieren.

@Override
protected void configure() {
    bind(NiceGreetingService.class)
            .to(GreetingService.class)
            .in(RequestScoped.class);
}

Der Standardbereich ist PerLookup bedeutet, dass jedes Mal, wenn dieser Dienst angefordert wird, ein neuer erstellt wird. Im obigen Beispiel wird mithilfe von RequestScoped ein neuer Dienst für eine einzelne Anforderung erstellt. Dies kann, je PerLookup , an wie vielen Stellen wir versuchen, es zu injizieren, der PerLookup . Möglicherweise versuchen wir, es in einen Filter und in eine Ressource zu injizieren. Wenn dies PerLookup wäre, würden für jede Anforderung zwei Instanzen erstellt. In diesem Fall wollen wir nur einen.

Die anderen beiden verfügbaren Bereiche sind Singleton (nur eine Instanz wurde erstellt) und Immediate (wie Singleton ), werden jedoch beim Start erstellt (mit Singleton wird er jedoch erst bei der ersten Anforderung erstellt).

Abgesehen von bindenden Klassen können wir auch eine Instanz verwenden. Dies würde uns einen Standard-Singleton geben, so dass wir keine in Syntax verwenden müssen.

@Override
protected void configure() {
    bind(new NiceGreetingService())
            .to(GreetingService.class);
}

Was ist, wenn wir eine komplexe Erstellungslogik haben oder Anforderungskontextinformationen für den Dienst benötigen. In diesem Fall gibt es Factory s. Die meisten Dinge, die wir in unsere Jersey-Ressourcen injizieren können, können wir auch in eine Factory injizieren. Nehmen Sie zum Beispiel

public class GreetingServiceFactory implements Factory<GreetingService> {
    
    @Context
    UriInfo uriInfo;
    
    @Override
    public GreetingService provide() {
        return new GreetingService(
                uriInfo.getQueryParameters().getFirst("name"));
    }
    
    @Override
    public void dispose(GreetingService service) {
        /* noop */
    }
}

Hier haben wir eine Factory, die Anforderungsinformationen von UriInfo , in diesem Fall Abfrageparameter, und wir erstellen daraus den GreetingService . Zur Konfiguration verwenden wir die folgende Syntax

@Override
protected void configure() {
    bindFactory(GreetingServiceFactory.class)
            .to(GreetingService.class)
            .in(RequestScoped.class);
}

Das ist es. Dies sind nur die Grundlagen. Es gibt noch viel mehr Dinge, die HK und Jersey tun müssen.



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow