12

私は独自のスコープ (つまり、 を実装するクラスorg.springframework.beans.factory.config.Scope) を作成しており、いくつかの Bean を注入する必要があります。それ、どうやったら出来るの?

背景: どの Bean がスコープに入るかを定義できるように、Spring は最初にすべてのスコープ Bean を作成する必要があります。しかし、そもそもスコープを構築するために必要な Bean はどうでしょうか?

4

2 に答える 2

4

かなり安全だと思われるこの回避策を思いつきましたが、コメントを聞きたいです(または、私の答えがより良いアイデアを提供してくれるかもしれません):

  1. スコープを定義し、セッターを指定します (を使用する代わりに@Autowired)
  2. 「スコープ コンフィギュアラー」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 は遅延であってはなりません。

理由:

  1. スコープ自体は、最初の Bean の前に作成されるため、オートワイヤーを使用できません。後で作成される可能性がありますが、他のすべての Bean の前に作成されることを確認できます。そのため、自動配線は確実に機能しません。

  2. コンフィギュア Bean は、他のすべての Bean と一緒に作成されますが、スコープの後に作成されます。そのため、自動配線が機能します。

  3. コンフィギュアラー Bean は遅延初期化されないため、アプリケーションの残りの部分がアプリケーション コンテキストを参照できるようになる前に作成されます。これは、スコープの Bean (つまり、 を持つ Bean @Scope("custom")) が現時点で作成されていないことを意味します - スコープはまだ「アクティブ」にできません -> Spring はまだ Bean をそこに入れようとしません。

  4. スコープ自体は通常、静的定数としてどこかに作成されます。そのため、コンストラクターに引数として渡す必要があります。

于 2012-08-17T15:03:13.723 に答える
2

これは非常に簡単に行うことができます。

以下のカスタム スコープ クラスを検討してください。

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ため、それを使用して自動配線することはできません。@AutowiredAutoWiredAnnotationBeanPostProcessor

ただし、カスタム スコープは の前に登録され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 が作成され、すぐにCustomScopeBean が作成され、カスタム スコープを使用する準備が整います。しばらくAaron Digulla's CustomScopeConfigurerすると、 foo を に初期化する が作成されCustomScopeます。CustomScope registrationしかし、Bean の作成前後にカスタム スコープ Bean が作成された場合はどうなるAaron Digulla's CustomScopeConfigurerでしょうか。これらの Bean の場合、Bean に foo はありませんCustomScope

于 2015-11-29T13:22:47.360 に答える