Programming/Spring Framework 주요 개념

스프링 AOP (스프링 핵심 기술 - 5)

흠냐아뤼 2020. 3. 5. 00:43
728x90

 

1. AOP (Aspect-Oriented Programming) 이란?

- OOP를 보완하는 수단으로, 흩어진 Aspect를 모듈화 할 수 있는 프로그래밍 기법

- 흩어진 관심사들을 하나로 모아서 Aspect로 모듈화하는 기법

 

 

2. 주요 개념

- Aspect : 모듈

- Target : 적용되는 대상 (Class A, B)

- Advice : 해야할 일

- Join Point : 합류 지점 (생성자 호출 전, 메소드를 호출하기 전, 필드에서 값을 가져갈 때...)

- Pointcut : 어디에 적용되어야 하는지

 

 

3. 구현체

- AspectJ (다양한 Join Point를 사용해야 할 때)

- 스프링 AOP

- 둘을 연동해서 사용 가능

 

 

3. 적용 방법

- 컴파일 타임 : 컴파일 할 때, 조작된 자바 바이트 코드를 생성 (AspectJ 컴파일러)

- 로드 타임 : 바이트 코드를 로드할 때 생성 (AspectJ 사용)

- 런타임 : A객체 빈을 만들 때, 이를 감싸는 proxy 빈을 만듬 (스프링 AOP 사용 - 합리적이고, 자주 쓰게될 방법)

 

 

4. 스프링AOP

- 프록시 기반의 AOP 구현체

- 스프링 빈에만 AOP를 적용할 수 있다

 

프록시 패턴

- 왜 프록시 패턴 사용? 기존 코드 변경 없이 접근 제어 또는 부가 기능 추가

- Proxy는 RealSubject를 참조하며 이 기능 + 추가적인 기능을 수행함.

- Client와 RealSubject 코드의 변경없이 기능 추가

- 매번 프록시 클래스 생성, 객체들 관계 복잡 등 문제 있음 따라서 스프링 AOP 등장

 

스프링AOP

- 스프링 IoC컨테이너가 제공하는 기반 시설과 Dynamic 프록시를 사용하여 복잡한 문제 해결

- 동적 프록시 (동적으로 프록시 객체를 생성)

- 스프링 IoC의 AbstractAutoProxyCreator(BeanPostConstruct를 상속)는 기존 빈을 대체하는 동적 프록시 빈을 만들 어 등록 시켜줌

 

 

5. @AOP

- 어노테이션 기반의 @AOP 

 

1. 의존성 추가

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

 

2. Aspect 정의

@Component
@Aspect
public class PerfAspect {

    // 어디에 적용할 것인가 (포인트 컷)
    @Around("@annotation(PerfLogging)")
    // 해야할 일 (어드바이스)
    public Object logPerf(ProceedingJoinPoint pjp) throws Throwable {
        // pjp 는 적용되는 부분으로 (메소드 그 자체)
        long begin = System.currentTimeMillis();
        Object retVal = pjp.proceed();
        System.out.println(System.currentTimeMillis() - begin);
        return retVal;
    }

    @Before("bean(simpleEventService)")
    public void printHello(){
        System.out.println("Hello~");
    }

}

 

3. 어노테이션 정의

/*
    이 어노테이션을 사용하면 성능을 측정해줍니다.
 */
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.CLASS)
public @interface PerfLogging {
}

 

 

참고)

// 인터페이스 타입인 경우 인터페이스로 주입 받는 것을 권장함

@Autowired
EventService eventService;

/*
실무에서 우려되는 부분은
인터페이스를 쓰지 않을 때 다음과 같은 복잡한 문제가 생길 수 있음

인터페이스를 기반으로 프록시 객체를 만들도록 설정하면
MyService -> DefaultMyService
MyService -> ProxyService
ProxyService 는 DefaultMyService 와 상속관계가 아니므로 불러올 수 없음

스프링 부트는 default로 클래스를 기반으로 프록시 객체를 만듬
MyService -> DefaultMyService -> ProxyService
*/
// 이렇게 같은 타입으로 지정하거나, 같은 클래스 이름으로 지정하면 해당 빈을 주입받을 수 있음

@Autowired
SimpleEventService simpleEventService;

@Autowired
EventService simpleEventService;

 

 

인프런 백기선님 '스프링 프레임워크 핵심 기술' 강의를 듣고 정리한 내용입니다.

 

728x90