AOP
AOP(Aspect-Oriented Programming, 관점 지향 프로그래밍)는 프로그래밍의 한 패러다임으로, 애플리케이션의 공통 관심 사항(Cross-Cutting Concerns)을 모듈화하는 방법이다. AOP를 통해 로깅, 트랜잭션 관리, 보안 등과 같은 공통 기능을 애플리케이션의 다른 부분에 영향을 주지 않고 분리하여 관리할 수 있다.
다시 말하여 보통 비즈니스 웹 애플리케이션이라면 사업에 핵심적인 핵심 비즈니스 로직이 있고, 애플리케이션 전체를 관통하는 부가 기능 로직이 있다. 이를 횡단 관심사(cross-cutting concerns)라고 한다. (로깅, 보안, 트랜젝션)
횡단 관심사의 코드를 핵심 비즈니스 로직의 코드와 분리하여, 코드의 간결성을 높이고 변경에 유연함과 무한한 확장이 가능하도록 하는 것이 AOP의 목적이다.
아래의 코드는 AOP를 적용하기 전의 순수 자바 코드이다. 비즈니스 로직인 total() 메서드에 실행 시간을 로그로 기록하는 부가 기능 로직이 섞여 존재한다.
// JAVA로 AOP 사용하기 전
package spring.aop;
import spring.aop.entity.Exam;
import spring.aop.entity.NewlecExam;
public class Program {
public static void main(String[] args) {
Exam exam = new NewlecExam(1, 1, 1, 1);
System.out.printf("total is %d\n", exam.total());
System.out.printf("avg is %f\n", exam.avg());
}
}
package spring.aop.entity;
public class NewlecExam implements Exam {
private int kor;
private int eng;
private int math;
private int com;
public NewlecExam() {
}
public NewlecExam(int kor, int eng, int math, int com) {
this.kor = kor;
this.eng = eng;
this.math = math;
this.com = com;
}
@Override
public int total() {
// 예전에는 성능을 확인하기 위해서 이렇게 메인기능에 보조기능의 코드를 넣어서 확인
long start = System.currentTimeMillis();
int result = kor+eng+math+com;
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
String message = (end - start) + "ms 시간이 걸렸습니다.";
System.out.println(message);
return result;
}
@Override
public float avg() {
float result = total() / 4.0f;
return result;
}
}
//출력
//204ms 시간이 걸렸습니다.
//total is 4
//210ms 시간이 걸렸습니다.
//total is 1.000000
그래서 total() 메서드 안에 존재하는 보조 기능의 코드를 따로 빼자는것이 AOP이다.
횡단 관심사(cross-cutting concerns)의 코드를 핵심 비즈니스 로직의 코드와 분리하면 아래와 같다.
// JAVA로 AOP 사용 후
package spring.aop.entity;
public class NewlecExam implements Exam {
private int kor;
private int eng;
private int math;
private int com;
public NewlecExam() {
}
public NewlecExam(int kor, int eng, int math, int com) {
this.kor = kor;
this.eng = eng;
this.math = math;
this.com = com;
}
@Override
public int total() {
int result = kor+eng+math+com;
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
return result;
}
@Override
public float avg() {
float result = total() / 4.0f;
return result;
}
}
package spring.aop;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import spring.aop.entity.Exam;
import spring.aop.entity.NewlecExam;
public class Program {
public static void main(String[] args) {
Exam exam = new NewlecExam(1, 1, 1, 1);
Exam proxy = (Exam) Proxy.newProxyInstance(NewlecExam.class.getClassLoader(),
new Class[] {Exam.class},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
long start = System.currentTimeMillis();
//메인 기능
Object result = method.invoke(exam, args);
long end = System.currentTimeMillis();
String message = (end - start) + "ms 시간이 걸렸습니다.";
System.out.println(message);
return result;
}
});
System.out.printf("total is %d\n", proxy.total());
System.out.printf("avg is %f\n", proxy.avg());
}
}
//출력
//211ms 시간이 걸렸습니다.
//total is 4
//205ms 시간이 걸렸습니다.
//avg is 1.000000
참고자료
'🖥️ Backend > Spring' 카테고리의 다른 글
[Spring] 17.Spring AOP(XML, BeforeAdvice) (0) | 2024.12.31 |
---|---|
[Spring] 16.Spring AOP(XML, AroundAdvice) (0) | 2024.12.31 |
[Spring] 14.@Configuration (0) | 2024.12.30 |
[Spring] 13.@Component (0) | 2024.12.30 |
[Spring] 12.@Autowired (0) | 2024.12.30 |