1

我的 AspectJ 方面如下所示:

@Aspect
public class MyAspect {
  private Child child;
  public MyAspect() {
    this.child = new Child();
  }
  @Around("... skipped ...")
  public Object wrap(ProceedingJoinPoint point) throws Throwable {
    // some custom functionality
    return point.proceed();
  }
}

这不起作用,因为在构造切入点Child的过程中wrap()会调用它并导致运行时异常,因为 的实例MyAspect尚未准备好。

MyAspect是否可以在实例化后以某种方式告诉 AspectJ 调用某个方法?

4

2 回答 2

3

新答案:

这是一个示例驱动程序类Child

public class Child {
    private String name;

    public Child(String name) {
        this.name = name;
        System.out.println("Constructing child named " + this.name);
    }

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

    public static void main(String[] args) {
        Child myChild = new Child("Penélope");
        System.out.println("My child is named " + myChild.getName());
        myChild.setName("María Elena");
        System.out.println("My child is now named " + myChild.getName());
    }
}

这是一个MyAspect拦截公共方法和构造函数执行Child的切面,但不包括切面构造函数:

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class MyAspect {
    private Child child;

    public MyAspect() {
        child = new Child("Scarlett");
        System.out.println("Aspect child is named " + child.getName());
        child.setName("Cristina");
        System.out.println("Aspect child is now named " + child.getName());
    }

    @Around(
        "(execution(public * Child.*(..)) || execution(public Child.new(..)))" +
        "&& !cflow(initialization(MyAspect.new()))"
    )
    public Object wrap(ProceedingJoinPoint point) throws Throwable {
        System.out.println(point.getStaticPart());
        return point.proceed();
    }
}

这是示例输出:

Constructing child named Scarlett
Aspect child is named Scarlett
Aspect child is now named Cristina
execution(void Child.main(String[]))
execution(Child(String))
Constructing child named Penélope
execution(String Child.getName())
My child is named Penélope
execution(void Child.setName(String))
execution(String Child.getName())
My child is now named María Elena

您可以看到Child在方面构造过程中没有截取任何连接点。顺便说一句,否则你NoAspectBoundException无论如何都会得到。;-)


老答案:

您可以将切入点与(未经测试的)类似的东西结合起来:

... && !cflow(MyAspect.new())

这应该排除您不希望拦截的内容。

于 2013-04-11T21:22:33.170 回答
0

也许您最好尝试在建议中进行初始化。例如-

after() : execution(MyAspect.new()) {
  this.child = new Child();
}

但实际上,这让我觉得这是一种糟糕的形式。在构造过程中在某处应用包含方面的建议Child似乎是一种循环依赖。我会尝试重构(也许是多个方面)以避免循环。

于 2013-04-11T20:38:45.967 回答