Jersey HK2 Dependency Injection

一世执手 提交于 2019-11-28 14:19:34

What you can do is create a custom annotation

@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface Config {
    String value();
}

Then create an InjectionResolver for it (which allows for injection using custom annotations)

public static class ConfigInjectionResolver implements InjectionResolver<Config> {

    private static final Map<String, String> properties = new HashMap<>();

    public ConfigInjectionResolver() {
        properties.put("greeting.message", "Hello World");
    }

    @Override
    public Object resolve(Injectee injectee, ServiceHandle<?> handle) {
        if (String.class == injectee.getRequiredType()) {
            AnnotatedElement elem = injectee.getParent();
            if (elem instanceof Constructor) {
                Constructor ctor = (Constructor) elem;
                Config config = (Config) ctor.getParameterAnnotations()[injectee.getPosition()][0];
                return properties.get(config.value());
            } else {
                Config config = elem.getAnnotation(Config.class);
                return properties.get(config.value());
            }
        }
        return null;
    }

    @Override
    public boolean isConstructorParameterIndicator() { return true; }

    @Override
    public boolean isMethodParameterIndicator() { return false; }
}

This example just uses a Map, but I'm sure you can figure out how to make it use Properties. Once you register the InjectionResolver, you can now just do

public SomeService(@Config("some.property") String property) {}

Here is a complete test case

import org.glassfish.hk2.api.Injectee;
import org.glassfish.hk2.api.InjectionResolver;
import org.glassfish.hk2.api.ServiceHandle;
import org.glassfish.hk2.api.TypeLiteral;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.filter.LoggingFilter;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Test;

import javax.inject.Inject;
import javax.inject.Singleton;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
import java.lang.annotation.*;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;

import static org.junit.Assert.*;

/**
 * Run like any other JUnit Test. Only one required dependency
 *
 * <dependency>
 *   <groupId>org.glassfish.jersey.test-framework.providers</groupId>
 *   <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
 *   <version>${jersey2.version}</version>
 * </dependency>
 *
 * @author Paul Samsotha
 */
public class ConfigExample extends JerseyTest {

    @Target({ElementType.FIELD, ElementType.PARAMETER})
    @Retention(RetentionPolicy.RUNTIME)
    public static @interface Config {
        String value();
    }

    public static class ConfigInjectionResolver implements InjectionResolver<Config> {

        private static final Map<String, String> properties = new HashMap<>();

        public ConfigInjectionResolver() {
            properties.put("greeting.message", "Hello World");
        }

        @Override
        public Object resolve(Injectee injectee, ServiceHandle<?> handle) {
            if (String.class == injectee.getRequiredType()) {
                AnnotatedElement elem = injectee.getParent();
                if (elem instanceof Constructor) {
                    Constructor ctor = (Constructor) elem;
                    Config config = (Config) ctor.getParameterAnnotations()[injectee.getPosition()][0];
                    return properties.get(config.value());
                } else {
                    Config config = elem.getAnnotation(Config.class);
                    return properties.get(config.value());
                }
            }
            return null;
        }

        @Override
        public boolean isConstructorParameterIndicator() { return true; }

        @Override
        public boolean isMethodParameterIndicator() { return false; }
    }


    private static interface GreetingService {
        String getGreeting();
    }

    private static class ConfiguredGreetingService implements GreetingService {
        private String message;

        public ConfiguredGreetingService(@Config("greeting.message") String message) {
            this.message = message;
        }

        @Override
        public String getGreeting() {
            return this.message;
        }
    }

    @Path("greeting")
    public static class GreetingResource {

        @Inject
        private GreetingService greetingService;

        @GET
        public String getConfigProp() {
            return greetingService.getGreeting();
        }
    }

    @Override
    public ResourceConfig configure() {
        ResourceConfig config = new ResourceConfig(GreetingResource.class);
        config.register(new LoggingFilter(Logger.getAnonymousLogger(), true));
        config.register(new AbstractBinder(){
            @Override
            protected void configure() {
                bind(ConfiguredGreetingService.class).to(GreetingService.class).in(Singleton.class);
                bind(ConfigInjectionResolver.class)
                        .to(new TypeLiteral<InjectionResolver<Config>>(){})
                        .in(Singleton.class);
            }
        });
        return config;
    }

    @Test
    public void should_get_configured_greeting() {
        final Response response = target("greeting")
                .request().get();
        assertEquals("Hello World", response.readEntity(String.class));
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!