1

Spring 経由で注入されるいくつかのリソースを使用するBuilderがあります。これは次のようになります。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class SandBoxBuilder {
    private final SandUtil sandUtil;
    private Sand sand;
    private Box box;

    @Autowired
    public SandBoxBuilder(SandUtil sandUtil) {
        this.sandUtil = sandUtil;
    }

    public SandBoxBuilder setSand(Sand sand) {
        this.sand = sand;
        return this;
    }

    public SandBoxBuilder setBox(Box box) {
        this.box = box;
        return this;
    }

    public SandBox build() {
        SandBox sandBox = new SandBox(sand);
        sandUtil.changeBox(sandBox, box);
        return sandBox;
    }
}

これに関する問題は、スレッドセーフではないことです。このビルダーはシングルトンであってはならないことはわかっていますがSandUtil、ビルダーを配線して使用する場所に注入せずに、Spring 注入リソース ( ) を使用する方法がわかりません。

春によって注入されたシングルトンを利用するスレッドセーフビルダーを実装するにはどうすればよいですか?

解決

いくつかのアーキテクチャ上の制約により、呼び出しクラスにユーティリティを挿入できませんでした。最終的に、Spring リソースへの参照を持つビルダーの新しいインスタンスを返すファクトリー ビルダー Bean を実装しました。

ソリューションの実装

@Component
public class SandBoxBuilderFactory {
    private final SandUtil sandUtil;

    @Autowired
    public SandBoxBuilderFactory(SandUtil sandUtil) {
        this.sandUtil = sandUtil;
    }

    public Builder newBuilder(){
        return new Builder(sandUtil);
    }

    public static class Builder {
        private final SandUtil sandUtil;
        private Sand sand;
        private Box box;

        private Builder(SandUtil sandUtil) {
            this.sandUtil = sandUtil;
        }

        public Builder setSand(Sand sand) {
            this.sand = sand;
            return this;
        }

        public Builder setBox(Box box) {
            this.box = box;
            return this;
        }

        public SandBox build() {
            SandBox sandBox = new SandBox(sand);
            sandUtil.changeBox(sandBox, box);
            return sandBox;
        }

    }
}

使用法

newBuilder().setBox(box).setSand(sand).build();
4

3 に答える 3

0

これのスレッドセーフでない部分は、sandUtil フィールドに関係していると思いますか?

changeBox メソッドで外部ロックを使用して、同期アクセスを確保できます。

それ以外の場合は、おそらく「プロトタイプ」Bean スコープが役立ちますか?

http://docs.spring.io/spring/docs/3.0.x/reference/beans.html#beans-factory-scopes

http://docs.spring.io/spring/docs/3.0.x/reference/beans.html#beans-factory-scopes-prototype

于 2013-10-01T17:09:40.837 に答える
0

最近、春のIOCについてあまり知りません。私は、同様の内部作業を提供するはずの Tapestry IOC を多く使用しています。

まず第一に、シングルトンは定義ごとにスレッドセーフでなければなりません。したがって、使用するたびにビルダーを作成する場合、ビルダーはスレッドセーフである必要はありません。SandUtil は、それ自体がスレッドセーフである必要があります。

これはコントラクトのようなものです。シングルトン サービスの場合、複数のスレッドに注入されます。したがって、シングルトン サービスはスレッドセーフである必要があります (同期メソッド、共有ロック、同期オブジェクトなど)。サービスが PerThread であり、同じサービスが単一のスレッド内でのみ使用されることを意味する場合、スレッドセーフである必要はありません。

そのため、SandUtil がスレッドセーフであることを確認し、Sandbox が PerThread または PerOccurence (注入されるたびに新しいインスタンスが作成される) の場合は問題ありません。

ビルダーの単一のインスタンスがスレッド内でのみ使用されるかどうかを確認できないため、ビルダーをスレッドセーフにしたい場合 - パフォーマンスをあまり気にしない場合 - ビルダーのすべての非プライベート メソッドに synchronized キーワードを追加するだけです。クラス。これは貧弱な同時実行制御です。それ以外の場合は、元の Java レッスンのような同時実行制御に関するいくつかのチュートリアルを確認してください。

于 2013-10-01T17:08:06.430 に答える