1

次のようなクラスがあるとします。

public class MyClass {

   @ThreadScoped    
   private Collection<String> words = new ArrayList<String>();

   public void addWord(String word) {
        words.add(word);
   }

}

実行時には、このクラスのインスタンスは 1 つしかありませんが、複数のスレッドからの呼び出しを受け入れます。

クラスを作成する開発者が、マルチスレッドアクセス用に作成しているという事実を無視して、フィールドに「スレッドスコープ」として注釈を付けられるようにしてほしい。

まるでwordsフィールドがThreadLocal. メソッドが複数回呼び出された場合でも、コレクションはスレッドに結び付けられる必要があります。

私はsetおよびgetポイント カットを見てきましたが、オブジェクトにフィールドを設定する必要がなく、クラスのスレッド セーフを台無しにするそれらを利用する方法がわかりません。

プロキシやリフレクションなど、側面を利用しない別の方法はありますか?

4

2 に答える 2

2

設計には、矛盾する可能性のある決定がいくつかあるようです。

  • のインスタンスは1つだけですMyClass

  • 各スレッドが独自のバージョンのwordsフィールドを表示するようにします。

この目的でAspectJを使用するのはやり過ぎかもしれないように私には思えます。スレッド固有のアクセスは横断的関心事と見なすことができると思いますが、AOPがこれに対処する方法であるかどうかはわかりません。AspectJを試す前に、まず純粋なJavaコードの再設計を検討します。

正直なところ、2番目の効果を実現する最も簡単な方法は、各スレッドが独自のインスタンスを持つことだと思いますMyClass。各スレッドに明示的に渡すことができない場合は、を使用ThreadLocalして適切なインスタンスへのアクセスを提供することもできます。MyClass

MyClass複数のスレッドで共有されているフィールドがある場合は、リファクタリングMyClassを検討して、フィールドを2つのクラスに分割することを検討してください。これにより、スレッド固有のフィールドが共有フィールドから分離され、それぞれのケースを異なる方法で処理できるようになります。

編集:

あなたのコメントについて少し考えましたが、AOPを使用して、開発者からフィールドの実装を本質的に隠そうとしているようです。プログラミングインターフェイスを実際の実装から分離する問題は、AOPに解決することなく、オブジェクト指向プログラミングでほとんど解決されています。

あなたの場合、そのフィールドのプライベートMyClass宣言を保持するために抽象スーパークラスを使用し、次にいくつかのgetterメソッドとsetterメソッドを使用してそれを処理する方法があります。そうすれば、他に影響を与えることなく実際の実装を変更できます。MyClass

public abstract AbstractMyClass {
    private ... words = ...;

    protected Collection<String> getWords() {
        ...
    }
}

public Myclass extends AbstractMyClass {
   public void addWord(String word) {
        this.getWords().add(word);
   }
}
于 2013-02-27T17:40:49.913 に答える
1

いくつかの理由により、一般的な方法で AspectJ を使用することは不可能です。

  • コレクションであっても、作成時にオブジェクトを複製する一般的な方法はありません。次に、プリミティブ型について考えます。
  • ThreadLocal特定のポイントカットでオブジェクトをクローンしたとしても、set()オブジェクトのメソッド呼び出しをクローンにリダイレクトするにはどうすればよいでしょうか?

そうは言っても、魔法のような処理を行うソース コード プリプロセッサを作成する方法があります (問題のオブジェクトとそれらに対するメソッド呼び出しをラップします)。プリプロセッサは、通常はjavacでコンパイルする前に、そのコードをソースに織り込みます。

とにかく、thkalaが言ったように、最も簡単な解決策は、開発者に実際にThreadLocal自分で使用するか、APIによって提供されるトレッドローカルラッパーを使用するように教えることです(実装する必要があります)。

于 2013-03-16T13:31:47.217 に答える