1

私は「Spring Recipes」の本を読んでいて、春の「魔法」を例を挙げて調査しようとしています。それが私が持っているものです。Bean クラスSequenceGenerator :

public class SequenceGenerator {
    private List<Object> suffixes;
    //..... 
    public void setSuffixes(List<Object> suffixes) {
        this.suffixes = suffixes;
    }
    public synchronized String getSequence() {
        StringBuffer buffer = new StringBuffer();            
        for (Object suffix : suffixes) {
            buffer.append(suffix);
            buffer.append("-");
        }
        return buffer.toString();
    }
}

メインクラス:

public class Main {
    public static void main(String[] args) {
        ApplicationContext context =
                new ClassPathXmlApplicationContext("beans.xml");
        SequenceGenerator generator =
                (SequenceGenerator) context.getBean("sequenceGeneratorSet");
        System.out.println(generator.getSequence());
    }
}

XML 構成:

<bean id="sequenceGeneratorSet" class="com.apress.springrecipes.sequence.SequenceGenerator">
        <property name="initial" value="100000"/>
        <property name="suffixes">
            <set>
                <value>A</value>
                <value>A</value>
                <bean class="java.net.URL">
                    <constructor-arg value="http" />
                    <constructor-arg value="www.apress.com" />
                    <constructor-arg value="/" />
                </bean>
            </set>
        </property>
    </bean>

xml では、意図的にタグを使用して結果を監視しています。また、同じ値「A」を 2 回書きました。Spring は、Bean クラスの型定義として、"suffixes" プロパティの ArrayList を注入したことに気付きました。ただし、「A」値を 1 つだけ含む、出力のセットのように動作します。Spring が内部的にそれをどのように理解できるか、誰にもわかりませんか?

4

2 に答える 2

4

Spring には、コンテキストを生成するためのメソッド呼び出しの膨大なスタックがあります。XML コンテキストを解析すると、Spring はRootBeanDefinitionBean (クラス、プロパティなど) を記述するオブジェクトとPropertyValues、プロパティの名前 ( <property>) とその値を含むオブジェクトを生成します。

この場合、それは である を作成しManagedSetます

管理された Set 値を保持するために使用されるタグ コレクション クラス。これにはランタイム Bean 参照が含まれる場合があります (Bean オブジェクトに解決されます)。

AあなたとURL価値を保持します。

上記は、実際の Bean オブジェクトのフィールドのいずれかが初期化される前に行われます (BeanPostProcessors処理、プロキシなど) が、インスタンス自体 (デフォルトでフィールド値を に設定null) が作成されます。これは、空のコンストラクターを作成し、デバッグ中にブレークポイントを追加することで確認できます。

さらに下の ではAbstractApplicationContext#refresh()finishBeanFactoryInitialization()初期化が最終的に行われる場所で呼び出されます。BeanDefinition以前に作成されたそれぞれと対応するPropertyValuesに対して、Spring は作成中の Bean を呼び出しapplyPropertyValues()ますBeanFactory

あなたのsuffixesフィールドについて、Spring は期待されるタイプと実際のタイプが一致しないことを認識します。Aは、 (the ) から実際の型に変換するためにTypeConverterDelegateどちらのPropertyEditororを使用するかを判断します。. この場合、 を使用します。そのエディターは、宣言されているコレクションのタイプで呼び出します。あなたにとって、それは. そうConversionServicePropertyValuesManagedSetFieldListCustomCollectionEditorcreateCollection()FieldList

protected Collection createCollection(Class collectionType, int initialCapacity) {
    if (!collectionType.isInterface()) {
        try {
            return (Collection) collectionType.newInstance();
        }
        catch (Exception ex) {
            throw new IllegalArgumentException(
                    "Could not instantiate collection class [" + collectionType.getName() + "]: " + ex.getMessage());
        }
    }
    else if (List.class.equals(collectionType)) { // US HERE
        return new ArrayList(initialCapacity);
    }
    else if (SortedSet.class.equals(collectionType)) {
        return new TreeSet();
    }
    else {
        return new LinkedHashSet(initialCapacity);
    }
}

を作成しArrayListます。以前の の各要素についてSet、必要に応じて要素を変換してから に追加しようとしArrayListます。を使用してBeanWrapperImpl、プロパティ値を設定します。これを行うためにMethod、リフレクションを通じてセッターを見つけ、ArrayList.

Spring は、コンテキストで宣言された各 Bean および各プロパティに対して、これと同じロジックを実行します。

于 2013-09-04T21:08:29.773 に答える