본문으로 바로가기

[스프링]4.스프링을 쓰는이유? AOP

category SPRING/스프링 2021. 3. 26. 18:06
728x90
반응형
SMALL

AOP란


Aspect Oriented Programing 의 약자로 OOP와 같은 프로그래밍 패러다임의 하나이다.

"횡단 관심사" 를 분리함으로써 모듈성을 증가시키는 것이 목적인 프로그램이다.

 

 

횡단 관심사

어플리케이션을 구성하는 중요한 요소임과 동시에 부가적인 기능을 담당하는 것

EX) 트랜잭션, 로깅, 성능분석

 

 

🌈관점을 나눠서 구현하자 ❗️

출처:https://jojoldu.tistory.com/71
핵심기능에서의 관점

✏️핵심기능의 관점에서는 각각의 Service는 Board, User, XXX 으로 공통된 요소가 없다

각각의 Service는 각자 코드를 구현하고 있으나 부가기능의 관점에서 봤을땐 상황이 달라진다.

부가기능에서의 관점

✏️부가기능의 관점에서는 각각의 Service 수행시잔 측정을 나타내는 before(), after()의 메소드가 공통되는 것을 알수 있다.

 

💪🏻AOP 는 여기서 시작한다.

기존 OOP에서 바라보던 관점을 달리하여 부가기능적인 측면에서 볼때,

공통된 요소를 추출하는 것 이다.

여기서 가로(횡단)영역의 공통된 부분을 잘라냈다고 하여 AOP를 크로스 컷팅 이라고 부르기도 한다.

🌈결국 공통된 기능을 재사용하는 기법이다.

 

🤖OOP 에서는 공통된 기능을 재사용하는 방법으로 상속, 위임을 사용한다.

허나, 전체 어플리케이션에서 수많은 부가기능들을 상속이나 위임으로 처리하기에는 무리가있다.❌

 

예를 보며 확인해보자

SampleService 인터페이스

public interface SampleService {
	
	public Integer doAdd(String str1, String str2)throws Exception;
}

 

SampleService 구현 클래스

@Service
public class SampleServiceImpl implements SampleService {

	//테스트 코드를 작성하면서 log.info()를 이용해 로그를 기록하는 부분을 AOP를 적용하여 중복 기록하는 부분을 제거 시킬것이다.
	
	
	@Override
	public Integer doAdd(String str1, String str2) throws Exception {
		// TODO Auto-generated method stub
		return Integer.parseInt(str1)+Integer.parseInt(str2);
	}
	

}

 

SampleService 구현 클래스의 메서드를 이용할때 로그를 남기는 aop 적용 부분

@Component
@Log4j
@Aspect
public class LogAdvice {

	//execution...문자열은 AspectJ의 표현식이다. 접근제한자와 특정 클래스의 메서드를 지정할 수 있음.
	@Before( "execution(* org.zerock.service.SampleService*.*(..))")
	public void logBefore() {
		
		log.info("============================");
	}
	
	//execution으로 시작하는 포인트컷 설정에 doAdd()메서드 명시하고 파라미터값 지정함
	// 뒤족 &&args 부분은 변수명을 지정 이 두 정보를 이용하여 logBeforeWithParam 메서드의 파라미터값을 설정
	@Before( "execution(* org.zerock.service.SampleService*.doAdd(String,String)) && args(str1, str2)")
	public void logBeforeWithParam(String str1, String str2) {
		
		log.info("str1: "+str1);
		log.info("str2: "+str2);
	}
	
	@AfterThrowing(pointcut = "execution(* org.zerock.service.SampleSerivce*.*(..))", throwing="exception")
	public void logException(Exception exception) {
		
		log.info("Exception.....!!!!!");
		log.info("exception: "+ exception);
	}
	
	@Around("execution(* org.zerock.service.SampleService*.*(..))")
	public Object logTime( ProceedingJoinPoint pjp) {
		
		long start = System.currentTimeMillis();
		
		log.info("Target: "+pjp.getTarget());
		log.info("Param: "+Arrays.toString(pjp.getArgs()));
		
		Object result = null;
		
		try {
			result = pjp.proceed();
		} catch (Throwable e) {
			e.printStackTrace();
		}

		long end= System.currentTimeMillis();
		
		log.info("TIME: "+(end - start));
		
		return result;
	}
	
}

 

어떤 위치에 Advice를 적용할 것인지를 결정하는 포인트 컷이다.

@Before(~~)org.zerock.service.SampleService*.*(..))")

 

@AfterThrowing 은 지정된 대상이 예외를 발생한 후에 동작하면서 문제를 찾을수 있도록 도와준다.

@AfterThrowing(pointcut = "execution(* org.zerock.service.SampleSerivce*.*(..))", throwing="exception")
	public void logException(Exception exception)

 

@Around 부분은 직접 대상 메서드를 실행할 수 있는 권한을 가지고 있고, 메서드의 실행 전과 실행 후에 처리가 가능하다.

ProceedingJoinPoint는 @Around와 같이 결합해서 파라미터나 예외 등을 처리할 수 있다.

그리고 AOP의 대상이 되는 Target이나 파라미터등을 파악할 수 있고 직접 실행 결과를 결정할 수도 있음

@Before과는 달리 리턴 타입이 void가 아닌 타입으로 설정하고, 메서드의 실행 결과 역시 직접 반환하는 형태로 작성해야함

 

해당 테스트코드 실행시

	@Test
	public void testAdd() throws Exception{
		
		log.info("testAdd[더하기 테스트]");
		log.info(service.doAdd("123", "456"));
	}

 

 

출처;jojoldu.tistory.com/71

728x90
반응형
LIST