- 기존 OOP(객체지향 프로그래밍)에서는 수행시간 측정과 같은 공통 관심사항을 여러곳에 적용하려면 중복된 코드가 생겨나는 한계가 있다. -> 이를 해결하기 위해 AOP 등장
- AOP는 문제를 해결하기 위해 핵신 관심 사항과 공통 관심 사항을 기준으로 프로그래밍 함으로써 공통 모듈을 손쉽게 적용할 수 있게 한다.

Advice : 어느 시점에 어떤 공통 관심기능(Aspect)을 적용할지 정의한 것
JoinPoint : Aspect가 적용 될 수 있는 지점.(Spring에서는 method), 즉 target객체가 구현한 인터페이스의 모든 method는 JoinPoint가 된다.
Pointcut : 공통 관심사항이 적용될 JoinPoint, Advice를 적용할 target의 method를 선별하는 정규 표현식이 사용된다.
@Around(value = "execution(* board.model.dao.Board*.list*(..))") // 모든 반환, board/model/dao에 있는 Board로 시작하는 클래스 의 list로 시작하는 method가 Pointcut이 된다.
Aspect(Class) : 여러 객체에서 공통으로 적용되는 공통 관심 사항, AOP의 기본 모듈이다.
Weaving : 어떤 Advice를 어떤 Pointcut에 적용시킬 것인지에 대한 설정
- Before Advice : 대상객체의 method 실행이 시작되기 전 Aop가 실행
- After Returning Advice
- 대상 객체의 method 실행이 정상적으로 끝난 뒤 실행
- return type : void
- args : org.aspectj.lang.JoinPoint 객체를 받거나 없어도 된다, 대상 method에서 반환되는 특정 개체 타입의 값을 argument로 받을 수 있다.
- Around Advice
- 위의 네 가지 Advice를 다 구현 할 수 있는 Advice
- return type : Object
- argument : org.aspectj.lang.ProceedingJoinPoint를 반드시 첫 argument로 지정
- After Advice
- 대상 객체의 method가 정상적으로 실행 되었는지 아니면 exception을 발생 시켰는 지의 여부와 상관없이 실행 종료 후 공통 기능 적용
- return type : void
- argument : 없거나 JoinPoint
- After Throwing Advice
- 대상 객체의 method 실행 중 예외가 발생한 경우 실행
- return type : void
- argument : 없거나 JoinPoint , 대상 method에서 전달되는 예외 객체를 argument로 받을 수 있다.
<bean id="advice" class="com.ssafy.board.aop.LogAdvice"/>
<aop:config>
<aop:pointcut id="beforePointcut" expression="execution(* board.model.dao.Board*.write*(..))" />
<aop:pointcut id="afterPointcut" expression="execution(* board.model.dao.Board*.write*(..))" />
<aop:pointcut id="aroundPointcut" expression="execution(* board.model.dao.Board*.list*(..))"/>
<aop:pointcut id="returningPointcut" expression="execution(* board.model.dao.Board*.write*(..))" />
<aop:pointcut id="throwingPointcut" expression="execution(* board.model.dao.Board*.write*(..))" />
<aop:aspect ref="advice">
<aop:before method="logBefore" pointcut-ref="beforePointcut"/>
<aop:after method="logAfter" pointcut-ref="afterPointcut"/>
<aop:around method="logAround" pointcut-ref="aroundPointcut"/>
<aop:after-returning method="logAfterReturning" pointcut-ref="returningPointcut" returning = "returnObj"/>
<aop:after-throwing method="logThrowing" pointcut-ref="throwingPointcut" throwing = "e"/>
</aop:aspect>
</aop:config>
@Component
@Aspect
public class LogAdvice {
@Before(value = "execution(* board.model.dao.Board*.write*(..))")
public void logBefore() {
System.out.println("AOP Before Log");
}
@After(value = "execution(* board.model.dao.Board*.write*(..))")
public void logAfter() {
System.out.println("AOP After Log");
}
@Around(value = "execution(* board.model.dao.Board*.list*(..))")
public Object logAround(ProceedingJoinPoint jp) throws Throwable {
System.out.println("AOP Around Before log");
// JointCut
Object proceed = jp.proceed();
Object[] args = jp.getArgs();
for (Object object : args) {
if(object instanceof Map) {
Map<String, String> map = (Map) object;
Set<String> keySet = map.keySet();
for (Object key : keySet) {
System.out.println(map.get(key));
}
}
}
System.out.println("AOP Around After log");
return proceed;
}
@AfterReturning(value = "execution(* board.model.dao.Board*.write*(..))", returning = "returnObj")
public void logAfterReturning(JoinPoint joingPoint, Object returnObj) throws Throwable{
System.out.println("AOP After Returning log");
}
@AfterThrowing(value = "execution(* board.model.dao.Board*.write*(..))", throwing = "e")
public void logThrowing(Exception e) {
System.out.println("AOP log"+ e.getMessage());
}
@Around(value = "execution(* board.model.service.Board*.deleteArticleList(..))")
public Object trace(ProceedingJoinPoint joinPoint) throws Throwable {
String signature = joinPoint.getSignature().toShortString();
StopWatch stopWatch = new StopWatch();
stopWatch.start();
Object result = joinPoint.proceed();
stopWatch.stop();
System.out.println("아티클 삭제 실행 시간 - " + stopWatch.getTotalTimeMillis()+"ms");
return result;
}
}