使用“.properties”文件进行依赖注入

时间:2012-04-15 19:21:45

标签: configuration dependency-injection annotations java-ee-6 cdi

我正在使用Java EE 6,需要从" .properties"加载配置。文件。是否有推荐的方法(最佳实践)使用依赖注入从配置文件加载值?我在春天找到了这个注释,但我没有找到一个标准" Java EE的注释。

这家伙从头开始制定解决方案:

  

http://weblogs.java.net/blog/jjviana/archive/2010/05/18/applicaction-configuration-java-ee-6-using-cdi-simple-example

     

"我找不到如何配置应用程序的简单示例   通过从文件中读取配置属性来使用CDI ..."

但我想知道是否有更标准的方法而不是创建配置工厂......

4 个答案:

答案 0 :(得分:3)

配置注释

package com.ubiteck.cdi;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import javax.enterprise.util.Nonbinding;
import javax.inject.Qualifier;

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface InjectedConfiguration {
    /**
     * Bundle key
     * @return a valid bundle key or ""
     */
    @Nonbinding String key() default "";
    /**
     * Is it a mandatory property
     * @return true if mandator
     */
    @Nonbinding boolean mandatory() default false;
    /**
     * Default value if not provided
     * @return default value or ""
     */
    @Nonbinding String defaultValue() default "";
 }

配置工厂可能如下所示:

import java.text.MessageFormat;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import javax.enterprise.inject.Produces;
import javax.enterprise.inject.spi.InjectionPoint;

public class ConfigurationInjectionManager {
    static final String INVALID_KEY="Invalid key '{0}'";
    static final String MANDATORY_PARAM_MISSING = "No definition found for a mandatory configuration parameter : '{0}'";
    private final String BUNDLE_FILE_NAME = "configuration";
    private final ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_FILE_NAME);

    @Produces
    @InjectedConfiguration
    public String injectConfiguration(InjectionPoint ip) throws IllegalStateException {
        InjectedConfiguration param = ip.getAnnotated().getAnnotation(InjectedConfiguration.class);
        if (param.key() == null || param.key().length() == 0) {
            return param.defaultValue();
        }
        String value;
        try {
            value = bundle.getString(param.key());
            if (value == null || value.trim().length() == 0) {
                if (param.mandatory())
                    throw new IllegalStateException(MessageFormat.format(MANDATORY_PARAM_MISSING, new Object[]{param.key()}));
                else
                    return param.defaultValue();
            }
            return value;            
        } catch (MissingResourceException e) {
            if (param.mandatory()) throw new IllegalStateException(MessageFormat.format(MANDATORY_PARAM_MISSING, new Object[]{param.key()}));
            return MessageFormat.format(INVALID_KEY, new Object[]{param.key()});
        }
    }

Tutorial with explanation and Arquillian test

答案 1 :(得分:1)

尽管它并未完全涵盖您的问题,但您可能会对Weld文档的this part感兴趣。

提到这个 - 不,没有标准的方法来注入任意资源/资源文件。我想它只是超出规范的范围来标准化这种高度依赖于定制的要求(Spring不是规范,它们可以简单地实现他们喜欢的任何东西)。但是,CDI提供的是一种强大的(也就是类型安全的)机制,用于在一侧注入配置持有bean,以及一种灵活的生产者机制,用于在另一端读取和创建此类bean。肯定这是你提出的推荐方式。

您链接的方法肯定是一个非常好的方法 - 即使它可能对您的需求太多,取决于您计划注入的属性类型。

一种非常CDI的继续方式是开发CDI扩展(可以很好地封装所有必需的类)并与您的项目一起独立部署。当然,您也可以为CDI-extension catalog甚至Apache Deltaspike做出贡献。

答案 2 :(得分:1)

这样做的唯一“标准”方法是使用带有非绑定注释成员的限定符,并确保所有注入都依赖于作用域。然后在你的制作人中你可以得到一个注入点,并从注入点的限定符中获取键。你想要这样的东西:

@Qualifier
public @interface Property {
    @Nonbinding String value default "";
}

...
@Inject @Property("myKey") String myKey;


...
@Produces @Property public String getPropertyByKey(InjectionPoint ip) {
    Set<Annotation> qualifiers = ip.getQualifiers

    // Loop through qualifers looking for Property.class save that off
    return ResourceBundle.getBundle(...).getString(property.key);
}

显然,您可以对该代码进行一些增强,但它应该足以让您开始走上正确的轨道。

答案 3 :(得分:1)

请参阅Apache DeltaSpike的@ConfigProperty