1. AOP(Aspect Oriented Programming)란?
- 관점 지향 프로그래밍, 횡단 관심사, cross-cutting-concerns
- 부가 기능(advice)을 동적으로 추가해주는 기술
- 메서드의 시작 또는 끝에 자동으로 코드(advice) 를 추가
2. 공통 코드의 분리
- 여러 메서드에 공통 코드를 추가해야 한다면?
public class AopMain {
public static void main(String[] args) throws Exception {
Class myClass = Class.forName("com.fastcampus.ch3.aop.MyClass");
Object o = myClass.newInstance();
MyAdvice myAdvice = new MyAdvice();
for(Method m : myClass.getDeclaredMethods()){
myAdvice.invoke(m, o, null);
}
}
}
class MyAdvice{
void invoke(Method m, Object obj, Object... args) throws Exception{
System.out.println("[before]{"); // 공통으로 들어갈 코드
m.invoke(obj, args); // aaa(), aaa2(), bbb() 호출
System.out.println("}[after]"); // 공통으로 들어갈 코드
}
}
class MyClass{
void aaa(){
System.out.println("aaa() is called.");
}
void aaa2(){
System.out.println("aaa2() is called.");
}
void bbb(){
System.out.println("bbb() is called.");
}
}
- aaa(), aaa2()만 뽑고싶다면?
class MyAdvice{
Pattern p = Pattern.compile("a.*"); // a로 시작하는 문자열
boolean matches(Method m){ // 지정된 메서드가 패턴과 일치하는지 알려줌
Matcher matcher = p.matcher(m.getName());
return matcher.matches();
}
void invoke(Method m, Object obj, Object... args) throws Exception{
if (matches(m))
System.out.println("[before]{"); // 공통으로 들어갈 코드
m.invoke(obj, args); // aaa(), aaa2(), bbb() 호출
if(matches(m))
System.out.println("}[after]"); // 공통으로 들어갈 코드
}
}
- 패턴을주고 실행하면...
- bbb()는 [before]와 [after]가 추가되지 않았다.
<!-- Spring AOP: @Transactional을 위한 AOP 지원 (Spring Boot에서는 기본적으로 포함됨) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
- @Transactional 애너테이션을 사용할 수 없을 때 추가 해줘야한다.
- @Transactional 애너테이션을 추가해준뒤...
class MyClass{
@Transactional
public void aaa(){
System.out.println("aaa() is called.");
}
void aaa2(){
System.out.println("aaa2() is called.");
}
void bbb(){
System.out.println("bbb() is called.");
}
}
- 검증을 해주면...
class MyAdvice{
Pattern p = Pattern.compile("a.*"); // a로 시작하는 문자열
boolean matches(Method m){ // 지정된 메서드가 패턴과 일치하는지 알려줌
Matcher matcher = p.matcher(m.getName());
return matcher.matches();
}
void invoke(Method m, Object obj, Object... args) throws Exception{
if (m.getAnnotation(Transactional.class) != null)
System.out.println("[before]{"); // 공통으로 들어갈 코드
m.invoke(obj, args); // aaa(), aaa2(), bbb() 호출
if(m.getAnnotation(Transactional.class)!=null)
System.out.println("}[after]"); // 공통으로 들어갈 코드
}
}
3. 코드를 자동으로 추가한다면?
- 시작(Before)과 끝(After), 둘다(Around)
4. AOP 관련 용어
5. Advice의 종류
- Advice의 설정은 XML과 애너테이션, 두 가지 방법으로 가능
6. pointcut expression
- advice가 추가될 메서드를 지정하기 위한 패턴
- execution(접근 제어자 반환타입 패키지명.클래스명.메서드명(매개변수 목록))
public class AopMain2 {
public static void main(String[] args) {
ApplicationContext ac = SpringApplication.run(Config.class);
MyMath mm = ac.getBean(MyMath.class);
mm.add(3, 5);
mm.add(1,2,3);
System.out.println("mm.multiply(3,5) = " + mm.multiply(3, 5));
}
}
@EnableAspectJAutoProxy
@ComponentScan
@Configuration
class Config {
}
@Component
@Aspect
class LoggingAdvice{
@Around("execution(* com.fastcampus.ch3.aop.MyMath.add*(..))")
public Object methodClassLog(ProceedingJoinPoint pjp) throws Throwable {
// target 의 메서드 시작 부분에 추가될 코드
long start = System.currentTimeMillis();
System.out.println("<<[start]"+pjp.getSignature().getName()+ Arrays.toString(pjp.getArgs()));
Object result = pjp.proceed(); // target의 메서드를 호출
// target 의 메서드 끝 부분에 추가될 코드
System.out.println("result = " + result);
System.out.println("[end]>>"+(System.currentTimeMillis()-start)+"ms");
return result;
}
}
@Component("myMath")
class MyMath {
int add(int a, int b){
int result = a+b;
return result;
}
int add(int a, int b, int c){
int result = a+b+c;
return result;
}
int subtract(int a, int b){
int result = a-b;
return result;
}
int multiply(int a, int b){
int result = a*b;
return result;
}
}
- 실행이 안되었을때...
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
- 라이브러리를 전부 날리고 새 라이브러리를 추가하니 실행이 되었다.
'Spring DI, AOP' 카테고리의 다른 글
12. Spring으로 DB연결하기 - 패스트캠퍼스 백엔드 부트캠프 3기 (0) | 2025.02.26 |
---|---|
11. 데이터 모델링이란 - 패스트캠퍼스 백엔드 부트캠프 3기 (0) | 2025.02.25 |
9. 외부 설정 사용하기 - 패스트캠퍼스 백엔드 부트캠프 3기 (2) | 2025.02.24 |
8. @Import와 @Conditional - 패스트캠퍼스 백엔드 부트캠프 3기 (0) | 2025.02.24 |
7. 의존성 관리와 설정의 자동화(2) - 패스트캠퍼스 백엔드 부트캠프 3기 (0) | 2025.02.24 |