Whiteship's Note

'Advice parameters'에 해당되는 글 2건

  1. 2007.04.03 Advice parameters
  2. 2007.01.17 12. Advice parameters 1 (2)

Advice parameters

Spring/Chapter 6 : 2007.04.03 15:33


예전에 공부할 때 여기를 공부하다가 멈췄었네요.
Advice parameters 1 (2)
드디어 따라잡았습니다. 흐흣.

1. Access to the current JoinPoint

해당 Advice가 끼어드는 joinpoint에 대한 정보를 얻어 올 수 있습니다. @Around 어드바이스를 제외한 다른 어드바이스들의 첫번째 파라미터로 JoinPoint 를 만들어 주면 됩니다.

    @Before("aop.newStyle.aspect.CinemaAspect.sellTicketPointcut()")
    public void weblcomeAdvice(JoinPoint jp){
        System.out.println(jp.getClass());
        System.out.println("안녕하세요. 어떤 영화를 보시겠습니까?");
    }

실제 객체는 MethodInvocationProceedingJoinPoint 이 클래스라는 걸 확인할 수 있습니다.

@Around 어드바이는 이전 글에서 봤듯이 ProceedingJoinPoint가 와야 합니다.

2. Passing parameters to advice

    @Pointcut("execution(aop.newStyle.domain.Ticket *.sell*(..))")
    public void sellTicketPointcut() {
    }

    @Before("aop.newStyle.aspect.CinemaAspect.sellTicketPointcut() &&" +
            "args(movie, ..)")
    public void weblcomeAdvice(JoinPoint jp, Movie movie){
        System.out.println("안녕하세요." + movie.getName() + " 을(를) 보시겠습니까?");

이렇게 args()를 사용하여 대상 메소드가 받을 인자를 가져올 수 있습니다.

다른 방법으로는 @Pointcut을 정의할 때 args()를 사용해서 다음과 같이 하는 건데요. IllegalArgumentExecption이 발생하는데 아직 원인을 모르겠습니다. 레퍼런스에 나와있는 코드와 똑같이 친것 같은데 말이죠. ㅠ.ㅠ

3. Determining argument names

공부해야 할 부분

4. Proceeding with arguments

@Around 에서 proceed()를 실행 할 때 들어갈 인자값을 바꿀 수 있는데요 그때는 proceed(Object[]) 메소드를 사용하면 됩니다.

@Around("aop.newStyle.aspect.CinemaAspect.sellTicketPointcut() && " +
            "args(movie,..)")
    public Object ticketAround(ProceedingJoinPoint pjp, Movie movie) throws Throwable{
        System.out.println("안녕하세요." + movie.getName() + " (을)를 보시겠습니까?");
        Ticket ticket = (Ticket)pjp.proceed(new Object[]{movie, new Date()});
        System.out.println(ticket.getMovie().getName() + " 를 구매하셨습니다.");
        System.out.println("감사합니다. 다음에 또 오세요.");
        ticket.getMovie().setName("바뀐 영화 이름");
        return ticket;
    }

top


12. Advice parameters 1

AOP : 2007.01.17 18:49



Around Advice를 제외한 Advice 메소드에 첫번개 매개변수로 JoinPoint 타입을 선언할 수 있습니다. Aroud Advice는 JoinPoint의 하위 타입인 ProceedingJoinPoint를 주어야 합니다.

AspectJ API : http://www.eclipse.org/aspectj/doc/next/runtime-api/index.html
위 API를 참조 하시면 어떤 메소드들이 있는지 확인 하실 수 있습니다.

Around Advice는 기능이 다른 Advice들과는 차이가 있습니다.

  • 해당 Join Point를 실행 할지 안할지 정할 수 있습니다.
  • Join Point의 아규먼트로 들어가는 값을 임의로 변경할 수 있습니다.
  • Join Point의 리턴값도 임의로 변경할 수 있습니다.

이를 위해서 두 개의 메소드가 존재합니다.

사용자 삽입 이미지

proceed() 메소드는 Join Point를 실행하기 위한 메소드 입니다. proceed()의 리턴 타입은 실제 Join Point에서 리턴하는 값을 리턴 해 줍니다.

proceed(Object[]) 메소드는 Join Point를 실행할 때 Join Point로 들어갈 아규먼트를 대체 하고 싶을 때 원하는 값을 Object 배열 형태로 넣어 줄 수 있습니다.

public class Test {

       public static void main(String[] args) {

 

             BeanFactory bf = new ClassPathXmlApplicationContext(

                           "parameter/joinpoint/aopAppContext.xml");

             Human human1 = (Human) bf.getBean("keesun");

             Human human2= (Human) bf.getBean("youngkun");

 

             System.out.println(human1.getName());

             System.out.println(human2.getName());

 

             human1.setName("찬욱");

 

             System.out.println(human1.getName());

       }

}


위에서 keesun이라는 bean의 name은 "기선" youngkun이라는 bean의 name은 "영근"으로 setter injection을 사용해서 값을 넣어뒀습니다.

@Aspect

public class HumanAspect {

 

       @Pointcut("execution(* get*(..))")

       public void sayHi() {

       }

 

       //리턴 변경하기.

       @Around("sayHi()")

       public Object say(ProceedingJoinPoint joinPoint) throws Throwable {

             System.out.println("안녕하세요.");

             Object name = joinPoint.proceed();

             return name;

       }

 

       //매개 변수의 임의로 변경하기.

       @Around("execution(* set*(..))")

       public void validate(ProceedingJoinPoint pjp) throws Throwable {

             System.out.println("모두 안녕~");

             pjp.proceed(new Object[]{"영회"});

       }

}


그리고 위와 같은 Aspect를 적용하면 결과는 다음과 같습니다.

안녕하세요.
기선
안녕하세요.
영근
모두 안녕~
안녕하세요.
영회


위의 Aspect에서 위에 있던 sayHi Advice를 다음과 같이 수정하면 결과는 다음과 같습니다.

       //리턴 변경하기.

       @Around("sayHi()")

       public Object say(ProceedingJoinPoint joinPoint) throws Throwable {

             System.out.println("안녕하세요.");

             Object name = joinPoint.proceed();

             return ".. 큰일났다.";

       }

 

안녕하세요.
앗.. 큰일났다.
안녕하세요.
앗.. 큰일났다.
모두 안녕~
안녕하세요.
앗.. 큰일났다.

그리고 하지 말라고 하면 더 하고 싶어지는.. 그런 장난끼에 ProceedingJoinPoint말고 그냥 JoinPoint로 선언한 뒤 실행하면 다음과 같은 출력이 됩니다.
안녕하세요.
null
안녕하세요.
null
모두 안녕~
안녕하세요.
null
top