본문 바로가기
CLASS/SPRINGBOOT

#2-2 / AOP-springboot

by hingu 2024. 8. 13.

  👀 AOP - springboot  

  1. @SpringBootApplication - 실행시 AOP에 대한 어노테이션 설정
    @EnableAspectJAutoProxy 를  BootwebApplication.java에 추가
    BootwebApplication.java : springboot project 생성시 자동으로 생성된 파일임
    ( @SpringBootApplication 이게 미리 들어있음 )

  2. class(AOP를 작동시키는 class를 생성) - module
  3. @Pointcut 추상화 메소드를 생성
  4. 때에 따라 annotation 선택해서 사용
    - @Before : 해당 메소드가 실행되기 전에 실행되는 메소드 
    - @AfterReturning : 해당 메소드가 정상적으로 실행되고 난 후 반환되는 값에대해 실행되는 메소드
                                    기존 메소드에 필수로 return값이 있어야 함
    - @After : 해당 메소드가 실행된 후에 실행되는 메소드 
    - @Around : 해당 메소드가 실행 전,후 모두 실행되는 메소드 (예외처리 발생시에도 실행됨)

    ..등 몇개 더 있지만 주로 쓰는게 이 4개

 

✅ 어제 만든 coupon_list 예제에 해볼거임   https://dev-eunse.tistory.com/264

로그기록 => coupon_list에 접속시 로그를 기록함

 

- coupon_service.java  - 어제 만든 interface

//걍 참고만.. 요건 수정없음 그대로임 

//interface - repository + mapper.xml을 로드할 수 있는 interface를 생성
public interface coupon_service{
	public List<coupon_dao> getAllCoupon();
	
	public int insert_service(coupon_dao dao);
	
	public int delete_coupon(String cidx);
	
}

 

 

- logaspect.java   => 걍 class

AOP 추가코드를 작성 - couponService 인터페이스의 코드를 가져와서 추가할거임

@Around

package kr.co.sen;
//AOP 추가코드를 작성 - couponService 인터페이스의 코드를 가져와서 추가할거임

import org.aopalliance.intercept.Joinpoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.ILoggerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import lombok.extern.slf4j.Slf4j;

@Aspect //AOP선언
@Component //특정 클래스 타입을 선언 - 부품
@Slf4j  //로그 기록을 담당하는 어노테이션
public class logaspect {
	//slf4j : 추상 인터페이스(가상화되있는거 - 실제 인터페이스는 아님)
	Logger log = LoggerFactory.getLogger(this.getClass());
	
	@Pointcut("execution(* kr.co.sen.coupon_service.*(..))")
	private void doexecute() {} //AOP 추가 코드 부분
	
	@Around("doexecute()") //해당 interface의 class를 실행시 해당 AOP가 발동하게됨
	public Object logging(ProceedingJoinPoint joinpoint) throws Throwable {
		//aop의 기본은 object 형태!
		String methodname = joinpoint.getSignature().toShortString();
		Object obj = null;
		try {
			log.info(methodname + "해당 메소드 실행됨");
			obj = joinpoint.proceed();
		}finally {
			log.info(methodname + "해당 메소드 실행 종료");
		}
		
		return obj;
	}
}

@Component

특정 클래스 타입을 선언 - 부품

해당 프로세스가 돌면 단독으로 내부 메소드가 돌아감

 

@Pointcut => AOP - 표현식 결합

: @Pointcut("execution(* kr.co.sen..*(..))")
  (해당 패키지에 있는 모든 interface를 가져오는 경우 - 사실 이렇게 쓰진 않음, 개판오분전됨)
: @Pointcut("execution(* kr.co.sen.coupon_service.*(..))")   :    패키지명.그안의interface명
  이렇게 쓰면 해당 interface만 가져오는거(width 안의 모든 메소드)

 

@Around("pointcut 부분의 메소드명")

 

/list.do 접속시

 


AOP class는 controller와 관계없이 프로젝트 실행시 무조건 실행하는 Module!

 

- logaspect2.java   => 걍 class

@Before,@After

package kr.co.sen;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

import lombok.extern.slf4j.Slf4j;

@Aspect
@Component
@Slf4j
public class logaspect2 { 
	//AOP class는 controller와 관계없이 프로젝트 실행시 무조건 실행하는 Module!
	
	//AOP에서만 사용하는 변수
	private long start = 0;
	private long end = 0;
	
	//controller에 있는 class중에서 여러개의 method 중 하나를 실행 전 작동하는 메소드
	@Before("execution(* kr.co.sen.main_controller.*(..))")
	public void logBefore(JoinPoint joinpoint) {
		this.start = System.currentTimeMillis();
		log.info("AOP에서 실행된 log기록 Before값 : " + joinpoint.getSignature().getName());
	}
	
	//controller에 있는 class중에서 여러개의 method 중 하나를 실행 후 작동하는 메소드
	@After("execution(* kr.co.sen.main_controller.*(..))")
	public void logAfter(JoinPoint joinpoint2) {
		this.end = System.currentTimeMillis();
		long result = this.end-this.start;
		
		try {
			Thread.sleep(2000);
			System.out.println(result);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		log.info("AOP에서 실행후 log기록 After값 : " + joinpoint2.getSignature().getName());
	}
}

사실 controller로 aop핸들링을 잘 하지는 않음 - 주로 interface로 함

result는 캡쳐 못함ㅋ