티스토리 뷰

어드바이스는 각 조인포인트에 삽입되어 동작할 횡단 관심에 해당하는 공통 기능이며, 동작 시점은 설정 파일에서 설정이 가능하다.

 

스프링 프레임워크에서는 총 다섯가지의 동작 시점을 제공한다.


동작 시점 설명
Before 비즈니스 메서드 실행 전 동작
After - After Returning: 비즈니스 메서드가 성공적으로 리턴되면 동작 (try)
- After Throwing: 비즈니스 메서드가 실행 중 예외가 발생하면 동작 (catch)
- After: 비즈니스 메서드가 실행된 후, 무조건 실행 (finally)
Around 메서드 호출 자체를 가로채 비즈니스 메서드 실행 전, 후에 처리할 로직을 삽입할 수 있음

 

간단하게 예제들을 한번 확인해보자. 횡단 관심을 제외한 공통 예제 코드는 다음과 같다.

 

◎UserServiceImpl

package com.choonham.biz.board.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.choonham.biz.board.UserService;
import com.choonham.biz.board.UserVO;

@Service("userService")
public class UserServiceImpl implements UserService{

	@Autowired
	private UserDAO userDAO;

	@Override
	public UserVO getUserInfo(UserVO vo) {
		System.out.println("ㅎㅅㅎ");
		return userDAO.getUserInfo(vo);
	}

	public UserServiceImpl() {
		// TODO Auto-generated constructor stub
	}
}

 

◎Main

package com.choonham.biz;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;

import com.choonham.biz.board.UserService;
import com.choonham.biz.board.UserVO;

public class Client {

	public static void main(String[] args) {
		AbstractApplicationContext container = new GenericXmlApplicationContext("applicationContext.xml");
		
		UserService userService = (UserService)container.getBean("userService");
		
		UserVO vo = new UserVO();
		vo.setId("123");
		vo.setPassword("1234");
		
		UserVO user = userService.getUserInfo(vo);
		
		if(user != null){
			System.out.println(" 끝!!");
		} 
		
		container.close();

	}

}

1. Before

 

◎BeforeLog (횡단 관심)

package com.choonham.biz.board.common;

public class BeforeLog {

	public void printLog() {
		System.out.println("[Advice] I'm Before!");
	}
	public BeforeLog() {
		// TODO Auto-generated constructor stub
	}

}

 

◎xml 설정 파일

<bean id = "before_log" class = "com.choonham.biz.board.common.BeforeLog"></bean>
<bean id = "after_return_log" class = "com.choonham.biz.board.common.AfterReturnLog"></bean>
<bean id = "after_throw_log" class = "com.choonham.biz.board.common.AfterThrowingLog"></bean>
<bean id = "after_log" class = "com.choonham.biz.board.common.AfterLog"></bean>
<bean id = "around_log" class = "com.choonham.biz.board.common.Around"></bean>

<aop:config>
  <aop:pointcut expression="execution(* com.choonham.biz.board..*UserServiceImpl.*(..))" id="allPointcut"/>
  <aop:pointcut expression="execution(* com.choonham.biz.board..*UserServiceImpl.get*(..))" id="getPointcut"/>
  <aop:aspect ref="before_log">
  	<aop:before  pointcut-ref="allPointcut" method = "printLog"/>
  </aop:aspect>
</aop:config>


2. after-returning

 

◎AfterReturnLog (횡단 관심)

package com.choonham.biz.board.common;

public class AfterReturnLog {

	public void printLog() {
		System.out.println("[Advice] I'm AfterReturning!");
	}
	
	public AfterReturnLog() {
		// TODO Auto-generated constructor stub
	}

}

◎xml 설정 파일

<bean id = "before_log" class = "com.choonham.biz.board.common.BeforeLog"></bean>
<bean id = "after_return_log" class = "com.choonham.biz.board.common.AfterReturnLog"></bean>
<bean id = "after_throw_log" class = "com.choonham.biz.board.common.AfterThrowingLog"></bean>
<bean id = "after_log" class = "com.choonham.biz.board.common.AfterLog"></bean>
<bean id = "around_log" class = "com.choonham.biz.board.common.Around"></bean>

<aop:config>
  <aop:pointcut expression="execution(* com.choonham.biz.board..*UserServiceImpl.*(..))" id="allPointcut"/>
  <aop:pointcut expression="execution(* com.choonham.biz.board..*UserServiceImpl.get*(..))" id="getPointcut"/>
  <aop:aspect ref="after_return_log">
  	<aop:after-returning  pointcut-ref="allPointcut" method = "printLog"/>
  </aop:aspect>
</aop:config>

 


3. after-throwing

 

◎AfterThrowingLog (횡단 관심)

package com.choonham.biz.board.common;

public class AfterThrowingLog {

	public void printLog() {
		System.out.println("[Advice] I'm AfterThrowing!");
	}
	
	public AfterThrowingLog() {
		// TODO Auto-generated constructor stub
	}

}

◎xml 설정 파일

<bean id = "before_log" class = "com.choonham.biz.board.common.BeforeLog"></bean>
<bean id = "after_return_log" class = "com.choonham.biz.board.common.AfterReturnLog"></bean>
<bean id = "after_throw_log" class = "com.choonham.biz.board.common.AfterThrowingLog"></bean>
<bean id = "after_log" class = "com.choonham.biz.board.common.AfterLog"></bean>
<bean id = "around_log" class = "com.choonham.biz.board.common.Around"></bean>

