2017-12-26 8 views
0

AspectJ에 대한 경험이 없지만 최근 구현해야 할 작업이 있고 여러 가지 AspectJ 자습서를 읽었으므로 AspectJ가 될 수 있다고 생각합니다. 내 해결책.특정 주석을 사용하여 클래스 멤버에 대한 메서드 호출을위한 Pointcut 패턴

작업은 다음과 같습니다. 나는 어떤 메소드 b()가있는 클래스 A를 가지고 있으며이 클래스의 객체는 다른 클래스의 필드로 포함됩니다. 이러한 필드에 @C 주석을 달아서 A 형 필드와 @C 형 필드에서 b() 메서드를 호출 할 때마다이 주석 값을 얻고 싶습니다.

간체 코드 :

class A{ 
    field1; 
    field2; 
    field3; 

     void b(String[] fieldsToIgnore){ 
     doSomething with fields 1,2,3 (excluding fields from fieldsToIgnore array) 
    } 
     } 

    class B{ 
     @C(value="field1,field2") 
     A fieldA; 
     } 


     //Here when I want to weaver my aspect - before I call to method b() on fieldA with annotation @C - I want to get annotation value and to pass it as an argument to method b() 
     new B.fieldA.b() 

나에게 조언을 날이 올 포인트 컷을 작성 도와주세요. 또한 어떻게 내 조언 메서드에서 내 메서드 b() 데이터를 전송할 수 이해할 수 없다 - 그것은 전혀 가능합니까?

어떤 도움을 주셔서 감사합니다 - 당신은 그냥 산을 말할 경우에도 "아니, 불가능"- 그것은 나에게 시간과 신경 :) 사실

+0

내가 대답하기 전에 당신이 분명히 말하기를 바란다 : "조언에서 메소드'b()'로 데이터를 전송한다는 것은 무엇을 의미합니까? (의사) 코드를 편집하고 해당 데이터를 해당 방법에서 사용하는 방법을 알려주십시오. BTW,'A' 필드와 그 필드에 할당 된 객체의 연결과 관련하여 수동으로 부기를 할 준비가 되셨습니까? 이것이 이것이 취할 수있는 일이기 때문에 가능하지만 응용 프로그램 설계로 인해 약간 지루합니다. – kriegaex

+0

내 의사 코드를 업데이트했습니다. 주요 아이디어는 주석 값에 나열된 필드 이름 목록을 메서드 b()에 전달하여이 메서드 실행 중에이 필드가 무시되도록하는 것입니다. –

+0

'new B(). fieldA.b()'(BTW, 거기에 괄호를 잊어 버렸습니다.) 메소드 서명'void b (String [] fieldsToIgnore)'와 일치 할 수 없으므로 컴파일되지 않습니다. 이것은 AspectJ를 사용하기 전에도 자바 문제이다.또한 응용 프로그램이 (a) 응용 프로그램이 측면에 대해 알고 있고 그 응용 프로그램 없이는 작업 할 수없는 경우와 (b) 주석이 문자열로 주석에 나열된 필드 이름을 너무 많이 필요로하는 경우에만 응용 프로그램 디자인에 결함이있는 것입니다. 리팩토링되면 깨질 것입니다. 이것은 교차 관심사가 아니므로 가능한 경우 AOP 유스 케이스가 없습니다. – kriegaex

답변

1

을 많이 절약 할 수, 당신은 이미 반사를 사용하는 경우 대규모 어쨌든 - 이 코드는 코드를 리팩터링하지 않는 핑계가 아니며 계속 그렇게하기를 원합니다. 사실 더 난잡하게 만들려면 실제로 AspectJ가 필요하지 않습니다. 이처럼 다만 수

도우미 클래스를 반사 필드 액세스 :

package de.scrum_master.app; 

import java.lang.reflect.Field; 
import java.util.Arrays; 
import java.util.List; 

