https://sundaland.tistory.com/77
AOP (Aspect-Oriented Programming)는 프로그램 구조를 생각하는 또 다른 방법을 제공하여 OPP (Object-Oriented Programming)를 보안한다. OPP에서의 주요 모듈화 단위는 클래스인 반면, AOP에서 모듈화 단위가 aspect이다. aspect는 트랜잭션 관리와 같은 여러 타입과 객체에 걸쳐 있는 문제를 모듈화할 수 있게 해준다. 이러한 문제는 AOP 문헌에서 흔히
crosscutting concerns라고 불린다.
스프링의 주요 구성 요소 중 하나는 AOP 프레임워크이다. 스프링 IoC 컨테이너는 AOP에 의존하지 않으므로 (AOP를 사용하지 않아도 된다는 의미) AOP를 꼭 사용해야 하는 것은 아니지만, AOP는 스프링 IoC를 보완하여 매우 강력한 미들웨어 솔루션을 제공한다.
[ ▶ AspectJ pointcuts을 사용하는 Spring AOP ]
스프링은 scheman-based approach (XML 방식)이나 @AspectJ 어노테이션 스타일을 사용하여 사용자 정의 aspect를 작성하는 간단하고 강력한 방법을 제공한다. 이 두 스타일 모두 완전히 타입화된 advice와 AspectJ pointcut 언어의 사용을 제공하면서도 여전히 Spring AOP를 사용하여 위빙 (weaving)한다.
- 선언적 (declarative) 엔터프라이즈 서비스를 제공하기 위해. 가장 중요한 서비스는 선언적 트랙잰션 관리이다.
- 사용자들이 OOP를 AOP와 함께 사용하여 사용자 정의 aspect를 구현할 수 있도록 하기 위해 사용된다
[ ▷ AOP Concepts ]
- Aspect : 여러 클래스에 걸쳐 있는 관심사의 모듈화이다. 트랜잭션 관리는 엔터프라이즈 자바 애플리케이션에서 공통 관심사의 좋은 예이다. 스프링 AOP에서 aspect는 일반 클래스 (스키마 기반 접근 방식)를 사용하거나 @Aspect 어노테이션이 있는 일반 클래스를 사용하여 구현된다. (@AspectJ 스타일)
- Join Point : 프로그램 실행 중의 한 시점으로, 메서드 실행이나 예외 처리와 같은 순간을 의미한다. 스프링 AOP에서 조인 포인트는 항상 메서드 실행을 나타낸다. # aspect를 언제 붙일건가?
- Advice : 특정 조인 포인트에서 aspect가 수행하는 동작이다. 어드바이스의 종류로는 "around", "before", "after" 어드바이스가 있다. 스프링을 포함한 많은 AOP 프레임워크는 어드바이스를 인터셉터로 모델링하면, 조인 포인트 주번에 인터셉터 체인을 유지한다. # aspect를 어디에 붙인건가?
- Pointcut : 조인 포인트를 매칭하는 조건이다. 어드바이스는 포인트컷 표현식과 연관되며, 포인트컷이 매칭되는 모든 조인 포인트에서 실행된다. (특정 이름의 메서드 실행). 포인트컷 표현식에 의해 매칭된 조인 포인트 개념은 AOP의 핵심이며, 스프링은 기본적으로 AspectJ 포인트컷 표햔식 언어를 사용한다.
- Introduction : 타입을 대신하여 추가 메서드가 필드 를 선언하는 것이다. 스프링 AOP는 어드바이스된 객체에 새로운 인터페이스 (및 해당 구현)을 도입할 수 있게 한다. 예를 들어, Introduction을 사용하여 빈이 isModified 인터페이스를 구현하도록 하여 캐싱을 간소화할 수 있다. (Introduction은 AspectJ 커뮤니티에서 inter-type 선언으로 알려져 있다.)
- Target Object : 하나 이상의 aspect에 의해 어드바이스된 객체이다. 스프링 AOP는 런타임 프록시를 사용하여 구현되므로, 이 객체는 항상 프록시 객체이다.
- AOP proxy : aspect contracts (어드바이스 메서드 실행 등)을 구현하기 위해 AOP 프레임워크에서 생성된 객체이다. 스프링 프레임워크에서는 AOP 프록시가 JDK 동적 프록시 또는 CGLIB 프록시이다.
- Weaving : aspect와 다른 애플리케이션 타입 또는 객체를 연결하여 어드바이스된 객체를 생성하는 과정이다. 이는 컴파일 타임 (AspectJ 컴파일러 사용), 로드 타임, 또는 런타임에 수행될 수 있다. 스프링 AOP는 다른 순수 자바 AOP 프레임워크처럼 런타임에 위빙을 수행한다.
[ ▷ Spring AOP에서 제공하는 어드바이스 유형 ]
- Before advice : 조인 포인트전에 실행되는 어드바이스로, 조인 포인트로의 실행 흐름을 방해할 수 없다 (예외를 발생시키지 않는 한).
- After returning advice : 조인 포인트가 정상적으로 완려된 후 (메서드가 예외를 던지지 않고 반환된 경우) 실행되는 어드바이스.
- After throwing advice : 메서드가 예외를 던져 종료되면 실행되는 어드바이스.
- After (finally) advice : 조인 포인트가 어떤 방식으로 종료되든 (정상 또는 예외 반환) 실행되는 어드바이스.
- Around advice : 메서드 호출과 같은 조인 포인트를 둘러싸는 어드바이스로, 가장 강력한 어드바이스 유형이다. Around 어드바이스는 메서드 호출 전후에 커스텀 동작을 수행할 수 있으며, 조인 포인트로의 실행을 계속 진행할지, 자체 반환 값을 반환하거나 예외를 발생시켜 조언된 메서드 실행을 단축할지 선택할 책임이 있다.
Around 어드바이스는 가장 일반적인 어드바이스 유형이다. 스프링 AOP가 AspectJ와 같이 모든 종류의 어드바이스를 제공하므로, 필요한 동작을 구현할 수 있는 가장 덜 강력한 어드바이스 유형을 사용하는 것이 좋다. 예를 들어, 메서드의 반환 값으로 캐시를 업데이트해야 한다면, Around 어드바이스 대신 After retruning 어드바이스를 사용하는 것이 더 좋다. 더 구체적인 어드바이스 유형을 사용하면 더 간단한 프로그래밍 모델을 제공하여 오류 발생 가능성이 적다.
예를 들어, Around 어드바이스에 사용되는 JointPoint에서 proceed() 메서드를 호출할 필요가가 없으며, 따라서 이를 호출하지 않아도 된다.
모든 어드바이스 파라미터는 정적으로 타입이 지정되므로, 적절한 타입 (메서드 실행의 리턴 값 타입)의 어드바이스 파라미터로 작업할 수 있다.
포인트컷에 의해 매칭된 조인 포인트의 개념은 AOP의 핵심으로, 이를 통해 객체 지향 계층 구조와 독립적으로 어드바이스를 적용할 수 있다. 예를 들어, 선언적 트랜잭션 관리릴 제공하는 Around 어드바이스를 서비스 계층의 여러 객체에 걸친 메서드 집합을 적용할 수 있다.
[ ▷ Spring AOP Capabilities and Goals ]
스프링 AOP는 순수 자바로 구현되었다. 이를 위해 특별한 컴파일 과정이 필요하지 않다. 또한 스프링 AOP는 클래스 로더 계층을 제어할 필요가 없으므로 서블릿 컨테이너나 애플리케이션 서버에서 사용하기 적합하다.
현재 스프링 AOP는 메서드 실행 조인트 포인트 (스프링 빈의 메서드 실행을 어드바이스하는 것)만을 지원한다. 필드 인터셉션은 구현되어 있지 않지만, 필드 인터셉션 지원이 추가되더라도 스프링 AOP의 핵심 API를 손상시키지 않고 구현될 수 있다. 필드 접근과 업데티으 조인 포인트를 어드바이스해야 할 필요가 있다면 AspectJ와 같은 언어를 고려해야 한다. 스프링 AOP의 AOP 접근 방식은 대부분의 다른 AOP 프레임워크오 다르다. 목표는 가장 완벽한 AOP 구현을 제공하는 것이 아니다. 오히려, AOP 구현과 스프링 IoC 사이의 긴밀한 통합을 제공하여 엔터프라이즈 애플리케이션에서 흔히 발생하는 문제를 해결하는데 중점을 둔다.
따라서 스프링 프레임워크의 AOP 기능은 일반적으로 스프링 IoC 컨테이너와 함께 사용된다. aspect은 일반적인 빈 정의 문법을 사용하여 구성된다. (이로 인해 강력한 auto-proxying 기능을 사용할 수 있다). 이것은 다른 AOP 구현과의 중요한 차이점이다. 스프링 AOP를 사용하면 매우 세밀한 객치 (일반적으로 도메인 객체)를 어드바이스하는 것과 같은 작업을 쉽게 또는 효율적으로 수행할 수 없다. 이러한 경우에는 AsepctJ가 가장 좋은 선택이다. 스프링 AOP에 적합한 엔터프라이즈 자바 애플리케이션의 대부분 문제에 대해 훌륭한 솔류션을 제공한다.
스프링 AOP는 종합적인 AOP 솔루션을 제공하기 위해 AspectJ와 경쟁하려고 하지 않는다. 스프링 AOP와 같은 프록시 기반 프레임워크와 AspectJ와 같은 완전한 프레임워크가 모두 가치가 있으며, 경쟁 관계가 아닌 상호 보완적이다. 스프링은 스프링 AOP와 IoC를 AspectJ와 원할하게 통합하여 일관된 스프링 기반 애플리케이션 아키텍처 내에서 AOP를 사용할 수 있도록 한다. 이 통합은 스프링 AOP API나 AOP Alliance API에 영향을 미치지 않으며, 스프링 AOP는 이전 버전과의 호환성을 유지한다.
[ ▷ Note ]
스프링 프레임워크의 중심 원칙 중 하나는 비침투성 (non-invasiveness)이다. 이는 비즈니스 또는 도메인 모델에 프레임워크 특정 클래스와 인터페이스를 강제로 도입하지 않아야 한다는 아이디어이다. 그러나 특정 시나리오에서는 스프링 프레임워크가 특정 코드베이스에 스프링 프레임워크 관련 의존성을 도입할 수 있는 옵션을 제공하기도 한다. 이러한 옵션을 제공하는 이유는 특정 기능을 더 쉽게 일거나 코딩할 수 있는 경우가 있기 때문이다. 그러나 스프링 프레임워크는 거의 항상 선택권을 제공한다. 특정 사용 사례나 시나리오에 가장 적합한 옵션을 선택할 수 있는 자유를 제공하는 것이다. AspectJ, 스프링 AOP 또는 둘 다 선택할 수 있다. 또한 @AspectJ 어노테이션 스타일 접근 방식 또는 스프링 XML 스타입 접근 방식 중에서 선택할 수 있다.
[ ▷ AOP Proxies ]
스프링 AOP는 기본적으로 AOP 프록시를 위해 표준 JDK 다이나믹 프록시를 사용한다. 이를 통해 어떤 인터페이스 (또는 인터페이스 세트)도 프록시화할 수 있다.
스프링 AOP는 또한 CGLIB 프록시를 사용할 수 있다. 이는 인터페이스가 클래스를 프록시화하기 위해 필요하다. 기본적으로 비즈니스 객체가 인터페이스를 구현하지 않는 경우 CGLIB이 사용된다. 클래스보다는 인터페이스를 대상으로 프로그래밍하는 것이 좋은 관행이기 때문에, 클래스는 일반적으로 하나 이상의 인터페이스를 구현한다. 인터페이스에 선언되지 않은 메서드를 어드바이스해야 하거나, 프록시 객체를 구체적인 타입으로 메서드에 전달해야 하는 경우에는 CGLIB 사용을 강제할 수 있다.
스프링 AOP가 프록시 기반이라는 사실을 이해하는 것이 중요하다.