用于更改类变量的方法的切入点

时间:2012-10-21 07:22:44

标签: aop aspectj

是否可以编写与更改特定类类型的类变量的方法匹配的有效切入点? 这样做的关键是我的类有一个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)

1 个答案:

答案 0 :(得分:3)

没有。 getset切入点仅适用于成员,但不适用于局部变量。因此,您的示例仅匹配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