2016-10-21 4 views
0

목록 인터페이스 내의 메소드를 가리키는 클래스를 만들고 싶습니다. 이것은 내 조언에 표적 (목록)을 추가하기 전까지는 효과가있는 것으로 보인다. 나는 (예를 들어) 무엇이 바뀌 었는지를보기 위해 추가하기 전과 후에 목록의 요소를보고 싶습니다. 그러나 나는 객체로서 내 목록을 전달할 수 없습니다.AspectJ 매개 변수화 된 유형이 대상 pointcut을 지원하지 않습니다.

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를에 오히려 자바 제네릭을 구현하는 방법에 관련되지 않은 모든

첫째 : 나는 조금 더 가서가이 오류가 이유도 을 설명합니다. 계속 읽기 전에 type erasure이라는 현상에 대해 잘 알고 있어야합니다.

음, 유형의 삭제는 JVM의 현실과 target()this() 때문에 컴파일 시간보다는 런타임에 해결되기 때문에 - 당신이 간접적으로 모두 getTarget()getThis()JoinPoint 아니라 JoinPoint.StaticPart 이외의 방법이라는 사실이 결론을 내릴 수 있습니다 - 무엇을 하고 싶지 않다면 AspectJ 컴파일러 오류가 발생한다. 수행 할 수있는 유일한 작업은 instanceof을 사용하여 대상 목록에 무엇이 추가되는지 동적으로 결정하는 것입니다. 이렇게하는 가장 우아한 방법은 if() 포인트 컷 식입니다.

드라이버 응용 프로그램 : 여기

은 몇 가지 예제 코드입니다

그래서 우리는 목록의 두 가지 유형 또한 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). 목록에서 형식 매개 변수를 제거하면 예상대로 작동합니다.