개발/Spring

Custom annotation 만들기 (Spirng AOP 이용)

신매력 2013. 4. 9. 10:12

예전 블로그에 올렸던거 슬슬 여기로 옮겨놔야지..

다시 정리해본다ㅎㅎ




사용자가 만들어 사용하는 Custom Annotation은 어떻게 효과적으로 응용할 수 있는지 궁금할 것이다.
인터넷에 예제도 별로 없고.. 
내가 짠 것은 아니지만, Spring 프렘웍의 AOP를 이용해서 만든 커스텀 어노테이션 사용법에 대해서 정리하겠다



* AOP(Aspect Oriented Programming)이란?

먼저, OOP(Object Oriented Programming)의 경우, 객체 단위로 기능을 묶어서 코딩하는 방법이다.
이런 구현방법이 단점이 될 상황이 있다. 
사용자 인증을 항상 해야 한다고 하면, 객체마다 반복되는 코드가 생기게 될 것이다. 
 
그래서 사용자 인증 같이 자주 사용되는 코드를 단위로 묶어서 필요할 때마다 삽입하여 사용하는 것을 AOP 라고 한다.
사용자 인증하는 코드가 A라고 하고, 비지니스 부분을 B라고 한다면 
[B가 실행되기 전 또는 후에 A를 실행한다.]  
전체적으로는 위의 코드가 한 비지니스 로직에서 실행되는 것처럼 하는 것이다.




어노테이션을 통해 사용자 인증을 하는 예제이다.




1. 커스텀 어노테이션 설정


(1) 어노테이션 인터페이스 작성

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.Method)
public @interface PreAuth {
Auth hasAuth() default com.x.x.Auth.VISITOR 
}


@Retention : 어노테이션은 주석이기 때문에 컴파일시 사라진다. 
하지만 retention을 통해, 런타임때까지 주석을 남기겠다 라고 컴파일러에게 알려줌

@Target : 어디에 어노테이션을 적용할 지 타겟을 정함

위의 어노테이션에 대한 옵션들은 검색 ㄱㄱ


(2) Auth enum 구현

 public enum Auth {
ADMIN(1), OWNER(2), USER(3), VISITER(4);
// 생략
}


숫자로 처리하기 위해 enum 사용.


(3) 비지니스에서의 어노테이션 사용

@Controller

public class Text {
      @PreAuth(hasAuth=Auth.OWNER   // 로긴된 사람이 Owner일때만 메소드 실행
public void view() {
// 구현
}
}



2. AOP  

(1) AOP 사용을 위한 xml 설정 (*-context.xml)

 ....
<aop:aspectj-autoproxy />


저 설정을 등록하면 @Aspect 어노테이션을 사용할 수 있다.


(2) 인증 처리 구현

@Component

public class AuthManager {
// 인증 처리 구현 
}



(3) 2.(2)에서 구현한 로직을 1.(3) 에 삽입할 시점 구현(Aspect)

@Aspect

@Component
public class AuthAspect {
@Resource(name = "authManager")
AuthManager authManager;

        // @PreAuth가 있는 지점을 pointcut으로 지정
@Pointcut("@annotation(com.x.x.annotation.PreAuth)" 
public void pointcut() { } 

        // pointcut 한 부분 이전에, 인증 수행(joinpoint)
@Before("pointcut()")   
public void beforeTargetMethod(JoinPoint joinPoint) {
hasAuth(joinPoint);
}

private void hasAuth(JoinPoint joinPoint) {
// Todo: reflection을 이용하여 어노테이션 속에 있는 값을 가져온다
authManager.hasAuth(hasRole); // 위에서 받아온 값을 넘긴다. 
}
}



joinPoint : 메소드 호출 전/후 등의 적용 지점

pointcut : 실제 로직에 적용되는 joinpoint