복붙노트

[SPRING] Spring AOP-setter를 호출하기 전에 오래된 필드 값을 얻습니다.

SPRING

Spring AOP-setter를 호출하기 전에 오래된 필드 값을 얻습니다.

현재 Spring AOP (v4) 및 AspectJ를로드 타임 위버와 함께 사용하고 있습니다.

현재 빈에 더러운 플래그 메커니즘을 추가하는 방법을 찾고 있습니다. 따라서 나는 AOP를 사용하여 Bean의 setter가 호출되기 전에 메소드를 호출합니다. 이것은 이미 달성했지만 수정하기 전에 이전 필드 값에 어떻게 액세스 할 수 있습니까? 아니면 setter가 호출되기 전에 getter를 호출 할 수 있도록 필드 이름을 얻는 방법이 있습니까?

아무도 포인트 컷 / 조언을 인수로 전달하는 방법에 대한 예를 여기에서 제공 할 수 있습니까?

@Aspect
public class MyAspect {

  @Before("execution(* foo.*.set*(..))") 
  public void beforeSetterCalled(JoinPoint joinPoint){
    System.out.println("beforeSetter");
  }
}

불행히도 Spring AOP가 "set ()"field-pointcut 구문을 지원하지 않는 것 같습니다. 맞습니까? 또는 이것을 사용하기 위해 어쨌든 존재합니까?

도움을 주셔서 감사합니다.

해결법

  1. ==============================

    1.효율적인 솔루션을 얻으려면 전체 AspectJ를 set () pointcut과 함께 사용하는 것이 좋습니다. 그러나 리플렉션과 관련하여 느리고 추악한 솔루션을 사용하는 것이 마음에 들지 않으면 다음과 같이 할 수도 있습니다.

    효율적인 솔루션을 얻으려면 전체 AspectJ를 set () pointcut과 함께 사용하는 것이 좋습니다. 그러나 리플렉션과 관련하여 느리고 추악한 솔루션을 사용하는 것이 마음에 들지 않으면 다음과 같이 할 수도 있습니다.

    package de.scrum_master.app;
    
    public class Person {
        private int id;
        private String firstName;
        private String lastName;
    
        public Person(int id, String firstName, String lastName) {
            this.id = id;
            this.firstName = firstName;
            this.lastName = lastName;
        }
    
        public int getId() { return id; }
        public String getFirstName() { return firstName; }
        public String getLastName() { return lastName; }
    
        public void setId(int id) { this.id = id; }
        public void setFirstName(String firstName) { this.firstName = firstName; }
        public void setLastName(String lastName) { this.lastName = lastName; }
    
        @Override
        public String toString() { return "Person [" + id + ", " + firstName + " " + lastName + "]"; }
    
        public static void main(String[] args) {
            Person albert = new Person(1, "Albert", "Camus");
            Person audrey = new Person(2, "Audrey", "Hepburn");
            System.out.println(albert);
            System.out.println(audrey);
            System.out.println();
            albert.setId(8);
            albert.setLastName("Einstein");
            audrey.setId(9);
            audrey.setLastName("Tautou");
            System.out.println();
            System.out.println(albert);
            System.out.println(audrey);
        }
    }
    
    package de.scrum_master.aspect;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.SoftException;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    
    @Aspect
    public class SetterInterceptor {
        @Before("execution(* set*(*)) && target(instance) && args(newValue)")
        public void beforeSetterCalled(JoinPoint thisJoinPoint, Object instance, Object newValue) {
            String methodName = thisJoinPoint.getSignature().getName();
            try {
                System.out.println(
                    methodName.substring(3) + ": " +
                    instance
                        .getClass()
                        .getMethod(methodName.replaceFirst("set", "get"))
                        .invoke(instance) +
                    " -> " + newValue
                );
            } catch (Exception e) {
                throw new SoftException(e);
            }
        }
    }
    

    콘솔 로그 :

    Person [1, Albert Camus]
    Person [2, Audrey Hepburn]
    
    Id: 1 -> 8
    LastName: Camus -> Einstein
    Id: 2 -> 9
    LastName: Hepburn -> Tautou
    
    Person [8, Albert Einstein]
    Person [9, Audrey Tautou]
    
  2. ==============================

    2.스프링이 필드 결합 점을 지원하지 않는 것에 대해 맞습니다

    스프링이 필드 결합 점을 지원하지 않는 것에 대해 맞습니다

    Spring AOP를 사용하여 AOP 조언을 통해 필드 값을 직접 얻을 수는 없습니다.

    방법은 필드와 관련이 없습니다. 접근 자 (및 뮤 테이터)는 Java의 규칙 일뿐입니다. 해당 규칙을 따르는 경우 메소드 이름에서 필드 이름을 추론하고 리플렉션을 사용하여 검색 할 수 있습니다.

  3. from https://stackoverflow.com/questions/31503041/spring-aop-get-old-field-value-before-calling-the-setter by cc-by-sa and MIT license