public class FieldHelper { 
    public static Field getField(Class<?> clazz, String fieldName) { 
    Field field; 
    try { 
     field = clazz.getDeclaredField(fieldName); 
    } catch (NoSuchFieldException | SecurityException e) { 
     throw new RuntimeException("Reflection problem", e); 
    } 
    field.setAccessible(true); 
    return field; 
    } 

    public static Field[] getFields(Class<?> clazz) { 
    Field[] fields = clazz.getDeclaredFields(); 
    for (Field field : fields) 
     field.setAccessible(true); 
    return fields; 
    } 

    public static List<String> extractIgnoredFieldsList(Class<?> clazz, String fieldName) { 
    return Arrays.asList(
     getField(clazz, fieldName) 
     .getAnnotation(IgnoreFields.class) 
     .fieldNames() 
    ); 
    } 
} 

마커 주석 : 호출하는 방법

package de.scrum_master.app; 

import java.lang.annotation.ElementType; 
import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 
import java.lang.annotation.Target; 

@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.FIELD) 
public @interface IgnoreFields { 
    public String[] fieldNames(); 
} 

클래스 :

package de.scrum_master.app; 

import java.lang.reflect.Field; 
import java.util.Date; 
import java.util.List; 

import static de.scrum_master.app.FieldHelper.*; 

public class A { 
    int number = 11; 
    String text = "Hi there!"; 
    Date date = new Date(); 
    String optionalText = "I am not really always needed"; 
    int optionalNumber = 123; 

    public void doSomething(List<String> ignoredFields) { 
    for (Field field : getFields(this.getClass())) { 
     if (!ignoredFields.contains(field.getName())) { 
     try { 
      System.out.println(field.getName() + " = " + field.get(this)); 
     } catch (IllegalArgumentException | IllegalAccessException e) { 
      throw new RuntimeException("Reflection problem", e); 
     } 
     } 
    } 
    } 
} 
주석 멤버 필드와

등급 :

package de.scrum_master.app; 

import static de.scrum_master.app.FieldHelper.*; 

public class B { 
    @IgnoreFields(fieldNames = { "optionalText", "optionalNumber" }) 
    A noOptionalsA = new A(); 

    @IgnoreFields(fieldNames = { "text", "number", "date" }) 
    A onlyOptionalsA = new A(); 

    public static void main(String[] args) { 
    B b = new B(); 
    b.noOptionalsA.doSomething(extractIgnoredFieldsList(b.getClass(), "noOptionalsA")); 
    System.out.println("----------------------------------------"); 
    b.onlyOptionalsA.doSomething(extractIgnoredFieldsList(b.getClass(), "onlyOptionalsA")); 
    } 
} 

콘솔 로그 :

number = 11 
text = Hi there! 
date = Wed Dec 27 18:54:44 ICT 2017 
---------------------------------------- 
optionalText = I am not really always needed 
optionalNumber = 123 

당신은, 제발 여기 일어나고 또는 여전히 AspectJ를 용액에 고집 무엇인지 이해하지 않는 경우 알려 주시면 추가적인 aspect 코드를 설명하고 설명해 드리겠습니다.

+0

제공된 솔루션에 감사드립니다. 아마 aspectj 대신에 사용하겠습니다. 왜냐하면 aspectj를 사용하면 우리 프로젝트에서 롬복을 사용하고 있기 때문에 두통이 심해질 것이고 함께 잘 작동하지 않기 때문입니다. –

+0

** 업데이트 : ** 런타임 예외 (즉, 리플렉션 사용으로 인해 메소드 서명을 변경하지 않아도 됨)에 ** 확인 된 리플렉션 기반 예외를 래핑 **하기 위해 코드를 리팩터링했습니다 ** (b) ** 주석에서 무시 된 필드 목록을 도우미 클래스로 가져 오기 위해 이전 반복 된 상용구 코드를 이동합니다. – kriegaex

관련 문제