[38일차] JoinPoint, AOP애너테이션

유태형·2022년 6월 21일
0

코드스테이츠

목록 보기
38/77

오늘의 목표

  1. JoinPoint
  2. AOP 애너테이션
  3. AOP 코드



내용

JoinPoint

AOP는 어떤 어드바이스를 적용시킬 것인지도 중요하지만 어느 위치에 적용할 것인지도 매우 중요합니다. 생성자, 필드 값 접근, static 메서드, 일반 메서드 등에서 실행가능 하며, AOP를 수행하는 메서드는 JoinPoint(@AroundProceedingJoinPoint)를 인자로 받게 됩니다.

조인 포인트는 AOP를 적용할 수 있는(어드바이스가 적용될 수 있는) 지점을 의미합니다.

스프링에서 AOP를 적용하는 방법은 2가지가 있습니다. 첫번째로 AspectJ를 사용하는 경우 모든 조인포인트에서 어드바이스를 적용시킬 수 있습니다. 반면에 두번째로 프록시를 사용하는 AOP인 경우 메서드 실행으로 제한됩니다.



JoinPoint 인터페이스

추상 메서드설명
JoinPoint.getArgs()JoinPoint에 전달된 인자를 배열로 반환합니다.
JoinPoint.getThis()AOP 프록시 객체를 반환합니다.
JoinPoint.getTarget()AOP가 적용된 대상 객체를 반환합니다.
JoinPoint.getSignature()조인되는 메서드의 시그니처(반환타입,메서드명,매개변수) 정보가 저장된 시그니처 객체를 반환합니다.
JoinPoint.toString()조인되는 메서드의 대한 설명을 출력합니다.
ProceedingJoinPoint.proceed()다음 어드바이스나 타겟을 호출합니다.



AOP 애너테이션

Spring에서 AOP는 Ioc를 보완하여 강력한 솔루션을 제공합니다.



@AspectJ 지원

@AspectJ는 에너테이션이 있는 일반 자바 클래스로 관점을 선언하는 스타일을 의미합니다.

  • @AspectJ는 AspectJ 5 버전 릴리스부터 도입되었습니다.
  • AOP 런타임은 순수한 스프링 AOP이며, AspectJ 컴파일러나 위버에 의존하지 않습니다.

@AspectJ 지원을 활성화 하기 위해선 @EnableAspectJAutoProxy 에너테이션을 @Configuration에너테이션이 있는 클래스에 추가합니다.

@Configuration
@EnableAspectJAutoProxy
public class AppConfig{

}

애너테이션이 아닌 XML기반 구성을 @AspectJ지원을 활성화 할 수 있습니다.

<aop:aspectj-autoproxy/>


@AspectJ 선언

@AspectJ 지원이 활성화되면 @AspectJ 관점이 있는 클래스로 애플리케이션 컨텍스트에 정의된 모든 빈이 Spring에서 자동으로 감지되고 SpringAOP를 구성하는데 사용됩니다.

<bean id="myAspect" class="start.aop.MyAspect">
</bean>
@Aspect
public class MyAspect{

}

포인트컷과 어드바이스, 어스팩트는 추상적인 개념으로 스프링 내에서 무엇을 의미하는지 파악하는 것이 중요하다고 생각합니다.

  • 어스팩트 : 어드바이스(메서드)들이 모여있고 @Aspect에너테이션이 있는 일반 클래스
  • 포인트컷 : 핵심 기능에서 어드바이스가 실행되는 위치(전,후,성공,실패,공통,..)
  • 어드바이스 : 어스팩트 내에 존재하는 부가기능을 정의하는 메서드



AOP 코드

스프링에서 AOP는 어떤 형태로 존재하고 사용되는지 알아보도록 하겠습니다.
AspectJ는 외부라이브러리로 사용하기 전에 gradle에서 import 하여야 사용할 수 있습니다.

build.gradle의 dependency에 추가

implementation 'org.springframework.boot:spring-boot-starter-aop'
implementation 'org.springframework.boot:spring-boot-starter-test'
CompileOnly 'org.projectlombok:lombok'
AnnotationProcessor 'org.projectlombok:lombok'

testCompileOnly 'org.projectlombok:lombok'
testAnnotationProcessor 'org.projectlombok:lombok'

스프링 컨테이너에 등록할 빈 객체에는 @Slf4j애너테이션이 추가적으로 필요합니다.

@Slf4j
//@Service
//@Controller
@Repository
public class BeanObject{

}

AspectJ로 테스트를 진행하기 위해선 테스트를 수행할 설정 정보 클래스에 @SpringBootTest에너테이션을, 테스트를 수행할 메서드엔 @Test에너테이션이 필요합니다.

@Slf4j
@SpringBootTest
public class 설정정보클래스{

	@Test
    void 테스트메서드(){
    
    }
}

Junit을 사용하여 실행합니다.

Aspect를 만들기 위해선 @Slf4j 애너테이션과 @Aspect애너테이션이 필요합니다.

@Slf4j
@Aspect
public class 어스팩트{
	@Around("AspectJ표현식") //포인트컷
    public Object 어드바이스(ProceedingJoinPoint joinPoint) throws Throwable{
    	log.info("",joinPoint.getSignature());
        return joinPoint.proceed();
    }
}

@Around는 포이트컷으로 대상의 어느 시점에 적용할지 지정합니다.
어스팩트 클래스내에 어드바이스 메서드로 어떤 부가적인 기능을 수행할지 정의합니다.

@Pointcut 애너테이션을 활용하여 어드바이스에서 포인트컷을 분리할 수도, 두 포인트 컷을 합칠 수도 있습니다

@Slf4j
@Aspect
public class 어스펙트{
	@Pointcut("AspectJ표현식")
    private void first(){}
    
    @Pointcut("AspectJ표현식")
    private void second(){}
    
    @Around("first() && second()")
    public Object 어드바이스(ProceedingJoinPoint joinPoint) throws Throwable{
    	log.info("",joinPoint.getSignature());
        return joinPoint.proceed();
    }
}

@Around에너테이션은 @Before, @AfterReturning, @AfterThrowing, @After을 모두 포함할 수 있습니다.

@Around("AspectJ표현식")
public Object 어드바이스(ProceedingJoinPoint joinPoint) throws Throwable{
	try{
    	//@Befpre
    	Object result = joinPoint.proceed();
        //@AfterReturning
    }catch(Exception e){
    	//@AfterThrowing
    }finally{
    	//@After
    }
}



후기

AOP는 어렵게 생각하면 어렵고 쉽게 생각하면 쉬운것인 것 같네요, 특히 프록시와 AspectJ부분이 깊게 파고들면 그만큼 난이도가 많이 어려워지는것 같습니다. 지금 달달 외우기 보단 스프링에 좀더 익숙해지고 아는것이 많아지면 다시 익히는것이 좋을 것 같습니다.




GitHub

https://github.com/ds02168/CodeStates_Spring/tree/main/section2-week4

profile
오늘도 내일도 화이팅!

0개의 댓글