6

Java EE 6 を使用しており、「.properties」ファイルから構成をロードする必要があります。依存性注入を使用して構成ファイルから値をロードするための推奨される方法 (ベスト プラクティス) はありますか? Spring でこれに関する注釈を見つけましたが、Java EE の「標準」注釈は見つかりませんでした。

この男はゼロからソリューションを開発しました:

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

「ファイルから構成属性を読み取って CDI を使用してアプリケーションを構成する方法の簡単な例が見つかりませんでした...」

しかし、構成ファクトリを作成する代わりに、より標準的な方法があるのだろうか...

4

4 に答える 4

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()});
        }
    }

説明付きのチュートリアルと Arquillian テスト

于 2013-04-10T13:21:54.970 に答える
1

それはあなたの質問を正確にカバーしていませんが、Weldドキュメントのこの部分はあなたにとって興味深いかもしれません。

これについて言及しましたが、いいえ、任意のリソース/リソースファイルを挿入する標準的な方法はありません。このような高度にカスタム依存の要件を標準化することは、仕様の範囲を超えていると思います(Springは仕様ではなく、好きなように実装できます)。ただし、CDIが提供するのは、一方の側で構成保持Beanを注入するための強力な(別名タイプセーフ)メカニズムと、もう一方の側でそのようなBeanを読み取って作成するための柔軟なプロデューサーメカニズムです。間違いなく、これはあなたが尋ねていた推奨される方法です。

あなたがリンクしているアプローチは確かにかなり良いものです-あなたが注入することを計画しているプロパティの種類によっては、あなたのニーズには多すぎるかもしれませんが。

非常にCDI風の継続方法は、CDI拡張機能(必要なすべてのクラスを適切にカプセル化する)を開発し、プロジェクトとは独立してデプロイすることです。もちろん、CDI拡張カタログApacheDeltaspikeに貢献することもできます。

于 2012-04-16T17:48:53.240 に答える
1

これを行う唯一の「標準的な」方法は、拘束力のない注釈メンバーで修飾子を使用し、すべてのインジェクションが依存スコープであることを確認することです。次に、プロデューサーで InjectionPoint を取得し、注入ポイントの修飾子からキーを取得できます。次のようなものが必要です。

@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);
}

もちろん、そのコードに対して実行できる拡張機能がいくつかありますが、正しい軌道に乗るには十分なはずです。

于 2012-04-16T21:07:21.913 に答える
1

Apache DeltaSpike の @ConfigProperty を参照してください。

于 2012-04-26T17:28:58.940 に答える