AspectJ正式切入点未绑定 [英] AspectJ formal unbound in cutpoint

查看:312
本文介绍了AspectJ正式切入点未绑定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下课程:

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错误.

Now I want that everytime when newYear() is called, that the "statistics" are printed to the console. Unfortunately I get the ajc: formal unbound in pointcut error.

要使其正常运行,我需要更改什么?

What do I need to change to make it work?

推荐答案

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

I refactored your code a bit because getPopulation() is a bad name and against conventions. Not the population object s returned as the name implies but the population's size.

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

As for your aspect, the naming caller is also bad because the object is not the caller but the callee or the target of the call. I simply renamed the parameter to population because this time it really contains a population object. Then I bound it to a target() parameter in order to make your error message go away.

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

I also switched from call() to execution() pointcut because it is more efficient to weave the code into the executed method instead of into every single place where the method is called.

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

I also made sure that the count starts at 1, not 0, after the first new year is over and the population has grown. I did this by using ++size rather than size++, i.e. pre- instead of 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

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

Can you spot the problem? You have one overall year counter, but multiple populations. Actually, you should have one year counter per population in order to get your statistics right. This can be done by using one aspect instance per target (i.e. per population) instead of a singleton aspect and of course by no longer making the year counter static:

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构造函数执行中(即,每个创建的对象)创建一个方面实例.

Here, pertarget(execution(Population.new(..))) means: Create one aspect instance per Population constructor execution, i.e. per created object.

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

Now the statistics are correct (I also changed the log message a bit in order to print the object ID so we can see which message belongs to which population):

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

这篇关于AspectJ正式切入点未绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