<aop:config>
  <aop:pointcut expression="execution(* com.choonham.biz.board..*UserServiceImpl.*(..))" id="allPointcut"/>
  <aop:pointcut expression="execution(* com.choonham.biz.board..*UserServiceImpl.get*(..))" id="getPointcut"/>
  <aop:aspect ref="after_throw_log">
  	<aop:after-throwing  pointcut-ref="allPointcut" method = "printLog"/>
  </aop:aspect>
</aop:config>

 

또한 Exception 을 발생시켜야하기 때문에 비즈니스 로직을 조금 변경했다.

 

◎UserServiceImpl

package com.choonham.biz.board.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.choonham.biz.board.UserService;
import com.choonham.biz.board.UserVO;

@Service("userService")
public class UserServiceImpl implements UserService{

	@Autowired
	private UserDAO userDAO;

	@Override
	public UserVO getUserInfo(UserVO vo) {
        	vo = null;
		System.out.println("ㅎㅅㅎ");
		return userDAO.getUserInfo(vo);
	}

	public UserServiceImpl() {
		// TODO Auto-generated constructor stub
	}
}


4. after

 

◎AfterLog (횡단 관심)

package com.choonham.biz.board.common;

public class AfterLog {

	public void printLog() {
		System.out.println("[Advice] I'm After!");
	}
	
	public AfterLog() {
		// TODO Auto-generated constructor stub
	}

}

◎xml 설정 파일

<bean id = "before_log" class = "com.choonham.biz.board.common.BeforeLog"></bean>
<bean id = "after_return_log" class = "com.choonham.biz.board.common.AfterReturnLog"></bean>
<bean id = "after_throw_log" class = "com.choonham.biz.board.common.AfterThrowingLog"></bean>
<bean id = "after_log" class = "com.choonham.biz.board.common.AfterLog"></bean>
<bean id = "around_log" class = "com.choonham.biz.board.common.Around"></bean>

<aop:config>
  <aop:pointcut expression="execution(* com.choonham.biz.board..*UserServiceImpl.*(..))" id="allPointcut"/>
  <aop:pointcut expression="execution(* com.choonham.biz.board..*UserServiceImpl.get*(..))" id="getPointcut"/>
  <aop:aspect ref="after_throw_log">
      <aop:after-throwing  pointcut-ref="allPointcut" method = "printLog"/>
  </aop:aspect>
  <aop:aspect ref="after_log">
 	 <aop:after  pointcut-ref="allPointcut" method = "printLog"/>
  </aop:aspect>
</aop:config>


5. around

 

around 어드바이스는 클라이언트의 메서드 호출을 가로채기 때문에 클라이언트가 호출한 비즈니스 메서드가 실행되기 전에 사전 로직 처리를 할 수 있으며, 비즈니스 메서드가 모두 실행되고 나서도 사후 로직 처리를 수행할 수 있다.

 

이를 위해 코드는 다음과 같이 구성한다.

 

◎AroundLog (횡단 관심)

package com.choonham.biz.board.common;

import org.aspectj.lang.ProceedingJoinPoint;

public class Around {

	public Object aroundLog(ProceedingJoinPoint pjp) throws Throwable {
		System.out.println("[before]: before");
		Object returnObj = pjp.proceed();
		System.out.println("[after]: after");
		return returnObj;
	}
	public Around() {
		// TODO Auto-generated constructor stub
	}

}

pjp.proceed() 메서드 호출 앞에 작성된 코드는 Bofore 과 동일하게 동작하며, 메서드 호출 뒤에 작성된 코드는 After 와 동일하게 동작한다.

 

◎xml 설정 파일

<bean id = "before_log" class = "com.choonham.biz.board.common.BeforeLog"></bean>
<bean id = "after_return_log" class = "com.choonham.biz.board.common.AfterReturnLog"></bean>
<bean id = "after_throw_log" class = "com.choonham.biz.board.common.AfterThrowingLog"></bean>
<bean id = "after_log" class = "com.choonham.biz.board.common.AfterLog"></bean>
<bean id = "around_log" class = "com.choonham.biz.board.common.Around"></bean>

<aop:config>
  <aop:pointcut expression="execution(* com.choonham.biz.board..*UserServiceImpl.*(..))" id="allPointcut"/>
  <aop:pointcut expression="execution(* com.choonham.biz.board..*UserServiceImpl.get*(..))" id="getPointcut"/>
  <aop:aspect ref="around_log">
  	<aop:around  pointcut-ref="allPointcut" method = "aroundLog"/>
  </aop:aspect>
</aop:config>
	

반응형

'[JAVA] > Spring' 카테고리의 다른 글

[Spring] AOP: 어노테이션을 이용한 구현  (0) 2021.06.18
[Spring] AOP: JoinPoint  (0) 2021.06.18
[Spring] AOP 용어 정리  (0) 2021.06.17
[Spring] AOP(Aspect Oriented Programming)  (0) 2021.06.17
[Spring] Spring JDBC 2 : DAO Class 구현  (0) 2021.06.17
Comments