KIC/Spring

day63 - Spring Framework(스프링, AOP)

바차 2021. 9. 13. 22:23
반응형

[AOP]

- Aspect Oriented Programming. 관점 지향 프로그래밍으로 어플리케이션에서 전반적으로 사용되는 공통 기능들을 공통 관심 사항으로 구분한다.

- 중복 코드를 제거하고 그로 인한 간경성과 생산성을 얻을 수 있다.

- 재사용성과 유지보수성 또한 증가한다.

 

- Advice

언제 공통 관심 기능을 핵심 로직에 적용할 것인 지를 정의한다.

 

- Jointpoint

Advice 가 적용 가능한 지점을 의미한다. 메소드 호출, 필드값 변경 등이 이에 해당한다.

 

- Pointcut

Joinpoint의 부분 집합으로써 실제로 Advice가 적용 되는 Jointpoint를 말한다. 정규 표현식이나 Aspectj의 문법을 사용하여 Pointcout을 정의할 수 있다.

 

- Aspect

- 여러 객체에 공통으로 적용되는 공통 관심 사항을 Aspect라고 한다.

 

 

 

 

[Advice의 종류]

- Before Advice

대상 객체의 메서드 호출 전에 공통 기능을 실행한다.

 

- After Returning Advice

대상 객체의 메서드가 예외 없이 실행한 이후에 공통 기능을 실행한다.

 

- After Throwing Advice

대상 객체의 메서드 실행 도중 예외가 발생시에 공통 기능을 실행한다.

 

- After Advice

대상 객체의 메서드 실행 도중 예외가 발생 했는지 여부와 상관없이 메서드 실행 후 공통 기능을 실행한다.

(try catch finally 에서 finally 블록과 비슷한 역할이다.)

 

- Around Advice

대상 객체의 메서드 실행 전, 후 또는 예외 발생 시점에 공통 기능을 실행 시에 사용한다. 범용으로 사용 가능하다.

 

 

 

 

[Main2.java]

package ch03_AOPXmlAnno;
import org.springframework.context. ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import di06.Article;
import di06.ArticleNotFoundException;
import di06.ReadArticleService;

public class Main2 {

	public static void main(String[] args) {

	String[] config = {"ch03_AOPXmlAnno/di.xml", "ch03_AOPXmlAnno/aop2.xml"}; 
	ApplicationContext ctx = new ClassPathXmlApplicationContext(config); 
	ReadArticleService service = ctx.getBean("readArticleService", ReadArticleService.class);

	try {
		Article a1 =  service.getArticleAndReadCnt(1); //A 
		Article a2 = service.getArticleAndReadCnt(1); //B 
		System.out.println("[main] a1 == a2 : " + (a1==a2));
		service.getArticleAndReadCnt(0); //C
	} catch (ArticleNotFoundException e) {

	System.out.println("[main]" + e.getMessage());
	}
	}
}

 

[aop.xml]

<?xml version="1.0" encoding="utf-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xmlns:context="http://www.springframework.org/schema/context" 
	xmlns:p="http://www.springframework.org/schema/p" 
	xmlns:aop="http://www.springframework.org/schema/aop" 
	xsi:schemaLocation="http://www.springframework.org/schema/beans
			http://www.springframework.org/schema/beans/spring-beans.xsd
			http://www.springframework.org/schema/aop 
			http://www.springframework.org/schema/aop/spring-aop.xsd
			http://www.springframework.org/schema/context
			http://www.springframework.org/schema/context/spring-context.xsd">

	<bean id="LoggingAdvice" class="di06.LoggingAdvice" />
	<bean id="cacheAdvice" class="di06.ArticleCacheAdvice"/>

	<aop:config>
		<aop:aspect id="LoggingAspect" ref="LoggingAdvice">
			<aop:pointcut id="publicMethod"
				expression="execution (public * di06.*Service.*(..))" />
			<aop:before method="before"
				pointcut="execution (public * di06.*Service.*(..))" />
			<aop:after-returning method="afterReturning"
				pointcut-ref="publicMethod" returning="ret" />
			<aop:after-throwing method="afterThrowing"
				throwing="ex" pointcut-ref="publicMethod" />	
			<aop:after method="afterFinally" 
				pointcut-ref="publicMethod" />
		</aop:aspect>
		
		<aop:aspect id="cacheAspect" ref="cacheAdvice">
			<aop:around method="cache" pointcut="execution(public * *..ReadArticleServiceImpl.*(..))"/>
		</aop:aspect>
	</aop:config>
</beans>

 

[LoggingAdvice.java]

package di06;

public class LoggingAdvice {
	public void before() {
		System.out.println("[LA]메서드 실행 전(before) 전처리 수행함.");
	}
	public void afterReturning(Object ret) {
		System.out.println("[LA]메서드 정상 처리(afterReturning) 후 수행함 리턴값: " + ret);
	}
	public void afterThrowing(Throwable ex) {
		System.out.println("[LA]메서드 예외 발생 후(afterThrowing) 수행함 예외:" +ex.getMessage());
	}
	public void afterFinally() {
		System.out.println("[LA]메서드 실행 후(afterFinally) 후처리 수행함");
	}
}
300x250