OOP적으로 봤을 때, 서비스 클래스는 다른 외부 기술에 의존하지 않고 순수한 자바 언어로 작성되어 있어야 좋다.
근데 결국 Jdbc를 쓰든, JPA를 쓰든 트랜잭션을 열고 롤백하고 트랜잭션을 닫으려면 서비스 클래스에 순수 비즈니스 로직만 담기 어렵다.
이에 우린 @Transactional 어노테이션을 통해 프록시를 활용한다. 순수한 자바, 비즈니스 로직만을 만든 채
어플리케이션의 흐름은 그냥 스프링(혹은 그에 준하는)에 맡기는 거다.
각 메서드나 클래스에 핵심 기능을 실행할 때 필요한 부가기능을 편리하게, 그리고 OOP에 맞게 디자인 하기 위해서 만들어진 것이 바로 AOP다.
OOP만을 생각한다면, 맨 위 사진처럼 트랜잭션을 활용할 때, 코드가 쓸데 없이 복잡하고 길어지기 마련이다.
이는 유지 보수상에도 좋지 않은게, 순수한 자바 로직만 있어야 보기도 편하고 코드 작성 길이도 줄어든다.
특히 상기 이미지에서 try, catch는 반복이다. DB Connect를 따오고, 이를 통해 sql을 날리고 롤백이나 커밋을 한다.
sql문을 제외하곤 거의 동일한 부분을 계속 코딩해야 한다는 것임.
시간 = 비용이다.
AOP는 저런 공통 부분을 한꺼번에 처리할 수 있게끔 만들어준다.
스프링은 프록시 방식으로 AOP를 실행하기 때문에 메서드 실행 지점에만 적용할 수 있다.
그러므로 조인포인트가 무적권 메서드 실행에만 적용할 수 있는게 아니다.
프록시를 사용할 경우 기존 클래스를 상속받는 가상 클래스가 생기고 그 안에 메서드를 오버라이딩 하는 방식으로 작동 한다.
스프링AOP는 스프링 빈에만 적용할 수 있다. @Transactional같은 메서드도 빈 등록을 해야만 사용할 수 있음.
JoinPoint 인터페이스의 주요 기능
어드바이스 지점 중 Before, After Returning, After Throwing, After은 매개변수로 JoinPoint를 사용한다.
Around는 ProceedingJoinPoint를 매개변수로 사용한다.
- proceed() : 다음 어드바이스나 타겟을 호출한다.
Around는 얘를 써야 하기 때문
어노테이션으로 지정할 수 있다.
기본적으로 순서를 보장하지 않기 때문에, @Aspect, @Order 어노테이션을 활용해아 한다.
클래스 단위로 적용할 수 있음. 사용할 때엔 애스택트들을 별도의 클래스로 분리해야 한다.Around
Around는 가장 강력한 어드바이스다. 이 어드바이스 하나로 상기 4개 모든 기능을 수행할 수 있다.
proceed()를 통해 대상을 실행하고, 여러번 실행할 수도 있다.
다만 각 어노테이션 이름이 워낙 명시적이어서 실제 설계시엔 각각의 어드바이스를 잘 활용해야 하겠다.
@Pointcut("execution(* transfer(..))") //이런 식으로 사용함
void exampleMethod() {} // 포인트컷의 서명
포인트컷은 &&, ||, !를 사용해서 결합할 수 있다.
스프링은 AOP를 지원함. @AspectJ를 활용하면 됨.
@AspectJ 는 Java AOP 소프트웨어의 사실상의 표준이다. (개많이씀)
스프링 역시 AspectJ를 통한 AOP 개발을 지원한다. 때문에 스프링AOP와 AspectJ 두가지 방법 모드 스프링에서 해석이 가능함.
스프링 AOP은 그럼에도 AspectJ 컴파일러나 위버에 의존하지 않는다.
@Configuration에 AspectJ 지원을 활성화 하려면 @EnableAspectJAutoProxy을 추가로 선언해준다.
AspectJ 지원이 활성화 되면 @AspectJ가 선언된 빈을 스프링에서 자동으로 감지하고 스프링AOP를 구성하는데 사용한다.