Aspect와 관련된 모든 세팅은
나의 기준으로 resource -> applicationContext.xml
에서 담당한다.
=== applicationContext.xml ===========================
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<context:component-scan base-package="com.packagenm1.packagenm2"/>
<aop:aspectj-autoproxy /> <!-- aop관련설정 annotation 처럼 관리 가능 -->
<!-- JdbcTemplate 클래스 등록 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- DataSource클래스 등록 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:@localhost:1521:xe" />
<property name="username" value="hr" />
<property name="password" value="hr" />
</bean>
</beans>
======================================================
** <aop:aspectj-autoproxy />
이거 하나만 있으면 component-scan 처럼 Log를 담당하게 될 클래스를 메모리상에 올릴 수 있다. 물론 이것만 설정한다고 되는게 아니라, 해당 클래스에서도 작업을 해주어야한다.
=== Log.java ==========================================
package com.packagenm1.packagenm2.common;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Service;
@Service("log")
@Aspect
public class LogAdvice {
@Before("PointcutCommon.allPointCut()")
public void printLog(JoinPoint jp) {
String method = jp.getSignature().getName();
Object[] args = jp.getArgs();
System.out.println("[사전 처리] " + method + "() 매소드 ARGS 정보 : " + args[0].toString());
}
}
======================================================
** @Aspect
위처럼 클래스상단에 선언을 해주어야 진짜 메모리상에 클래스가 올라간다. xml에서 작업해주었던건 이것을 위한 사전작업.
** @Before("PointcutCommon.allPointCut()")
매소드 실행 전, 실행이 되는 매소드를 지정한다. 이것을 통해 Log를 찍어도 가능.
괄호안을 자세히 보면 PointcutCommon.allPointCut() 라고 작성이 되어 있는데 이것은,
PointcutCommon 클래스 안에 allPointCut 라고 작성되어있는 매소드의 @Pointcut 정보를 가져오기 위한 내용이다.
왜 이렇게 클래스를 따로 두어 관리하는 이유는 각각의 Service클래스마다
@Pointcut("execution(* com..package2..impl.*Impl.*(..))")
public void allPointCut(){}
이런식으로 작성이 되어지며, 이렇게 되면 불필요한 소스가 증가하므로, 클래스에 모아서 관리한다.
PointcutCommon 의 소스는 하단에 있다.
=== PointcutCommon .java ==========================================
package com.packagenm1.packagenm2.common;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class PointcutCommon {
@Pointcut("execution(* com..packagenm2..impl.*Impl.*(..))")
public void allPointCut(){}
@Pointcut("execution(* com.packagenm1.packagenm2..impl.*Impl.get*(..))")
public void getPointCut(){}
}
==================================================================
** @Pointcut("execution(* com..packagenm2..impl.*Impl.*(..))")
execution() 안의 파라메터 정리
첫번째 인자 : 리턴타입(void, !void, int, String ....)
두번째 인자 : 패키지명 (com..packagenm2 의 경우 안에 ..(점점)은 com 으로 시작하고 마지막으로 impl로 끝나는 모든 패키지를 가르킴
세번째 인자 : 클래스( *impl의 경우, 다들 알다시피 impl로 끝나는 클래스 전부)
네번째 인자 : *() 매소드명 (get*()의 경우 get으로 시작하는 모든 매소드)
※ *(..) 은 매개변수의 이름,개수,타입 인데... 보통은 무시하고 다들 .. 을 쓴다고 한다.
@AfterThrowing
@AfterReturning
@Around
은 Before와 조금 다르다.
먼저 AfterThrowing
매소드위에 다른건 before와 동일하고
==================================================================
@AfterThrowing(pointcut="PointcutCommon.allPointCut()", throwing="exceptObj")public void exceptionLog(JoinPoint jp, Exception exceptObj) {
String method = jp.getSignature().getName();
System.out.println("[예외 처리] " + method +
"() 메소드 수행중 발생된 예외 메시지 : " + exceptObj.getMessage());
}
==================================================================
** 우선 파라메터를 하나 더 받고 ( Exception exceptObj ) 그 파라메터의 값을 지정하기 위하여 @AfterThrowing 위에 throwing="exceptObj"을 지정해야지 오류메시지가 나오지 않는다.
다음 AfterReturning
==================================================================
@AfterReturning(pointcut="PointcutCommon.getPointCut()", returning="returnObj")
Object returnObj에 맞는 returnObj을 설정해주어야 하므로 추가 작업이 들어간다.
public void afterLog(JoinPoint jp, Object returnObj) {
String method = jp.getSignature().getName();
System.out.println("[사후 처리] " + method +
"() 메소드 리턴값 : " + returnObj.toString());
}
==================================================================
** afterthrowing처럼 파라메터 및 상단에 파라메터의 값을 지정해주어야한다.
다음 Around
==================================================================
@Around("PointcutCommon.allPointCut()")
public Object aroundLog(ProceedingJoinPoint pjp) throws Throwable {
// return타입과 매개변수가 정해져있다. 유일하게 around에서만 ProceedingJoinPoint를 쓴다
Object obj = null;
System.out.println("---< before logic >---");
long startTime = System.currentTimeMillis();
obj = pjp.proceed();
long endTime = System.currentTimeMillis();
System.out.println("---< after logic >---");
System.out.println("실행시간 : " + (endTime-startTime));
return obj;
}
==================================================================
** ProceedingJoinPoint 은 상단에 적힌대로 return타입이 정해져있고, JoinPoint를 상속받는 클래스가 ProceedingJoinPoint 인데 상속받은 이유는 기존 JoinPoint의 매소드는 그대로 사용하되 proceed()를 사용하기 위해서다.
'홈페이지 만들기 > Spring' 카테고리의 다른 글
스프링 action-servlet 위치 및 파일명 변경 (0) | 2015.04.15 |
---|---|
스프링 한글 인코딩으로 만들기 (0) | 2015.04.15 |
spring 컨테이너 구동 및 객체검색 (0) | 2015.04.14 |
Log4j 간단 정리 (0) | 2015.04.14 |
공통/설정데이터 XML파일로 가져오기 (0) | 2015.04.08 |
댓글