여러 객체에 공통으로 적용할수 있는 기능을 분리해서 재사용성을 높여주는 프로그래밍
❓ 이게 어떻게 재사용성을 높여줄까?
핵심 기능을 구현한 코드의 수정없이 공통기능을 적용할 수 있게 만든다.
+@ 프록시
모듈 단위 기능구현에서 핵심적인 기능의 실행은 위임하고, 부가적인 기능을 제공하는
객체를 프록시라 하겠다.
==> 데코레이터 패턴 객체에 가깝지만, 이해를 돕기위한 용어로 사용
+@ 데코레이터 패턴의 특징
데코레이터 패턴은 특정 개체의 기능을 정적으로 확장 (장식)하는 데 사용할 수 있으며, 디자인 타임에 일부 기초 작업이 수행되는 경우 동일한 클래스의 다른 인스턴스와 독립적으로 런타임에 일부 경우에 확장 할 수 있습니다. 이것은 원래 클래스를 래핑 하는 새로운 Decorator 클래스를 디자인함으로써 달성됩니다 .
위의 말의 뜻은 기초 작업이 수행되는 경우 독립적으로 다른 기능을 추가해서 원래 클래스를 wrapping(감싼다) 한다.
💨위의 말로 알 수 있는 데코레이터패턴의 장점은?
1) 기존 코드를 수정하지 않고도 데코레이터 패턴을 통해 행동을 확장시킬 수 있습니다.
2) 구성과 위임을 통해서 실행중에 새로운 행동을 추가할 수 있습니다.
=============================================================
핵심기능에 공통기능을 삽입하는 방법 3가지
컴파일 시점에 코드에 공통 기능을 삽입.
클래스 로딩 시점에 바이트 코드에 공통 기능을 삽입.
런타임시 프록시 객체를 생성해서 공통 기능을 삽입하는 방법.
이 중 스프링에서는 3번째와 2번째 방식을 일부 지원한다.
+@ 컴파일 시점, 클래스로딩 시점이란?
자바파일이 JAVAC 컴파일러를 거쳐 JVM이 해석할수있는 바이너리 클래스 코드로 변환되는 시점.
클래스 로딩시점 => 동적 로딩에 의해 JVM이 필요한 클래스를 런타임 데이터 영역(Runtime Data area) JVM의 메모리에 올리는 시점
프록시 기반 AOP
- 비지니스 로직 실행
1-1 공통 기능 실행
1-2 비지니스 핵심기능 실행
1-3 RETURN
1-4 공통기능 실행
1-5 RETURN
AOP 주요 용어
용어 | 의미 |
---|---|
Advice | 어느시점에 공통 기능을 핵심 로직에 적용할지를 정의한다. |
JoinPoint | Advice를 적용 가능한 지점을 의미한다. (메소드 호출) |
PointCut | Joinpoint의 부분 집합, 실제 적용되는 포인트를 말한다. |
Weaving | Advice를 핵심로직에 적용하는 것 |
Aspect | 여러 객체에 공통으로 적용되는 기능을 Aspect라한다. |
ADVICE의 종류
용어 | 의미 |
---|---|
Before Advice | 대상 객체의 메소드 호출 전에 공통기능실행 |
After Returning Advice | 대상 객체의 메서드가 exception 없이 실행된 이후 실행 |
After Throwing Advice | 대상객체의 메서드가 exception이 발생한 경우 실행 |
After Advice | exception 발생 여부와 관계없이 메서드 실행후, 공통기능 실행 |
Around Advice | 위의 모든상황을 아우를때 사용.(모든상황에서 사용) |
스프링 AOP 구현
💨 @Order 어노테이션을 @aspect가 붙은 프록시클래스에 지정하면 우선순위가 정해진다.
Order값 숫자가 작을수록 우선 순위가 높아지고, 우선 적용되어서 더 안 쪽에서 감싸지는 proxy가 되어서 타겟 Object의 코드와 붙어있는 Apspect가 된다.
즉, Aspect 설정에서 order값의 숫자가 클 수록 target객체에서 더 멀어지는 바깥 쪽의 Proxy로 결합된다.
CacheAspect:Cache에 추가[7]
RecCalculator.factorial([7]) 실행 시간: 3143800 ns
CacheAspect: Cache에서 구함 [7]
RecCalculator.factorial([7]) 실행 시간: 91000 ns
CacheAspect:Cache에 추가[5]
RecCalculator.factorial([5]) 실행 시간: 85400 ns
CacheAspect: Cache에서 구함 [5]
RecCalculator.factorial([5]) 실행 시간: 140100 ns
==================================================>
RecCalculator.factorial([7]) 실행 시간: 23300 ns
CacheAspect:Cache에 추가[7]
CacheAspect: Cache에서 구함 [7]
RecCalculator.factorial([5]) 실행 시간: 5200 ns
CacheAspect:Cache에 추가[5]
CacheAspect: Cache에서 구함 [5]
한쪽이 다른 한쪽을 감싼것 같은데 누가 감싸진걸까? 안쪽에 있는 프록시객체가 감싸진 것으로 숫자가 더 낮을것이다.
우선순위가 높을수록 숫자가 낮아지므로, 부가기능인 Exetime 숫자가 높을것이다.
중요도가 더 높은 cache는 숫자가 낮다