2015-12-12 3 views
1

Я пытаюсь понять AspectJ. Я хочу попытаться подсчитать все инициализации объектов (которые инициализируются из указанных мной классов, а не некоторых внутренних Java) в проекте, и я действительно не уверен, как это сделать.AspectJ: отслеживать инициализацию нового объекта

Предположим, что у меня есть классы, называемые A и B, где A имеет подклассы Aa и Ab, B имеет подклассы Ba и Bb, а Bb имеет подкласс Bba. Я хотел бы, чтобы мой аспект отслеживал каждую инициализацию объектов, созданных с этими классами в качестве базы, но я действительно не понимаю, как правильно это сделать (хотя это должно быть несколько простым). До сих пор, у меня есть что-то похожее на это:

public aspect AspectCounter { 
     private int objects = 0; 

     pointcut countObjects() : initialization(A.new(..)) || initialization(B.new(..)); 

     pointcut printObjects() : call(* Test.printCounter(..)); 

     after() : countObjects() { 
      objects++; 
     } 

     after() : printObjects() { 
      System.out.println(objects); 
     } 
} 

Что же, по крайней мере, напечатать нужное количество элементов а и Б, которые я создал (я не пошел с B * .new (..) так как это, как я понимаю, отслеживать любую инициализацию Bba три раза, что я не хочу в этом случае). То, как это работает прямо сейчас, состоит в том, что у меня есть класс Test, который, ну, проверяет материал, и после того, как я закончил тестирование, я просто вызываю пустой метод printCounter, который на самом деле ничего не делает. Кажется, что он работает и действительно дает мне правильное количество объектов, но я уверен, что есть лучший способ сделать это. Мне действительно не нравится иметь пустой метод.

ответ

1

Вы не можете сделать это с помощью initialization, preinitialization или execution на *.new(..) срезов в связи с порядком, в котором они выполняются. Они не вложены, как вы могли бы подумать, но выполнялись довольно последовательно из-за того, как работает JVM. Я подробно объяснил это here, включая пример кода и выход журнала. Таким образом, вы остаетесь только с возможностью использовать pointcut call. Вот пример:

package de.scrum_master.app; 

public class A {} 
package de.scrum_master.app; 

public class Aa extends A {} 
package de.scrum_master.app; 

public class Ab extends A {} 
package de.scrum_master.app; 

public class B {} 
package de.scrum_master.app; 

public class Ba extends B {} 
package de.scrum_master.app; 

public class Bb extends B {} 
package de.scrum_master.app; 

public class Bba extends Bb {} 

Драйвер приложения:

package de.scrum_master.app; 

public class Application { 
    public static void main(String[] args) { 
     new A(); 
     new Aa(); 
     new Ab(); 
     new B(); 
     new Ba(); 
     new Bb(); 
     new Bba(); 
    } 
} 

Формат:

package de.scrum_master.aspect; 

import de.scrum_master.app.A; 
import de.scrum_master.app.B; 

public aspect InstanceCreationCounter { 
    private static int count; 

    after() : call(A+.new(..)) || call(B+.new(..)) { 
     System.out.printf("%4d %s%n", ++count, thisJoinPoint); 
    } 
} 

консоли журнала:

1 call(de.scrum_master.app.A()) 
    2 call(de.scrum_master.app.Aa()) 
    3 call(de.scrum_master.app.Ab()) 
    4 call(de.scrum_master.app.B()) 
    5 call(de.scrum_master.app.Ba()) 
    6 call(de.scrum_master.app.Bb()) 
    7 call(de.scrum_master.app.Bba()) 

Я думаю, это то, что вы хотите.

Предостережение: Вы должны иметь контроль над всем вызывающим кодом и вставлять в него аспект, чтобы это работало.

Смежные вопросы