本文介绍了使用自定义的hk2 InjectionResolver来注入应用程序配置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有关的跟进。我正在尝试使用JSR-330标准注释注册应用程序配置数据,并使用与泽西搭配的HK2框架。

Kind of a follow up to my previous question. I'm trying to inject application configuration data using JSR-330 standard annotations and the HK2 framework bundled with jersey.

理想情况下,我想为命名为 InjectionResolver c $ c>注释,它将在我将从数据中填充的 Map 属性对象中查找所需的值在别处阅读在我第一次尝试中,我创建了一个应用程序实例,如

Ideally I'd like to create a custom InjectionResolver for the Named annotation, which will lookup the desired values in a Map or Properties object that I will populate from data read elsewhere. In my first attempt I've created an Application instance like

public class MyApplication extends ResourceConfig {
    ...
    packages(MY_PACKAGES);
    property(MY_CONFIG_PROPERTY, someValue);
    register(new AbstractBinder() {
        @Override
        protected void configure() {
            bind(ConfigurationInjectionResolver.class)
            .to(new TypeLiteral<InjectionResolver<Named>>(){})
            .in(Singleton.class)
        }
    });
}

然后我的 InjectionResolver 看起来像

public class ConfigurationInjectionResolver implements InjectionResolver<Named> {
    @Context Application application;

    @Override
    public Object resolve(Injectee injectee, ServiceHandle<?> serviceHandle) {
        // lookup data in application.getProperties();
    }
}

我的问题是应用程序.getProperties()为空。任何想法怎么了?另外,我可以绑定一个Injector的实例,而不是绑定该类吗?这样我可以构造一个传递我的 Map 数据作为参数的实例。

My problem is that application.getProperties() is empty. Any idea what's wrong? Also, could I bind an instance of my Injector instead of binding the class? That way I could construct the instance passing my Map data as a parameter.

推荐答案

不,这实际上对我来说完全正常。

No. This actually works perfectly fine for me.

public class ConfigurationInjectionResolver implements InjectionResolver<Named> {
    @Context
    Application application;

    @Override
    public Object resolve(Injectee injectee, ServiceHandle<?> root) {
        Named annotation = injectee.getParent().getAnnotation(Named.class);
        Map<String, Object> props = application.getProperties();
        String name = annotation.value();
        System.out.println(props.get(name));
        return props.get(name);
    }

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

@ApplicationPath("/rest")
public class JerseyApplication extends ResourceConfig {

    public JerseyApplication() {
        packages("jersey.startup.test");
        property("hello.config", "Hello World Property");
        register(new AbstractBinder() {
            @Override
            protected void configure() {
                bind(ConfigurationInjectionResolver.class)
                        .to(new TypeLiteral<InjectionResolver<Named>>() {
                        }).in(Singleton.class);
            }
        });
    }
}

资源

@Path("/config")
public class ConfigResource {

    @Named("hello.config")
    String hello;

    @GET
    public Response getHello() {
        return Response.ok(hello).build();
    }
}



个人而言,在这种情况下,我将创建自己的注释,以免覆盖 @Named 注释。

Personally though, in this situation, I would create my own annotation, as to not override any existing functionality of the @Named annotation.

HK2有一个配置扩展,您可以在其中从 .properties 属性对象c $ c>文件,并使这些属性自动注入 @Configured 注释。我找不到任何文档,但在

HK2 has a configuration extension, where you can load a Properties object from say a .properties file and and have those properties automatically injected with the @Configured annotation. I couldn't find any documentation on this, but there is an example usage of it in the HK2 source code examples.

这是一个示例实现

必需的依赖关系。检查泽西版本,看看它取决于什么HK2版本。在我的情况下,泽西2.13使用HK2 2.3.0-b10,所以应该是 $ {hk2.version}

Required dependencies. Check the Jersey version and see what HK2 version it depends on. In my case Jersey 2.13 uses HK2 2.3.0-b10, so that should be the ${hk2.version}

<dependency>
    <groupId>org.glassfish.hk2</groupId>
    <artifactId>hk2-configuration-hub</artifactId>
    <version>${hk2.version}</version>
</dependency>
<dependency>
    <groupId>org.glassfish.hk2</groupId>
    <artifactId>hk2-configuration-integration</artifactId>
    <version>${hk2.version}</version>
</dependency>
<dependency>
    <groupId>org.glassfish.hk2</groupId>
    <artifactId>hk2-property-file</artifactId>
    <version>${hk2.version}</version>
</dependency>

App config

App config

@ApplicationPath("/rest")
public class JerseyApplication extends ResourceConfig {

    @Inject
    public JerseyApplication(ServiceLocator locator) {
        packages("jersey.startup.test");
        ServiceLocatorUtilities.addClasses(locator, ConfigResource.class);
        try {
            loadConfigurationProperties(locator);
        } catch (IOException ex) {
            Logger.getLogger(JerseyApplication.class.getName())
                                   .log(Level.SEVERE, null, ex);
        }
    }

    private void loadConfigurationProperties(ServiceLocator locator)
                                                 throws IOException {
        ConfigurationUtilities.enableConfigurationSystem(locator);
        PropertyFileUtilities.enablePropertyFileService(locator);
        PropertyFileService propertyFileService
                = locator.getService(PropertyFileService.class);
        Properties props = new Properties();
        URL url = getClass().getResource("/configuration.properties");
        props.load(url.openStream());
        PropertyFileHandle propertyFileHandle
                = propertyFileService.createPropertyHandleOfAnyType();
        propertyFileHandle.readProperties(props);
    }
}

configuration.properties

configuration.properties

AppConfiguration.App.hello=Hello Squirrel Property!

资源

@Path("/config")
@ConfiguredBy("AppConfiguration")
public class ConfigResource {

    @Configured
    String hello;

    @GET
    public Response getHello() {
        return Response.ok(hello).build();
    }
}



Diclaimer:由于此功能没有很好的记录,我不知道我在这里有很好的实现。这只是试错。例如这个

Diclaimer: Since this feature isn't well documented, I am not sure if I have a good implementation here. It is just by trial and error. For instance this

ServiceLocatorUtilities.addClasses(locator, ConfigResource.class);

我觉得不必要。看起来很多,因为我已经是打包扫描。所以要明确添加 ConfigResource 到定位器上下文对我来说似乎不对。

I feel shouldn't be necessary. It seems redundant, as I am already package scanning. So to explicitly add the ConfigResource to the locator context doesn't seem right to me.

这篇关于使用自定义的hk2 InjectionResolver来注入应用程序配置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!