【问题标题】:AspectJ formal unbound in cutpoint切点中的 AspectJ 形式化未绑定
【发布时间】:2018-12-15 14:11:04
【问题描述】:

我有以下课程:

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

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

【问题讨论】:

    标签: java aspectj pointcut


    【解决方案1】:

    我稍微重构了您的代码,因为getPopulation() 是一个坏名字并且违反了约定。顾名思义,返回的不是人口对象,而是人口的大小。

    至于你的方面,命名caller 也不好,因为对象不是调用者,而是被调用者或调用的目标。我只是将参数重命名为population,因为这一次它确实包含一个人口对象。然后我将它绑定到target() 参数,以使您的错误消息消失。

    我还从call() 切换到execution() 切入点,因为将代码编织到执行的方法中而不是编织到调用该方法的每个地方会更有效。

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

    现在代码如下所示:

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-06
      相关资源
      最近更新 更多