私は独自のスコープ (つまり、 を実装するクラスorg.springframework.beans.factory.config.Scope
) を作成しており、いくつかの Bean を注入する必要があります。それ、どうやったら出来るの?
背景: どの Bean がスコープに入るかを定義できるように、Spring は最初にすべてのスコープ Bean を作成する必要があります。しかし、そもそもスコープを構築するために必要な Bean はどうでしょうか?
私は独自のスコープ (つまり、 を実装するクラスorg.springframework.beans.factory.config.Scope
) を作成しており、いくつかの Bean を注入する必要があります。それ、どうやったら出来るの?
背景: どの Bean がスコープに入るかを定義できるように、Spring は最初にすべてのスコープ Bean を作成する必要があります。しかし、そもそもスコープを構築するために必要な Bean はどうでしょうか?
かなり安全だと思われるこの回避策を思いつきましたが、コメントを聞きたいです(または、私の答えがより良いアイデアを提供してくれるかもしれません):
@Autowired
)「スコープ コンフィギュアラー」Bean を作成します。
public CustomScopeConfigurer {
@Autowired private Foo foo;
private CustomScope scope;
public CustomScopeConfigurer( CustomScope scope ) {
this.scope = scope;
}
@PostConstruct
public void initScope() {
scope.setFoo( foo );
}
}
この構成 Bean は遅延であってはなりません。
理由:
スコープ自体は、最初の Bean の前に作成されるため、オートワイヤーを使用できません。後で作成される可能性がありますが、他のすべての Bean の前に作成されることを確認できます。そのため、自動配線は確実に機能しません。
コンフィギュア Bean は、他のすべての Bean と一緒に作成されますが、スコープの後に作成されます。そのため、自動配線が機能します。
コンフィギュアラー Bean は遅延初期化されないため、アプリケーションの残りの部分がアプリケーション コンテキストを参照できるようになる前に作成されます。これは、スコープの Bean (つまり、 を持つ Bean @Scope("custom")
) が現時点で作成されていないことを意味します - スコープはまだ「アクティブ」にできません -> Spring はまだ Bean をそこに入れようとしません。
スコープ自体は通常、静的定数としてどこかに作成されます。そのため、コンストラクターに引数として渡す必要があります。
これは非常に簡単に行うことができます。
以下のカスタム スコープ クラスを検討してください。
package com.way2learn;
import java.util.Map;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.Scope;
public class MyCustomScope implements Scope{
private Map<String, Object> scope;
public void setScope(Map<String, Object> scope) {
this.scope = scope;
}
@Override
public Object get(String name, ObjectFactory<?> objectFactory) {
checkAndClear();
Object bean=scope.get(name);
if(bean==null){
bean=objectFactory.getObject();
scope.put(name,bean);
}
return bean;
}
private void checkAndClear() {
//Some logic to check condition and clear the scope
}
//optional methods
@Override
public Object remove(String name) {
// TODO Auto-generated method stub
return null;
}
@Override
public void registerDestructionCallback(String name, Runnable callback) {
}
@Override
public Object resolveContextualObject(String key) {
// TODO Auto-generated method stub
return null;
}
@Override
public String getConversationId() {
// TODO Auto-generated method stub
return null;
}
}
に依存していjava.util.Map
ます。
注釈は後でのみ機能する@Autowired
ため、それを使用して自動配線することはできません。@Autowired
AutoWiredAnnotationBeanPostProcessor
ただし、カスタム スコープは の前に登録されAutoWiredAnnotationBeanPostProcessor
ます。
したがって、以下のように手動でクラスにMap
注入できます。MyCustomScope
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd">
<util:map key-type="java.lang.String" value-type="java.lang.Object" id="custScopeMap"/>
<bean id="myCustomScope" class="com.way2learn.MyCustomScope">
<property name="scope" ref="custScopeMap"/>
</bean>
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="myScope" value-ref="myCustomScope"/>
</map>
</property>
</bean>
</beans>
私はそれを試してみました。それは正常に動作します。そして、Aaron Digulla's
答えにバグが見つかりました
次のシナリオを考えてみましょう。最初Spring's CustomScopeConfigurer
の Bean が作成され、すぐにCustomScope
Bean が作成され、カスタム スコープを使用する準備が整います。しばらくAaron Digulla's CustomScopeConfigurer
すると、 foo を に初期化する が作成されCustomScope
ます。CustomScope registration
しかし、Bean の作成前後にカスタム スコープ Bean が作成された場合はどうなるAaron Digulla's CustomScopeConfigurer
でしょうか。これらの Bean の場合、Bean に foo はありませんCustomScope
。