0

AspectJ とpertypewithin句を使用してシングルトン パターンを実行しようとしています。

これは、節を完全に理解するための教育目的です。私はすでに他の手法を使用してこれを行っていますが、希望どおりに機能させることはできません。

package resourceManager;



//For every Type that extends resource
public aspect ResourcePool pertypewithin(resource+) {
    //The resource      
    public Object cached;



Object around(Object instance): execution( *.new(..))&&!within(resource)&&this(instance){
    if(cached==null)
        {
        proceed(instance);
        cached=instance;
        }


    System.out.println(instance+" "+ cached);

    return cached;
}       




}

私の問題は、最後にキャッシュを返しますが、メイン関数の新しいオブジェクトがインスタンスの値を保持することです。アスペクト内では、本来の動作をします。最初にリソースをインスタンス化すると、キャッシュされ、インスタンスは同じ値を保持しますが、2 回目は異なります。

instance: resourceManager.RB@4ffac352 cached: resourceManager.RB@4ffac352
instance: resourceManager.RB@582d6583 cached: resourceManager.RB@4ffac352

しかし、2 つの新しいオブジェクトを印刷すると、次のようになります。

resourceManager.RB@4ffac352
resourceManager.RB@582d6583
4

1 に答える 1

0

最近編集された後、今日この古い質問を見つけました。

必要なのは、に基づくキャッシング ソリューションですpertypewithin。アイデアは素晴らしいものですが、技術的な問題が 1 つあります。問題around() : execution(*.new(..))のオブジェクトがまだ完全にインスタンス化されておらず、around アドバイスが暗黙的に を返すため、アドバイスからオブジェクトを返すことはできませんvoid。自分で試して、アドバイスの戻り値の型を に変更し、void何も返さないようにしてください。それはうまくいきます - 驚き、驚き!;-)

代わりに何ができますか?around() : call(*.new(..))コンストラクタ呼び出しの結果を操作するために代わりに使用してください。そこから呼び出さないことで、オブジェクトの作成を完全にスキップすることもできますproceed()

リソース オブジェクトをシングルトンにキャッシュするためにこれを利用する方法はいくつかあります。しかし、pertypewithinユースケースを具体的に求められたので、このタイプのアスペクトのインスタンス化を含むソリューションを選択します。ここでの欠点は、目的の結果を得るために 2 つの側面を組み合わせる必要があることです。

リソース クラスの例:

package de.scrum_master.resource;

public class Foo {}
package de.scrum_master.resource;

public class Bar {}

各リソース タイプの複数のインスタンスを作成するドライバー アプリケーション:

package de.scrum_master.app;

import de.scrum_master.resource.Bar;
import de.scrum_master.resource.Foo;

public class Application {
    public static void main(String[] args) {
        System.out.println(new Foo());
        System.out.println(new Foo());
        System.out.println(new Bar());
        System.out.println(new Bar());
    }
}

リソース プールの側面の変更されたバージョン:

package de.scrum_master.resourceManager;

public aspect ResourcePool pertypewithin(de.scrum_master.resource..*) {
    private Object cached;

    after(Object instance) : execution(*.new(..)) && this(instance) {
        // Not necessary because SingletonAspect only proceeds for 'cache == null' 
        //if (cached != null) return;
        cached = instance;
        System.out.println("Cached instance = " + cached);
    }

    public Object getCachedInstance() {
        return cached;
    }
}

オブジェクト作成時にオブジェクトをスキップし、キャッシュされたオブジェクトを返すアスペクト:

package de.scrum_master.resourceManager;

public aspect SingletonAspect {
    Object around() : call(de.scrum_master.resource..*.new(..)) {
        Object cached = ResourcePool
            .aspectOf(thisJoinPointStaticPart.getSignature().getDeclaringType())
            .getCachedInstance();
        return cached == null ? proceed() : cached;
    }
}

コンソール ログ:

Cached instance = de.scrum_master.resource.Foo@5caf905d
de.scrum_master.resource.Foo@5caf905d
de.scrum_master.resource.Foo@5caf905d
Cached instance = de.scrum_master.resource.Bar@8efb846
de.scrum_master.resource.Bar@8efb846
de.scrum_master.resource.Bar@8efb846
于 2016-07-23T13:10:50.573 に答える