SpringBoot AOP
의존성 소개
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
코드 구현
공용 필드 및 열거형 클래스:
private LocalDateTime createTime;
private LocalDateTime updateTime;
private Long createUser;
private Long updateUser;
/**
* 데이터베이스 연산 유형
*/
public enum OperationType {
/**
* 업데이트 작업
*/
UPDATE,
/**
* 삽입 연산
*/
INSERT
}
사용자 정의 어노테이션
사용자 지정 어노테이션 @AutoFill
/**
* 함수 필드 자동 채우기가 필요한 메서드를 식별하는 사용자 정의 어노테이션입니다.
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {
//데이터베이스 작업 유형: UPDATE, INSERT
OperationType values();
}
AOP
/**
* 공용 필드 필드 채우기를 구현하기 위한 사용자 정의 슬라이싱
*/
@Aspect
@Component
@Slf4j
public class AutoFillAspect {
/**
*
* @Pointcut진입점을 나타내는 어노테이션에는 여러 가지 유형이 있으며, 가장 일반적으로 사용되는 두 가지 유형은 실행 표현식과@annotation
* execution(* com.sky.mapper.*.*(..)) 는 com.sky.mapper패키지 아래의 모든 클래스의 모든 메서드
* @annotation(com.sky.annotation.AutoFill) 는 com.sky.annotion패키지 아래 어노테이션 자동 채우기
*/
@Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
public void autoFillPointCut(){}
/**
* 사전 어노테이션, 어노테이션의 공개 필드 할당
* 조인포인트에서 히트 메서드에 대한 정보를 얻고 이 정보를 사용하여 몇 가지 추가 비즈니스 작업을 수행할 수 있습니다;
* @Before("autoFillPointCut()") 액세스 포인트가 autoFillPointCut()의 진입점임을 나타냅니다.
*/
@Before("autoFillPointCut()")
public void autoFill(JoinPoint joinPoint){
log.info("공개 필드 자동 채우기 시작...");
//현재 인터셉트된 메서드에 대한 데이터베이스 연산 유형을 가져옵니다.
MethodSignature signature=(MethodSignature) joinPoint.getSignature();//객체 메서드 서명
AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);//메서드에 대한 어노테이션 객체를 가져옵니다.
OperationType values = autoFill.values();//데이터베이스 연산 객체 가져오기
//현재 인터셉트된 메서드의 매개변수 - 엔티티 객체를 가져옵니다.
Object[] args = joinPoint.getArgs();
if(args==null||args.length==0) {return;}
Object entity = args[0];
//할당을 위한 데이터 준비
LocalDateTime localDateTime = LocalDateTime.now();
Long currentId = BaseContext.getCurrentId();
//현재 작업 유형에 따라 해당 어트리뷰트가 리플렉션에 의해 할당됩니다.
if(values==OperationType.INSERT){
try {
Method setCreateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
Method setCreateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
setCreateTime.invoke(entity,localDateTime);
setCreateUser.invoke(entity,currentId);
setUpdateTime.invoke(entity,localDateTime);
setUpdateUser.invoke(entity,currentId);
} catch (Exception e) {
e.printStackTrace();
}
}else if(values==OperationType.UPDATE){
try {
Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
setUpdateTime.invoke(entity,localDateTime);
setUpdateUser.invoke(entity,currentId);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
핵심 주석 및 클래스
- 현재 클래스가 패싯 클래스임을 나타내는 @Aspect 는 클래스에서 사용됩니다.
- 메서드에 사용되는 @Before 주석으로 표시된 전달 알림은 컷인 메서드 실행 실행에서 실행됩니다.
- After는 메서드에 사용되는 이후 알림으로, @After로 주석이 달린 메서드가 컷인 메서드가 실행된 후에 실행됩니다.
- AfterRetrunning 주석이 표시된 메서드에 사용되는 반환 알림은 컷인 메서드의 결과 후에 실행됩니다.
- 메서드에 사용되는 예외 알림, @AfterThrowing. @AfterThrowing으로 주석이 달린 메서드는 컷인 메서드에서 예외가 발생한 후 실행되며, 일반적으로 예외 정보를 의도적으로 가져오는 데 사용됩니다.
- 랩 어라운드 알림인 @Aroud는 컷인 메서드가 실행되기 전후에 메서드를 실행하는 데 @Aroud 어노테이션이 사용되는 메서드에 사용됩니다.
- 메서드에 주석이 달린 진입점인 @Pointcut은 진입점을 정의하는 데 사용되며, 진입점은 어떤 연결 지점이 처음 잘랐는지 참조하는 것입니다. 포인트컷 주석은 표현식의 진입점이 가장 일반적으로 사용되는 두 가지, 실행 표현식과 주석이 있음을 나타냅니다;
- 실행: 메서드의 실행을 일치시키는 데 사용되는 연결 지점입니다.
- @annotation: 지정된 어노테이션을 가진 현재 실행 중인 메서드와 일치시키는 데 사용됩니다.
- 조인트포인트, 조인포인트, 조인포인트는 AOP 컷아웃으로 잘라낸 위치입니다. 조인포인트에서 히트 메서드에 대한 정보를 얻고 이 정보를 사용하여 몇 가지 추가 비즈니스 작업을 수행할 수 있습니다;
엔트리 포인트에 레이블을 지정하는 일반적인 방법
execution
표현 방법: 액세스 수정자 반환 값 패키지 이름. 패키지 이름... 클래스 이름. 메서드
//1. 모든 com.fanfuadd로 시작하는 메서드는 패키지와 그 하위 패키지 아래의 모든 클래스에 반환값과 매개변수를 무제한으로 사용할 수 있습니다;
@Pointcut("execution(* com.fanfu..*.*.add*(..))")
//2. 모든 com.fanfu패키지와 하위 패키지 아래의 모든 클래스에서 add로 시작하고 반환값이 무제한인 매개변수 유형이 String인 메서드;
@Pointcut("execution(* com.fanfu..*.*.add*(String))")
//3. 는 com.fanfu패키지 아래의 모든 클래스, 모든 메서드, 모든 매개변수;
@Pointcut("execution(* com.fanfu..*.*.*(String))")
- 실행()은 표현식의 본문입니다;
- 첫 번째 *는 반환 값 유형이 임의적임을 나타냅니다. 즉, 반환 값 유형에 제한이 없음을 의미합니다;
- 패키지 뒤의 *는 현재 패키지를 나타내며, 연속된 두 개의 . 는 현재 패키지와 그 하위 패키지를 나타내며, 매개변수를 나타냅니다;
- 마지막 *. * 는 모든 클래스, 모든 메서드, 모든 매개변수와 일치한다는 의미입니다;
어노테이션
주석 구문: @annotation(사용자 지정 주석)
// @AutoFill어노테이션 메서드
@Pointcut("@annotation(com.sky.annotation.AutoFill)")





