스프링 프레임워크 - 스프링 AOP, Null-Safety, 마무리
지난 강의 정리
ApplicationContext는 단순히 BeanFactory의 기능만 하는 것이 아니고 ResourceLoader, ApplicationEventPublisher,MessageSource, Environment 등 여러 기능들이 있습니다.
스프링 AOP
스프링 AOP - 개념 소개
Aspect-oriented Programming (AOP)은 OOP를 보완하는 수단으로 흩어진 Aspect를 모듈화 할 수 있는 프로그래밍 기법입니다.
흩어진 관심사(Crosscutting Concerns)
Concerns은 여러 클래스에서 비슷하게 쓰이는 코드
트랜잭션, 로깅 등…
AOP는 무엇일까?
해야할 일(관심사; 특정 기능)과 적용할 곳을 한 곳으로 모아서 모듈화(Aspect)를 하는 것입니다.
AOP 주요 개념
-
Advice: 해야할 일 - 언제 공통 관심 기능들을 핵심 로직에 적용할지 정의
-
Target: 적용이 되어야할 대상
-
Join Point: 합류 지점(끼어들 수 있는 곳)
-
Pointcut: 적용할 곳
-
Weaving: Advice를 핵심 로직 코드에 적용하는 것을 위빙
AOP 구현체
- AspectJ
- 스프링 AOP
AOP 적용 방법
- 컴파일
- 컴파일할 때(바이트 코드) 함께 적용을 하는 방법
- 로드 타임
- 클래스 A는 이미 컴파일이 되어있고 JVM에서 로드 될 때 Aspect가 같이 로드 되는 방법
- 런타임
- A라는 빈에 Aspect X를 적용해야 하는 것을 스프링이 알고 있고, A 타입의 프록시 빈을 만들어서 실제 A의 메서드를 호출하기 전에 Aspect X를 적용하고 A를 호출하는 방법
스프링 AOP - 프록시 기반 AOP
스프링 AOP 특징
- 프록시 기반의 AOP 구현체입니다.
- 스프링 빈에만 AOP를 적용할 수 있습니다.
- 모든 AOP 기능을 제공하는 것이 목적이 아닌, 스프링 IoC와 연동하여 엔터프라이즈 애플리케이션에서 가장 흔한 문제에 대한 해결책을 제공하는 것이 목적입니다.
프록시 패턴
프록시 패턴을 사용하는 이유
프록시 패턴은 기존 코드 변경 없이 어떤 객체에 대한 접근을 제어하는 용도 및 부가 기능을 추가하여 클라이언트에게 해당하는 객체를 제공하는 패턴입니다.
프록시 패턴의 문제점
- 결국 중복 코드가 생길 수 밖에 없고, 프록시 클래스를 만드는 비용이 들 수 있습니다.
- 같은 기능을 여러 클래스, 여러 메소드에 적용하려면 또 프록시를 만들고 중복된 작성할 수 밖에 없는 문제가 있습니다.
스프링 AOP
- 스프링 IoC 컨테이너가 제공하는 기반 시설과 dynamic 프록시를 사용하여 문제를 해결할 수 있습니다.
- 동적(Dynamic) 프록시: 동적으로 프록시를 만들어주는 방법
- 스프링 IoC: 기존 빈을 대체하는 동적 프록시 빈을 만들어 등록시켜 주는 역할을 합니다.
- 클라이언트의 코드 변경이 없습니다.
- AbstractAutoProxyCreator implements BeanPostProcessor
스프링 AOP: @AOP
애노테이션 기반의 스프링 @AOP
의존성 추가
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
Aspect 정의
@Component
@Aspect
public class TestAspect {
//@Arround("execution(* com.yoon..*.EventService.*(..))") // EventService 아래 모든 메서드 적용
@Arround("@annotation(PerfLogging)")
public Object logTest(ProceedingJoinPoint pjp) throws Throwable {
long begin = System.currentTimeMillis();
Object retVal = pjp.proceed();
System.out.println(System.currentTimeMills() - begin);
return retVal;
}
}
execution으로 클래스 범위를 정할 수 있으나 메서드 단위로 사용하기 어렵습니다.
@annotation 방식
특정 메서드에 추가할 때 annotation 방식을 사용합니다.
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.CLASS)
public @interface PerfLogging {
}
Aspect를 적용할 메서드에 @PerfLogging 애너테이션을 붙여줍니다.
bean으로 적용하는 방식
@Arround("bean(simpleEventService)")
어드바이스 정의
- @Before - 대상 Method가 실행되기 전에 호출
- @AfterReturning - 대상 Method가 정상적으로 실행된 이후 호출
- @AfterThrowing - 대상 Method가 예외를 발생시킨 경우 호출
- @After - 대상 Method가 정상적이건 예외건 상관없이 호출
- @Arround - 대상 Method에 대한 호출 자체를 가로챔, 위 4가지 경우 가능
Null-Safety
툴의 지원을 받아 컴파일 타임에 최대한 NullPointerException을 방지하기 위해 사용하는 애너테이션 입니다.
Null 관련 애너테이션
- @NonNull
- @Nullable
- @NonNullApi
- @NonNullFields
인텔리제이 사용시
Preferences -> Build,Excecution,Deployment -> Compiler -> Add runtime assertions for non-null ~ 체크 configure -> org.springframework.lang 패키지의 NonNull, Nullable 추가
마무리…
스프링 프레임워크의 핵심 기술에 대하여 간략하게 학습할 수 있었던 강의 였습니다. 스프링 IoC의 개념과 여러 기능들을 쭉 훑어 볼 수 있었습니다.