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;
}       




}

我的问题是最后我返回缓存但我的主函数中的新对象将保存实例的值。在方面内部,它的行为应如此:第一次实例化资源时,缓存和实例将保持相同的值,第二次,它们将不同。

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. 虽然这个想法很好,但存在一个技术问题:您不能从around() : execution(*.new(..))通知中返回对象,因为所讨论的对象尚未完全实例化,并且周围通知隐式返回void。自己尝试并将建议返回类型更改为void并且不返回任何内容。它有效 - 惊喜,惊喜!;-)

那么你能做什么呢?改为使用around() : call(*.new(..))以操作构造函数调用的结果。您甚至可以通过不proceed()从那里调用来完全跳过对象创建。

有几种方法可以利用它来使您的资源对象缓存为单例。但是因为您特别要求一个pertypewithin用例,所以我将选择一个涉及这种方面实例化的解决方案。这里的缺点是您需要结合两个方面才能达到预期的结果。

示例资源类:

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 回答