AOP (Aspect Oriented Programming)
관점 지향 프로그래밍
똑같은 코드가 여러 곳에 흩어져 있을 경우 수정할 때 여러 번 바꿔줘야 한다. 👉 공통적인 코드를 한 곳에 모아놓는다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class A {
method a() {
AAAA
안녕하세요.
BBBB
}
method b() {
AAAA
반갑습니다.
BBBB
}
}
class B {
method c() {
AAAA
안녕히가세요.
BBBB
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class A {
method a() {
안녕하세요.
}
method b() {
반갑습니다.
}
}
class B {
method c() {
안녕히가세요.
}
}
class AAAABBBB {
method aaaabbbb(JoinPoint point) {
AAAA
point.execute()
BBBB
}
}
AOP 구현 방법
- 컴파일
- 바이트코드 조작
- 프록시 패턴
컴파일
A.java –(AOP)–> A.class
컴파일할 때 AOP 적용
java 파일에는 반복되는 코드가 없지만 컴파일한 class 파일에는 있는 것처럼 해준다.
AspectJ가 제공
바이트코드 조작
A.java -> A.class –(AOP)–> 메모리
- 클래스를 로딩할 때 AOP 적용
class 파일에는 반복되는 코드가 없지만 A라는 클래스를 사용할 때 클래스 로더가 읽어와서 메모리에 올릴 때 있는 것처럼 해준다.
- 클로스 로더에다가 특별한 옵션을 붙여서 바이트 코드를 조작한다.
- AspectJ가 제공
프록시 패턴
- 스프링 AOP가 사용하는 방법
- 기존의 코드를 건들이지 않고 바꿀 수 있는 방법이기 때문에 클라이언트에 영향을 적게 준다.
구현 방법
- 인터페이스 생성
- 인터페이스를 구현하는 클래스 생성
- 인터페이스를 구현할 때 위의 클래스를 사용하여 앞뒤에 코드를 추가하는 클래스 생성 👉 프록시
사용 방법
인터페이스를 사용할 때 프록시 인스턴스를 대신 준다.
프록시 구현 예
1
2
3
public interface Payment {
void pay(int amount);
}
1
2
3
4
5
6
public class Cash implements Payment {
@Override
public void pay(int amount) {
System.out.prinln(amount + "현금결제");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
public class CreditCard implements Payment {
Payment cash = new Cash();
@Override
public void pay(int amount) {
if (amount > 100) {
System.out.println(amount + "신용카드");
} else {
cash.pay(amount);
}
}
}
프록시 사용 예
1
2
3
4
5
6
7
8
9
10
11
public class Store {
Payment payment;
public Store(Payment payment){
this.payment = payment;
}
public void buySomething(int amount){
payment.pay(amount);
}
}
1
2
3
4
5
6
7
8
9
public class StoreTest {
@Test
public void testPay() {
Payment creditCard = new CreditCard();
Store store = new Store(creditCard);
store.buySomething(100);
}
}
Store 클래스에서 Payment를 사용할 때 CreditCard를 주면 cash를 사용할지 말지 판단하는 코드가 실행된다.
원래는 Cash가 Bean으로 등록되는데 CreditCard라는 프록시가 대신 등록되어 사용된다.
CreditCard에서 Cash의 코드를 건드리지 않고 Cash 메소드 앞 뒤에 코드가 추가하여 사용할 수 있다.
@Transactional
- 코드 앞뒤로 트랜잭션 처리를 해주는 코드가 추가되는 Annotation (프록시 패턴 사용)
- 해당 Annotation을 사용하면 Connection에 setAutocommit을 false로 하고 SQL 실행이 모두 끝난 다음 Commit을 하거나 Rollback 해주는 코드가 추가된다.