2016-10-21 10 views
0

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

pointcut addPointCut() : call(boolean List.add(..)); 

before(List<Integer> list) : addPointCut() && target(list) { 
    System.out.println("testing"); 
    for(Object i : list) { 
     System.out.println(i); 
    } 
} 

ответ

0

Ответ Nándor правильный, поскольку он описывает ошибку компилятора, которую вы видите. Я хочу пойти немного дальше, а также объяснить, почему вы получите эту ошибку:

Прежде всего, эта проблема напрямую не связанную с AspectJ, а скорее как Java реализует дженерики. Перед тем, как продолжить чтение, ознакомьтесь с феноменом type erasure.

Ну, потому что тип стирание является JVM реальность и потому target() и this() разрешается во время выполнения, а не во время компиляции - вы можете косвенно заключить это из-за того, что оба getTarget() и getThis() являются методами JoinPoint, а не JoinPoint.StaticPart - то, что вы хотите сделать, не может работать и, следовательно, приводит к ошибке компилятора AspectJ. Единственное, что вы можете сделать, это использовать instanceof, чтобы динамически определять, что добавляется в целевой список. Самый изящный способ сделать это - выражение pointcut.

Вот некоторые примеры кода:

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

Так, чтобы сделать вещи немного более интересным, мы используем два типа списков, а также два типа add(..) вызовов. Цель должна заключаться в том, чтобы только перехватывать целые числа, которые должны быть добавлены в соответствующий список, независимо от того, какая подпись имеет метод add(..).

package de.scrum_master.app; 

import java.util.ArrayList; 
import java.util.List; 

public class Application { 
    public static void main(String[] args) { 
     List<Integer> integers = new ArrayList<>(); 
     integers.add(11); 
     integers.add(0, 22); 
     integers.add(33); 

     List<String> strings = new ArrayList<>(); 
     strings.add("foo"); 
     strings.add(0, "bar"); 
     strings.add("zot"); 
    } 
} 

Формат:

package de.scrum_master.aspect; 

import java.util.List; 

@SuppressWarnings({"rawtypes", "unchecked"}) 
public aspect GenericsAspect { 
    pointcut addPointCut(List list, Object newElement) : 
     !within(GenericsAspect) &&   // avoid stack overflow due to recursion 
     call(* List.add(..)) &&    // intercept all calls to List.add 
     args(.., newElement) &&    // capture last method parameter 
     if(newElement instanceof Integer) && // only capture added int/Integer elements 
     target(list);       // target is a List 

    before(List list, Object newElement) : 
     addPointCut(list, newElement) 
    { 
     System.out.println(thisJoinPoint + " -> new element = " + newElement); 
     for(Object i : list) 
      System.out.println(" " + i); 

     // Type erasure in action: 
     // During runtime there is no such thing as List<Integer>, only a raw List. 
     // Thus, we can easily add a String to a list declared as List<Integer>. 
     list.add("#" + newElement + "#"); 
    } 
} 

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

call(boolean java.util.List.add(Object)) -> new element = 11 
call(void java.util.List.add(int, Object)) -> new element = 22 
    #11# 
    11 
call(boolean java.util.List.add(Object)) -> new element = 33 
    22 
    #11# 
    11 
    #22# 

Любые дополнительные вопросы?

0

Использование дженериков в типе target(...) или this(...) срез точек не поддерживается, и компиляция потерпит неудачу с этой ошибкой : parameterized types not supported for this and target pointcuts (erasure limitation). Удалите параметр типа из списка, и он должен работать должным образом.

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

  • Нет связанных вопросов^_^