Я немного реорганизовал ваш код, потому что getPopulation()
- это плохое имя и противоречит соглашениям.Не объект совокупности, возвращаемый, как следует из названия, а размер совокупности.
Что касается вашего аспекта, то наименование caller
также является плохим, поскольку объект является не вызывающим, а вызываемым или целевым объектом вызова.,Я просто переименовал параметр в population
, потому что на этот раз он действительно содержит объект населения.Затем я связал его с параметром target()
, чтобы ваше сообщение об ошибке исчезло.
Я также переключился с call()
на execution()
pointcut, потому что эффективнее встроить код в исполняемый файл.вместо каждого отдельного места, где этот метод вызывается.
Я также позаботился о том, чтобы счет начинался с 1, а не с 0, после того, как закончился первый новый год, и численность населения выросла.Я сделал это, используя ++size
вместо size++
, то есть pre- вместо постинкремента.
Теперь код выглядит так:
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
выполнения конструктора, т.е. для каждого созданного объекта.
Теперь статистика верна (я также немного изменил сообщение журнала, чтобы вывести идентификатор объекта, чтобы мы могли видеть, какое сообщение принадлежиткакое население):
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