IT_Programming/Dev Libs & Framework

[펌_Sping] Spring에서의 Config설정 - AOP

JJun ™ 2013. 4. 12. 00:38



 출처: http://jeonsh.tistory.com/11





Spring을 도입하면서 가장 걱정했던 것이 권한(Role)과 Session 처리에 대한 부분이었다.

기존에 사용했던 Struts에서는 struts-config.xml파일에서 <controller processorClass=""/>로 설정하고 

해당 파일에서 Role과 Session을 체크한 후 요청에 대한 Action이 실행되게 설정이 가능했었다.





- AOP(Aspect Oriented Programming)


Spring에서는 두가지 방법이 있다.
Spring Aspect Oriented Programming(AOP)와 Spring Acegi Security Framework(ASF).
처음에는 "그래도 보안!!"이라는 생각으로 ASF를 한번 적용하려고 마음을 먹었으나, 

역시나 시간상 무리라는 판단에 제외...ㅡ.ㅡ;;
 그래서 AOP로 방향을 선회했으나, 이것 역시 상당히 까다롭다.

우선 AOP에 대해 이야기해 보자.
간단하게 이야기하면 AOP는 공통되는 기능을 따로 떼어놓고 특정한 규칙에 해당하는 Event가 발생했을 때, 해당되는 공통기능을 실행하도록 만드는 기법이라 보면 되겠다.


공통기능이 실행되는 방식에는 Before, After-Returning, After-Throwing, After, Around 등이 있다.


- Before : Method실행전에 적용

- After-Returning : Method가 정상적으로 실행된 이후 적용

- After-Throwing : Method에서 Exception이 발생했을 때 적용

- After : 결과여부에 상관없이 Method 실행 후 적용

- Around : 모든 경우에 적용가능


Role과 Session(CheckProcessor.java라고 예를 들자.)은 Method실행 전에 체크를 해야되므로 

Before를 사용하는게 맞겠다. 그래서 Before로 적용을 했다.


하지만, 안타깝게도 Before는 CheckProcessor.java파일을 실행한 후 Exception이 발생하거나, request.getRequestDispatcher()를 사용하더라도 요청 Method를 그대로 실행해버린다...

즉, 말그대로 Before다. 그냥 Method실행 전에 한번 실행해주는 것으로 끝이다...


다시 Around로 적용을 했다. 그렇다, 이게 정답이었다...^^;


참고로 AOP를 적용하기 위해서는 Spring2.5에서 spring.jar파일과 aspectjrt.jar, aspectjweaver.jar파일이 Library에 포함되어 있어야 한다.


dispatcher-servlet.xml

 <beans xmlns="http://www.springframework.org/schema/beans" 

 xmlns:p="http://www.springframework.org/schema/p" 

 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 

 xmlns:aop="http://www.springframework.org/schema/aop" 

 xsi:schemaLocation="http://www.springframework.org/schema/beans 

  http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

  http://www.springframework.org/schema/aop

  http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">


  <bean id="roleProcess" class="test.aspect.RoleProcessAspect" />

  <aop:config>

    <aop:aspect id="roleAspect" ref="roleProcess">

      <aop:pointcut id="publicMethod" expression="execution(public * *..*Controller.*(..))"/>

      <aop:around pointcut-ref="publicMethod" method="aroundRoleProcess" />

    </aop:aspect>

  </aop:config>

</beans>



설정자체는 간단하다. 그러나, 이렇게 하기 위해 수많은 삽질을 했다는 전설이 있었다...

설명을 하자면, 


 "public으로 시작하는 모든 Package의 Controller로 끝나는 파일에서 모든 Method를 실행할 때,  
  RoleProcessAspect파일의 aroundRoleProcess라는 Method를 실행하라."


는 뜻이다.


execution의 표현법에는 여러가지 패턴이 있으나 여기에 대한 설명은 다음에 하기로 하겠다.


RoleProcessAspect.java


 public class RoleProcessAspect
{

  public Object aroundRoleProcess(ProceedingJoinPoint joinPoint) throws Throwable

  {

    Object proceedObj = null;


    HttpServletRequest request = (HttpServletRequest)joinPoint.getArgs()[0];

    HttpServletResponse response = null;

    if(joinPoint.getArgs().length >= 2)

      response = (HttpServletResponse)joinPoint.getArgs()[1];

    }


    // Role과 Session은 여기서 체크한다.

    try{

      // 요청 Method를 실행한다.

      proceedObj = joinPoint.proceed();

    } catch(Throwable e){

      // Method 실행시 오류가 났을 경우

      throw e;

    }

    return proceedObj;

}



만약 Method실행시 Exception이 발생했을 경우 특정Page로 로딩하고 싶다면, 

dispatcher-servlet.xml에서 ExceptionResolver를 사용하면 된다.



<bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">

 <property name="exceptionMappings">

  <props>

   <prop key="java.lang.Exception">errorPage</prop>

  </props>

 </property>

</bean>



errorPage는 tiles-def.xml에서 정의한다.