Spring-JSP

[Spring-JSP] Custom Annotation을 이용한 AOP 만들기

Jeong Jeon
반응형

Spring하면 빼놓을수 없는것이 AOP이다.

CustomAnnotation을 이용하여 권한을 체크하는 방법을 기록해두려고 한다.

 

1). AuthorizationAspect를 정의하여 읽어올수 있게 Bean으로 등록한다.

root-context.xml

=> 다른 AOP도 아래와 같이 추가해주면 된다.

<bean id="authAspect" class="com.test.spring.aop.advices.AuthorizationAspect"/>

 

2). Custom Annotation을 만든다.

annotations.CheckAuth.java

@Retention(RetentionPolicy.RUNTIME) //Runtime동안 적용?
@Target({ElementType.METHOD})//Method에 적용
public @interface CheckAuth{
	int[] checkAuth(); //숫자 배열로 어노테이션 값을 전달받을 수 있게 설정.
}

 

3). Aspect를 만든다.

advices.AuthorizationAspect.java

@Aspect
public class AuthorizationAspect{
	//@CheckAuth Annotation이 붙은 메서드의 실행 직전에 실행
    //@annotation(target)을 통해 어노테이션 설정값들을 가져올수 있다.
    //
     @Before("@annotation(com.test.spring.aop.annotations.CheckUser) && @annotation(target)")
    public void checkAuth(JoinPoint jp, CheckAuth target) throws Exception {
    	//메서드의 인자값을 가져올 수 있다.
        //Object arg[] = jp.getArgs();
        
        //arg[]를 찍어보면 안에 값을알 수 있다.
    	//HttpServletRequest req = (HttpServletRequest)arg[0];
        
        //HttpServletRequest에 담아둔 user정보를 가져오기 위해 HttpServletRequest를 뽑아온다.
    	HttpServletRequest req = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        AccountVo session = (AccountVo)req.getAttribute("user");
        
        //target:@annotation으로 가져온 어노테이션 설정값에서 checkAuth 담긴 값을 가져온다.
        int[] list = target.checkAuth();
        
        //예외 처리
        if(StringUtils.isEmpty(list)) {
        	throw new MyBusinessException("",Constant.ERROR_404);
        }
        
        //해당 annotation(@CheckUser)를 사용한 메서드에서 허용하는 target과 비교하는 로직
        boolean result = false;
        loop: for(int i = 0; i < list.length; i++) {
        	if(session.getAccountTypeId() == list[i]) {
        		result = true;
        		break loop;
        	}
        }
        if(!result) {
        	throw new MyBusinessException("",Constant.ERROR_404);
        }
    }
}

 

4). 사용한다.

//CheckAuth Annotation을 사용한다.
//@Annotation명(annotation에 정의된 인자 = {int배열임으로 int 배열에 값을 넣어 전달}

@CheckAuth(checkAuth = {Constant.ACCOUNT_TYPE_COMPANY_USER})
@Override
public HashMap<String,Object> getTestList(HttpServletRequest req, TestVo testVo, Locale locale) throws Exception {
   
......
}

int[]로 받을 수 있게 했으니 여러개의 값을 전달해서 check해보자

@CheckAuth(checkAuth = {Constant.ACCOUNT_TYPE_COMPANY_USER,Constant.ACCOUNT_TYPE_NORMAL_USER})
@Override
public HashMap<String,Object> getTestList(HttpServletRequest req, TestVo testVo, Locale locale) throws Exception {
   
......
}

 

 

 

++ 추가 ==> 까먹었을 수도 있으니!!!!

 

타겟 (Target) : 어드바이스를 주입할 대상

어드바이스(Advice) : 횡단(공통) 관심사만을 분리하여 담은 내용

조인포인트 (JoinPoint) : 어드바이스가 적용될 수 있는 메서드 또는 그 위치

포인트컷 (PointCut) : 어드바이스(횡단(공통) 기능)를 주입시킬 대상(타켓)을 선정하기위한 방법

 

@Before

- 어드바이스가 주입될 타켓이 호출되기전 어드바이스 내용이 주입, 수행

@After

- 타켓이 수행한 내용 결과에 관계없이 수행이 끝나면 어드바이스 내용이 주입, 수행

@AfterReturning

- 타켓에 대한 내용이 예외없이 성공적으로 수행되면 결과값을 반환 후 어드바이스 내용이 주입, 수행

@AfterThrowing

- 타켓에 대한 내용이 예외를 던지게되면 어드바이스 내용이 주입, 수행

@Around

- 타켓에 대한 내용 수행 전, 후 를 감싸 어드바이스 내용이 주입, 수행

 

 

원하는 기능을 만들기에 다양한 방법이 있음을 잊지 말자...!!

까먹을수 있으니 기록.

반응형