본문 바로가기
개발/Spring

[Spring] 스프링 AOP (1)

by devhooney 2022. 7. 1.
728x90

스프링 코어 중 다른 하나인 DIxAOP 컨테이너의 AOP에 대해 알아보기

- DI 컨테이너란 오브젝트 사이에 밀접한 의존 관계를 가지지 않게 하고, 인터페이스에 의한 약한 결합을 쉽게 만들어 소프트웨어의 컴포넌트화를 촉진하며, 오브젝트의 생명 주기를 관리할 수 있게 하는 것

- DI 컨테이너만으로는 온전한 아키텍처를 개발할 수 없음

- AOP가 있으면 로깅이나 트랜잭션 등의 처리를 따로 관리할 수 있게 구현하는 기술

 

3.1 AOP란

- AOP란 업무 등 특정 책임이 있는 클래스 같이 본질적이지 않은 처리들을 밖으로 꺼내는 기술

 

3.1.1 AOP 용어

애스펙트(Aspect)

- 횡단 관심사의 동장과 그 횡단 관심사를 적용하는 소스 코드상의 포인트를 모은 것

 

어드바이스(Advice)

- 조인 포인트에서 실행되는 코드.

- 로그 출력이나 트랜잭션 관리 등의 코드.

 

조인 포인트(Join Point)

- 어드바이스가 실행하는 동작을 끼워 넣을 수 있는 때를 말함.

- 조인 포인트는 개발자가 고려해서 만들어 넣을 수 없는 AOP의 사양.

- 메소드가 호출될 때와 메소드가 원래 호출한 곳으로 돌아갈 때가 어드바이스를 끼워 넣을 수 있는 조인 포인트.

 

포인트컷(Pointcut)

- 조인포인트와 어드바이스의 중간에 있으면서 처리가 조인 포인트에 이르렀을 때 어드바이스를 호출할 지 선별함.

- 조인포인트의 상세한 스펙을 정의한 것.

3.1.2 스프링이 제공하는 어드바이스

- 스프링이 제공하는 어드바이스

어드바이스의 형태 설명
Before 조인트 앞에서 실행할 어드바이스
After 조인포인트 뒤에서 실행할 어드바이스
AfterReturning 조인포인트가 완전히 정상 종료한 다음 실행되는 어드바이스
Around 조인포인트 앞뒤에서 실행되는 어드바이스
AfterThrowing 조인포인트에서 예외가 발생했을 때 실행되는 어드바이스

 

스프링4 입문 그림3-2

 

3.1.3 프록시를 이용한 AOP

https://yadon079.github.io/2021/spring/spring-aop-core

- 프록시 기반의 AOP 구현체이다. 프록시 객체를 사용하는 이유는 접근 제어 및 부가 기능을 추가하기 위해서이다.

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

- 모든 AOP 기능을 제공하는 것이 목적이 아니라, 스프링 IoC와 연동하여 엔터프라이즈 애플리케이션에서 가장 흔한 문제(중복코드, 프록시 클래스 작성의 번거로움, 객체 간 관계 복잡도 증가 등등…)를 해결하기 위한 솔루션을 제공하는 것이 목적.

 

3.2 어노테이션을 이용한 AOP

- 스프링의 AOP를 사용하기 위한 방법은 3가지

1. Bean 정의 파일에 설정

2. JavaConfig에 작성

3. 어노테이션 작성

 

https://devhooney.tistory.com/9?category=1052447 

 

스프링 DI (1)

스프링 코어 중 하나인 DI에 대한 개요, 특징, 이용 방법 및 DI를 어떻게 이용할 것인가에 대한 설명 2.1 DI란 - DI는 '의존 관계의 주입'이다. - 오브젝트 사이의 의존 관계를 만드는 것. -> 오브젝트

devhooney.tistory.com

- 상단 게시물에서 작성한 Product로 예제를 재사용 함.

스프링4 입문 그림 3-8

- AOP의 적용 대상은 ProductDao의 findProduct 메소드

@Aspect
@Component
public class MyFirstAspect {
	@Before("execution(* findProduct(String))")
    public void before() {
    	// 메소드 시작 시 동작하는 어드바이스
        System.out.println("Hello Before");
    }
    
    @After("execution(* findProduct(String))") 
    public void after() {
    	// 메소드 종료 후 동작하는 어드바이스
       	System.out.println("Hello After");
    }
    
    @AfterReturning(value="execution(* findProduct(String))", returning="product")
    public void afterReturning(Product product) {
    	// 메소드 호출이 예외를 내보내지 않고 종료했을 때 동작하는 어드바이스
        System.out.println("Hello AfterReturning");
    }
    
    @Around("execution(* findProduct(String))")
    public Product around(ProceedingJointPoint pjp) throws Throwable {
    	// 메소드 호출 전후에 동작하는 어드바이스
        System.out.println("Hello Around Before");
        
        Product p = (Product)pjp.procced();
        System.out.println("Hello Around After");
        return p;
    }

	@AfterThrowing(value="execution(* findProduct(String))", throwing="ex")
    public void afterThroing(Throwable ex) {
    	// 메소드 호풀이 예외를 던졌을 때 동작하는 어드바이스
        System.out.println("Hello Throwing);
    }

}

- 클래스 선언 앞에 애스팩트임을 나타내는 @Aspect를 붙임

 

- 결과

Hello Before
Hello Around before
Hello After
Hello Around After
Hello AfterReturning
Product [name=공책, price=100]

 

3.2.1 포인트컷 기술 방법

- 어노테이션 괄호 안에 "execution(* findProduct(String))" 형식으로 기술

- execution 기본 구문

  • "메소드의 수식자(public 혹은 private)"나 "throws 예외"는 생략 가능
  • 메소드의 반환값형, 패키지와 클래스명, 인터페이스명에는 와일드카드 (*)를 이용 가능
  • "*"는 "."(패키지 구분 문자)와 일치하지 않으므로 복수 패키지와 일치시키려면 ".."를 사용
  • 메소드의 인수에 ".."를 기술하면 모든 인수와 일치시킬 수 있음
728x90

'개발 > Spring' 카테고리의 다른 글

[Spring] 스프링 시큐리티 (1)  (0) 2022.07.04
[Spring] 스프링 AOP (2)  (0) 2022.07.04
[Spring] 스프링 DI (2)  (0) 2022.06.29
[Spring] 스프링 DI (1)  (0) 2022.06.29
[Spring] @ResponseBody가 null만 가져올 때  (0) 2022.06.28