AspectJ正式在切点上未绑定

时间:2018-12-15 14:11:05

标签: java aspectj pointcut

我有以下课程:

public class Population {
    private int population;

    public Population()
    {
        population = 0;
    }

    public void newYear()
    {
        population += 10;
    }

    public int getPopulation() {
        return population;
    }
}

以及以下方面

public aspect StatisticsAspect {

    private static int year = 0;

    pointcut operation(Population caller) : call(* Population.newYear());

    after(Population caller) : operation(caller)
    {
        System.out.println("New Year: " + year);
        year++;

        System.out.println("Population: " + caller.getPopulation());
    } 
}

现在,我希望每次调用newYear()时,将“统计信息”打印到控制台。 不幸的是,我收到ajc: formal unbound in pointcut错误。

我需要进行哪些更改才能使其正常工作?

1 个答案:

答案 0 :(得分:1)

我稍微重构了您的代码,因为getPopulation()是一个不好的名字,违反了约定。不是名称所暗示返回的总体对象,而是总体的大小。

关于您的方面,caller的命名也很糟糕,因为对象不是呼叫者,而是被呼叫者或呼叫的目标。我只是将参数重命名为population,因为这次它实际上包含一个填充对象。然后,将其绑定到target()参数,以使您的错误消息消失。

我也从call()切换到execution()切入点,因为将代码编织到执行的方法中而不是编织到调用该方法的每个位置上,效率更高。

我还确保在第一个新年结束并且人口增长之后,计数从1开始,而不是0。我通过使用++size而不是size++来做到这一点,即使用pre-而不是post-increment。

现在代码如下:

package de.scrum_master.app;

public class Population {
  private int size;

  public Population() {
    size = 0;
  }

  public void newYear() {
    size += 10;
  }

  public int getSize() {
    return size;
  }

  public static void main(String[] args) {
    Population population1 = new Population();
    population1.newYear();
    population1.newYear();
    Population population2 = new Population();
    population2.newYear();
    population2.newYear();
  }
}
package de.scrum_master.aspect;

import de.scrum_master.app.Population;

public aspect StatisticsAspect {
  private static int year = 0;

  pointcut operation(Population population) :
    execution(* Population.newYear()) && target(population);

  after(Population population) : operation(population) {
    System.out.printf("Population for year %d = %d%n", ++year, population.getSize());
  }
}

现在查看控制台日志:

Population for year 1 = 10
Population for year 2 = 20
Population for year 3 = 10
Population for year 4 = 20

您能发现问题吗?您的年度总计数器为一个,但人口总数为多个。实际上,您应该为每个人口设置一个年计数器,以便正确计算统计信息。这可以通过使用每个目标(即每个人口)的一个方面实例而不是单例方面来完成,当然也可以不再使年份为静态:

package de.scrum_master.aspect;

import de.scrum_master.app.Population;

public aspect StatisticsAspect pertarget(execution(Population.new(..))) {
  private int year = 0;

  pointcut operation(Population population) :
    execution(* Population.newYear()) && target(population);

  after(Population population) : operation(population) {
    System.out.printf("%s size for year %d = %d%n", population, ++year, population.getSize());
  }
}

这里,pertarget(execution(Population.new(..)))的意思是:每个Population构造函数执行(即每个创建的对象)创建一个方面实例。

现在统计信息是正确的(为了显示对象ID,我还稍微更改了日志消息,以便我们可以看到哪个消息属于哪个人口):

de.scrum_master.app.Population@1d44bcfa size for year 1 = 10
de.scrum_master.app.Population@1d44bcfa size for year 2 = 20
de.scrum_master.app.Population@266474c2 size for year 1 = 10
de.scrum_master.app.Population@266474c2 size for year 2 = 20