如何在不使用构造函数的情况下初始化AspectJ方面?

时间:2013-04-11 16:57:46

标签: java aspectj

我的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的实例尚未就绪。< / p>

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

2 个答案:

答案 0 :(得分: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())

应该排除你不想截获的内容。

答案 1 :(得分:0)

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

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

但实际上,这对我来说是一种糟糕的形式。在构造Child期间在某处应用包含方面的建议似乎是循环依赖。我试图重构(也许是多方面)以避免循环。