Recherche…


Injection de dépendance de base à l'aide du HK2 de Jersey

Jersey (2) utilise HK2 comme système d'injection de dépendance (DI). Nous pouvons utiliser d'autres systèmes d'injection, mais son infrastructure est construite avec HK2 et nous permet également de l'utiliser dans nos applications.

Configurer l'injection de dépendance simple avec Jersey ne prend que quelques lignes de code. Disons par exemple que nous avons un service que nous aimerions injecter dans nos ressources.

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

Et nous voulons injecter ce service dans une ressource Jersey

@Path("greeting")
public class GreetingResource {

    @Inject
    public GreetingService greetingService;

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

Pour que l'injection fonctionne, il suffit d'avoir une configuration simple

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

Ici, nous disons que nous voulons associer le service GreetingService au système d’injection et l’annoncer comme injectable par la même classe. Ce que la dernière phrase signifie, c’est que nous ne pouvons l’injecter qu’en tant que GreetingService et (probablement de toute évidence) pas par une autre classe. Comme vous le verrez plus tard, il est possible de changer cela.

C'est tout. C'est tout ce dont vous avez besoin. Si vous n'êtes pas familier avec cette configuration ResourceConfig (vous utilisez peut-être web.xml), consultez la rubrique Configuration de JAX-RS à Jersey sur SO Docs.


Note: L'injection ci-dessus est l'injection de champ, où le service est injecté dans le champ de la ressource. Un autre type d'injection est l'injection constructeur, où le service est injecté dans le constructeur

private final GreetingService greetingService;

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

C'est probablement la meilleure façon de procéder, contrairement à l'injection sur le terrain, car elle facilite le test unitaire des ressources. L'injection de constructeur ne nécessite aucune configuration différente.


Ok, disons qu'au lieu d'une classe, GreetingService est une interface, et nous en avons une implémentation (ce qui est très courant). Pour configurer cela, nous utiliserons la syntaxe suivante dans la méthode de configure ci-dessus

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

Cela se lit comme "lier NiceGreetingService , et annoncer comme GreetingService ". Cela signifie que nous pouvons utiliser exactement le même code dans GreetingResource ci-dessus, car nous NiceGreetingService le contrat en tant que GreetingService et non NiceGreetingService . Mais la mise en œuvre réelle, une fois injectée, sera le NiceGreetingService .

Maintenant, qu'en est-il de la portée? Si vous avez déjà travaillé avec un cadre d'injection, vous aurez découvert le concept de portée qui détermine la durée de vie du service. Vous avez peut-être entendu parler d'une "Demande de portée", où le service n'est actif que pendant la durée de la demande. Ou un "Singleton Scope", où il n'y a qu'une seule instance du service. Nous pouvons configurer ces portées en utilisant également la syntaxe suivante.

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

La portée par défaut est PerLookup , ce qui signifie que chaque fois que ce service est demandé, un nouveau sera créé. Dans l'exemple ci-dessus, à l'aide de RequestScoped , un nouveau service sera créé pour une seule requête. Cela peut être ou ne pas être le même que le PerLookup , en fonction du nombre d'endroits que nous essayons d'injecter. Nous essayons peut-être de l'injecter dans un filtre et dans une ressource. S'il s'agissait de PerLookup , deux instances seraient créées pour chaque requête. Dans ce cas, nous n'en voulons qu'un.

Les deux autres étendues disponibles sont Singleton (une seule instance créée) et Immediate (comme Singleton ), mais elles sont créées au démarrage (alors qu'avec Singleton , elles ne sont créées qu'à la première demande).

Outre les classes de liaison, nous pourrions également utiliser une instance. Cela nous donnerait un singleton par défaut, nous n'avons donc pas besoin d'utiliser la syntaxe in .

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

Que se passe-t-il si nous avons une logique de création complexe ou si nous avons besoin d'informations de contexte de requête pour le service? Dans ce cas, il y a Factory s. La plupart des choses que nous pouvons injecter dans nos ressources de Jersey, nous pouvons également injecter dans une Factory . Prends pour exemple

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 */
    }
}

Ici , nous avons une usine, qui obtient demander des informations de la UriInfo , dans ce cas , un paramètre de requête, et nous créons le GreetingService de celui - ci. Pour le configurer, nous utilisons la syntaxe suivante

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

C'est tout. Ce ne sont que les bases. Il y a beaucoup plus de choses à faire à HK et à Jersey.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow