2

是否可以编写一个有效的切入点来匹配更改特定类类型的类变量的方法?这样做的目的是我的类有一个 lastModificationDate,每当类变量发生更改时,我都想将其更新为最新日期。

方法示例:

public void stupidMethod() {

 ...
 for (int i = 0; i < 100; i++) this.var = whatever;
 ...
} <--- I want to match here

目前我有这个,但它不是很理想:

after(SimpleEntity entity) : set(* *.*) && target(entity) && !within(SimpleEntityAspect)
4

1 回答 1

3

不存在,get并且set切入点仅适用于成员,但不适用于局部变量。因此,您的示例将仅匹配SimpleEntity对象的成员变量分配。如果这是您想要做的,请重新表述您的问题的标题和内容,以明确您真正想要实现的目标。还请提供更多代码上下文,例如类型声明的相关部分SimpleEntity

我现在最好的猜测是,您希望匹配更改特定类型成员的方法的退出点。如果您在建议中还告诉我们您究竟想做什么(例如打印方法名称或分配的值等),我们可能会更好地帮助您。


更新:好的,我找到了一个使用pertarget方面实例化加上 ITD(类型间声明)的解决方案,可以满足您的需求。我没有测试性能或内存消耗,我把它留给你。

示例实体类:

public class SimpleEntity {
    private static int currentId = 1;

    private int id;
    private String name;
    private long lastModification;

    public SimpleEntity(String name) {
        this.id = currentId++;
        this.name = name;
    }

    public void stupidMethod(final int count) {
        for (int i = 0; i < count; i++)
            name = name.replaceFirst("_[0-9]+$", "") + "_" + i;
    }

    public int tripleValue(final int value) {
        return 3 * value;
    }

    @Override
    public String toString() {
        return "SimpleEntity [id=" + id + ", name=" + name + ", lastModification=" + lastModification + "]";
    }
}

创建和使用实体的示例应用程序类:

public class Application {
    public static void main(String[] args) {
        SimpleEntity entity1 = new SimpleEntity("Adam");
        entity1.stupidMethod(3);
        entity1.tripleValue(11);
        entity1.stupidMethod(3);
        SimpleEntity entity2 = new SimpleEntity("Eve");
        entity2.stupidMethod(3);
        entity1.tripleValue(22);
        entity2.stupidMethod(3);
    }
}

执行 Piotr Blasiak 要求的方面:

public privileged aspect SetterCallingMethodAspect pertarget(entitySetter(SimpleEntity)) {
    private static interface MemberChangeDetector {}
    private boolean MemberChangeDetector.changed;

    declare parents : SimpleEntity implements MemberChangeDetector;

    pointcut entitySetter(SimpleEntity entity) :
        set (* SimpleEntity+.*) && target(entity) && !within(SetterCallingMethodAspect);
    pointcut constructorExecution() :
        execution(*.new(..)) && !cflow(adviceexecution());
    pointcut methodExecution() :
        execution(* *(..)) && !cflow(adviceexecution());

    after(SimpleEntity entity) : entitySetter(entity) {
        entity.changed = true;
        System.out.println(this + ",  " + thisJoinPointStaticPart + "  ->  " + entity);
    }

    after(SimpleEntity entity) : if(entity.changed) && target(entity)
        && (constructorExecution() || methodExecution())
    {
        entity.changed = false;
        entity.lastModification = System.nanoTime();
        System.out.println(
            this + ",  " + thisJoinPointStaticPart +
            "  ->  update lastModification to " + entity.lastModification
        );
    }
}

示例控制台输出:

SetterCallingMethodAspect@bb6ab6,  set(int SimpleEntity.id)  ->  SimpleEntity [id=1, name=null, lastModification=0]
SetterCallingMethodAspect@bb6ab6,  set(String SimpleEntity.name)  ->  SimpleEntity [id=1, name=Adam, lastModification=0]
SetterCallingMethodAspect@bb6ab6,  execution(SimpleEntity(String))  ->  update lastModification to 1863715110885880
SetterCallingMethodAspect@bb6ab6,  set(String SimpleEntity.name)  ->  SimpleEntity [id=1, name=Adam_0, lastModification=1863715110885880]
SetterCallingMethodAspect@bb6ab6,  set(String SimpleEntity.name)  ->  SimpleEntity [id=1, name=Adam_1, lastModification=1863715110885880]
SetterCallingMethodAspect@bb6ab6,  set(String SimpleEntity.name)  ->  SimpleEntity [id=1, name=Adam_2, lastModification=1863715110885880]
SetterCallingMethodAspect@bb6ab6,  execution(void SimpleEntity.stupidMethod(int))  ->  update lastModification to 1863715112627443
SetterCallingMethodAspect@bb6ab6,  set(String SimpleEntity.name)  ->  SimpleEntity [id=1, name=Adam_0, lastModification=1863715112627443]
SetterCallingMethodAspect@bb6ab6,  set(String SimpleEntity.name)  ->  SimpleEntity [id=1, name=Adam_1, lastModification=1863715112627443]
SetterCallingMethodAspect@bb6ab6,  set(String SimpleEntity.name)  ->  SimpleEntity [id=1, name=Adam_2, lastModification=1863715112627443]
SetterCallingMethodAspect@bb6ab6,  execution(void SimpleEntity.stupidMethod(int))  ->  update lastModification to 1863715114328497
SetterCallingMethodAspect@12d03f9,  set(int SimpleEntity.id)  ->  SimpleEntity [id=2, name=null, lastModification=0]
SetterCallingMethodAspect@12d03f9,  set(String SimpleEntity.name)  ->  SimpleEntity [id=2, name=Eve, lastModification=0]
SetterCallingMethodAspect@12d03f9,  execution(SimpleEntity(String))  ->  update lastModification to 1863715120762834
SetterCallingMethodAspect@12d03f9,  set(String SimpleEntity.name)  ->  SimpleEntity [id=2, name=Eve_0, lastModification=1863715120762834]
SetterCallingMethodAspect@12d03f9,  set(String SimpleEntity.name)  ->  SimpleEntity [id=2, name=Eve_1, lastModification=1863715120762834]
SetterCallingMethodAspect@12d03f9,  set(String SimpleEntity.name)  ->  SimpleEntity [id=2, name=Eve_2, lastModification=1863715120762834]
SetterCallingMethodAspect@12d03f9,  execution(void SimpleEntity.stupidMethod(int))  ->  update lastModification to 1863715121338606
SetterCallingMethodAspect@12d03f9,  set(String SimpleEntity.name)  ->  SimpleEntity [id=2, name=Eve_0, lastModification=1863715121338606]
SetterCallingMethodAspect@12d03f9,  set(String SimpleEntity.name)  ->  SimpleEntity [id=2, name=Eve_1, lastModification=1863715121338606]
SetterCallingMethodAspect@12d03f9,  set(String SimpleEntity.name)  ->  SimpleEntity [id=2, name=Eve_2, lastModification=1863715121338606]
SetterCallingMethodAspect@12d03f9,  execution(void SimpleEntity.stupidMethod(int))  ->  update lastModification to 1863715121829729
于 2012-10-22T09:12:25.820 回答