공통 관심과 핵심 관심을 분리시켜 코드 중복을 제거
코드의 재사용성을 높이는 프로그래밍 방법론
핵심 기능 코드의 변경 없이 런타임 시 프록시 객체를 생성해 공통기능을 적용
핵심 기능을 다른 객체에게 위임하고, 부가적인 기능을 제공하는 객체
스프링 프레임워크는 프록시 객체를 자동으로 생성하여 AOP를 구현한다.
애스펙트
적용되는 공통 관심 기능
어드바이스
기능 내용과 적용 시점을 정의
조인포인트
어드바이스가 적용될 위치(메서드, 예외 발생 또는 필드 변경, 스프링에선 보통 메서드)
포인트컷
조인 포인트의 부분집합, 공동기능 적용 대상을 선정(메서드를 선정)
위빙
어드바이스를 (핵심 기능 코드에) 적용하는 것.
컴파일 시, 클래스 로딩 시, 런타임 시로 분류, 보통 런타임 시 위빙을 사용
@Before
메서드 호출 전@After
메서드 실행 후@AfterReturning
메서드 값을 반환 후@AfterThrowing
메서드 예외 발생 시@Around
메서드 실행 전과 후 또는 예외 발생 시(가장 많이 사용됨)
1. @Aspect 지정(컨테이너 등록, 타겟 객체와 함께 @Configuration 선행)
2. @Pointcut 설정(execution() 설정) - 어드바이스 값으로도 설정 가능
3. @어드바이스 설정(Advice 유형 선택, pointcut, Advice 메서드)
4. @Configuration 지정 클래스에 @EnableAspectJAutoProxy를 추가하여 활성화
import org.aspectj.lang.*

@Aspect, @pointcut

@Before

@AfterReturning

@EnableAspectJAutoProxy
어드바이스(@Around, 기능과 시점)와 포인트컷(@Pointcut,타켓 지정)을 포함
명시자 execution()을 사용하여 어드바이스 대상이 되는 메서드를 지정
execution([접근제어자] 반환 타입 [패키지/클래스.] 메서드명 (파라미터 타입|"..",...) [throws Exception])
[모든 타입]의 [모든 리턴타입]을 갖는 [com.하위 경로]의 [set으로 시작하는 모든] 메서드
execution(* * com..set* (..))
[] 생략 가능, 와일드카드 * 사용 가능(타입, 메서드 이름 등..)
..는 매개변수 0개 이상임을 표현,
someMethod(Integer, ..) 라면 한 개 이상의 매개변수를 가지며 첫 매개변수가 Integer
someMethod(.., String)라면 마지막 매개변수가 String 타입임을 표현
someMethod(.., *)라면 반드시 두 개의 매개변수를 가짐
공통 기능을 실행 할 메서드 위에 적용
값으로 포인트 컷으로 지정한 메서드를 넣으면 해당 메서드 실행 전과 후에 메서드 내용 공통 기능으로 실행
@Around("targetMethod()")
@Around로 지정한 매서드가 받는 매개변수(ProceedingJoinPoint 타입)는 타깃 객체의 실제 메서드를 호출할 때 사용
Object result = joinPoint.proceed();
poceed() 실제 타깃이 되는 객체의 메서드를 호출
@Aspect이 붙은 빈 객체를 찾아 해당 객체의 포인트컷과 어드바이스 설정을 자동으로 사용
'빈 객체'를 찾아주기 때문에 @Aspect클래스를 스프링 빈으로 먼저 등록시켜 줘야 한다
여러 개의 어드바이스를 적용시 @Order 값 지정을 통해 우선순위 변경 가능
@Order(value = 1)
실행 중인 프로그램에서 특정 지점을 나타내며 보통 실행중인 메서드 정보를 호출하는데 사용
JoinPoint 인터페이스의 메서드
getSignature()호출 메서드의 시그니처 호출
getSignature().getName()메서스명 호출
getArgs()호출 매서드의 매개 변수의 목록 호출(배열값을 리턴한다)
배열요소.getClass().getName()로 타입을 확인할 수 있다
getTarget()호출 매서드의 객체 호출
getThis()Join Point를 구현한 객체를 반환
proceed()Join Point에서 현재 실행 중인 메서드
return JoinPoint.proceed()
JoinPoint.proceed()는 어드바이스 적용 메서드(핵심기능)를 호출
위 아래로 공통기능 코드를 구현...
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
//로그 임폴트 패키지
private static final Logger log = LoggerFactory.getLogger(LoggingAspect.class);
//사용 클래스가 파라미터
log.info("[메서드명] : {}", joinPoint.getSignature().getName());
//{}내에 인자가 출력된다