AOP를 구현하는 방법은 여러 가지 있지만, 스프링에서는 프락시(proxy)를 이용한다.
스프링에서 AOP를 구현하는 방법
· 프락시를 이용한 AOP는 아래 그림처럼 인터페이스를 구현한 프락시를 이용해서 Q 클래스가 호출한 메서드를 가로채서 어드바이스를 동작시킨다.
· Q 클래스에는 R 인터페이스 타입의 인스턴스 변수가 있고, 인터페이스 R을 구현한 RImpl 클래스를 DI를 활용하여 이용한다. 이때, RImpl 클래스의 어느 메서드를 실행해도 어드바이스가 동작하게 설정됐다고 가정한다.
- 스프링이라면 @Autowired 어노테이션이 붙는다.
· DIxAOP 컨테이너는 R 인터페이스를 구현한 프락시 클래스의 인스턴스를 자동으로 생성, Q 클래스의 R 인터페이스 변수에 인젝션한다.
- Q 클래스는 R 인터페이스를 구현한 클래스의 인스턴스가 인젝션되므로, 그 인스턴스가 진짜 RImpl 클래스 인스턴스인지 알 수 없다.
· 자동 생성된 프락시 클래스의 인스턴스는 RImpl 클래스로 구현된 메서드를 호출하도록 구현되어 있고, 어드바이스 종류에 따라 Rimpl 클래스의 메서드를 호출하기 전, 후에 어드바이스를 호출한다.
· 다음과 같이 인터페이스를 구현하는 클래스의 인터페이스라면 무엇이든 인젝션할 수 있다는 특성을 이용한 프락시를 통해 AOP를 구현하는 것이다.
· 프락시 기반 AOP는 단순한 자바 프로그래밍으로 구성되므로 클래스의 바이너리를 수정하는 다른 방식의 AOP와 비교하면, 메서드 이외의 필드 등 세밀한 AOP를 할 수 없고, 성능면에서 우수하지 않은 단점도 있다.
- 하지만 프락시 기반 AOP도 트랜잭션 관리, 오브젝트 그룹, 시큐리티, 형의 재정의 등 AOP로 구현되는 대부분의 기능을 수행할 수 있다.
- 형의 재정의: 어떤 오브젝트에 다른 기능을 가진 인터페이스를 AOP로 합성하는 것
· 인터페이스를 구현하지 않는 클래스에 AOP를 하는 경우에는 디폴트의 JDK Dynamic Proxy가 아닌 CGLib Proxy를 사용한다.
- CGLib 패키지는 java bytecode를 조작할 수 있다. 컴파일된 class 앞뒤에 byte 코드를 삽입하는 bytecode instrumnet 기술을
사용하여 AOP를 구현한다. AspectJ도 이와 같은 방법으로 AOP를 구현한다.
- 인터페이스가 없으면 JDK Proxy는 이용할 수 없다.
TODO: JDK Dynamic Proxy vs CGLib Proxy
출처
스프링4 입문 - 하세가와 유이치
'스프링' 카테고리의 다른 글
스프링에서 트랜잭션을 처리하는 방법: @Transactional (0) | 2022.02.04 |
---|---|
스프링 세션 (Spring Session)이란? spring-session-jdbc 사용하기 (0) | 2021.11.26 |
스프링에서 버전을 일관성있게 다루는 방법: BOM (0) | 2021.10.26 |
[Spring Boot] 스프링 부트 그레이들 플러그인(Gradle Plugin) (0) | 2021.09.03 |
[F-lab] 4주차 정리_자바 (0) | 2021.09.03 |
댓글