Spring を使用する場合、ランタイム データを Bean の構築に組み込むのはかなり面倒です。この分離を回避するテクニックはありますが、それには理由があると感じています。私の質問は、これが既知のパラダイムであるかどうか、およびそれについて議論している文献があるかどうかです。個人的には、アプリの動的性に応じて、長所と短所の両方があることがわかりました.
2 に答える
実行時データを Bean 構成に渡すためのよく知られた方法が少なくとも 5 つあります。
ApplicationContextInitializer
に追加PropertySources
するために使用しEnviroment
ます。- SPEL を使用して依存関係を注入します。
- 使用する
FactoryBeans.
factory-bean
およびfactory-method
属性を使用します。- ランタイム データを必要とするクラスを作成する場合は、それを提供するコラボレーターを注入するだけで済みます。
例えば
<bean id="requestAttributeReader" class="example.RequestAttributeReader" />
<bean id="requestInjectedBean" class="example.RequestInjectedBean" scope="request">
<property name="a" value="#{requestAttributeReader.a}" />
</bean>
Class RequestAttributeReader {
public String getA() {
return RequestContextHolder.getAttributes().getAttribute("a");
}
}
編集
IoC コンテナーの Bean 記述ファイルを使用すると、アプリケーション Bean でインプリメンターを構成できます。これは通常、具体的な構成に使用する実装クラスの静的定義であるため、xml が適しています。
ランタイムに基づいてインプリメンターを選択する必要がある場合は、コードを記述してそれらを選択し、コンテナーに通知する必要があります。
たとえば、 と を使用PropertySources
しPropertyPlaceholderConfigurer
ます。
String service = "example.NormalService";
if (BOSS_USERNAME.equals(System.getProperty("user.name")))
service = "example.BossService";
ctx.getEnvironment().getPropertySources().addFirst(new PropertiesPropertySource("service", service));
<bean id="service" class="${service}" />
ServiceFactoryBean、外部 ServiceFactory、SPEL などでも同じことができます...
たぶん、実行時に実装を置き換えることに関心があるかもしれません。つまり、コンテナがいつ更新されたかに依存するすべての Bean の Service 実装を変更することです。(破棄と更新なし)。
私の知る限り、フレームワークはそれを行うための明確な方法を提供していません。
スプリング バインディングを確認する必要があるように思えます。
public String create(@Valid Market market, BindingResult bindingResult, Model uiModel, HttpServletRequest httpServletRequest) {
したがって、これは Market オブジェクトのフィールドに一致するリクエスト パラメータを受け取り、それらをそのオブジェクトに設定します。@Valid アノテーションがあるため、params/object も検証されます。このバインディングは、PropertyEditors または Converters でカスタマイズできます。
マーケット オブジェクトに @Configurable アノテーションが付けられている場合、Spring が Bean を作成するときに @Autowired および @Value アノテーションを使用して Bean を構成できます。