- 횡단 관심사이기 때문
- 스프링 AOP가 인터페이스 기반으로 작동하기 때문에 그 요건을 충족하기 위해서.
- CGLiB 라이브러리를 사용해야 할 경우에는 코드를 변경할 수 없는 서드파티 모듈 안에 final로 선언
- 굵게 표시된 부분은 스프링 프레임워크를 적용하고 활용하는 부분이다.
- 스프링 AOP가 인터페이스 기반이기 때문이다.
- Boy.java와 Girl.java에서 공통적으로 나타나는 횡단 관심사를 모두 삭제했지만, 결국 누군가는 횡단 관심사를 처리해야 한다. MyAspect.java가 횡단 관심사를 처리하게 된다.
- 객체의 생성과 의존성 주입을 스프링 프레임워크에 위임하기 위해서다.
- 물론 스프링 프레임워크는 객체 생성뿐 아니라, 객체의 생명주기 전반에 걸쳐 빈의 생성에서 소멸까지 관리한다.
- boy와 girl 빈은 AOP 적용 대상이기에 등록할 필요가 있고, myAspect 빈은 AOP의 Aspect이기에 등록할 필요가 있다.
<aop:aspectj-autoproxy />는 뭘까?
- 6.2절에서 설명했던 프록시 패턴을 이용해 횡단 관심사를 핵심 관심사에 주입하는 것이다.
- 프록시 없이 호출
- 프록시 이용해 호출
- 메서드 뿐만 아니라 속성 등에서도
Aspect를 적용할 수 있기 때문
로직(code) 주입
횡단 관심사(cross-cutting concern)라고 한다.
- 자주 보는 의사코드 (볼드체: 공통적으로 나타나는 코드, 횡단 관심사)
- 밑줄: 핵심 관심사
- 코드 = 핵심 관심사 + 횡단 관심사

Boy, Girl, Start 클래스

스프링 AOP -> 👉로직(code) 주입, 들어갈 위치는?

// Boy.java
package org.AOP.aop001;
public class Boy {
public void runSomething(){
System.out.println("열쇠로 문을 열고 집에 들어간다.");
try{
System.out.println("컴퓨터로 게임을 한다.");
}catch(Exception ex){
if(ex.getMessage().equals("집에 불남")){
System.out.println("119에 신고한다.");
}
}finally {
System.out.println("소등하고 잔다.");
}
System.out.println("자물쇠를 잠그고 집을 나선다.");
}
}
package org.AOP.aop001;
public class Girl {
public void runSomething(){
System.out.println("열쇠로 문을 열고 집에 들어간다.");
try{
System.out.println("요리를 한다.");
}catch(Exception ex){
if(ex.getMessage().equals("집에 불남")){
System.out.println("119에 신고한다.");
}
}finally {
System.out.println("소등하고 잔다.");
}
System.out.println("자물쇠를 잠그고 집을 나선다.");
}
}
// Start.java
package org.AOP.aop001;
public class Start {
public static void main(String[] args) {
Boy romeo = new Boy();
Girl juliet = new Girl();
romeo.runSomething();
juliet.runSomething();
}
}




@Before("execution(public void org.AOP.aop002.Boy.runSomething())")
를 아래처럼 고쳐도 실행 가능하다.
@Before("execution(* runSomething())") // 대상 메서드 실행 전에 이 메서드를 실행하겠다는 의미
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<aop:aspectj-autoproxy />
<bean id="myAspect" class="org.AOP.aop002.MyAspect"/>
<bean id="boy" class="org.AOP.aop002.Boy"/>
<bean id="girl" class="org.AOP.aop002.Girl"/>
</beans>

runSomething() 메서드는 주고받는 내용을 감시하거나 조작할 수 있다.
💡- 스프링 AOP는 프록시를 사용, 그런데 호출하는 쪽(romeo.runSomething() 메서드 호출)에서나 호출 당하는 쪽(romeo 객체), 그 누구도 프록시가 존재하는지조차 모른다. 오직 스프링 프레임워크만 프록시의 존재를 안다.
버퍼, 캐시 서버 등도 존재 목적은 달라도, 모두 중간에서 가로채는 것이라는 동일한 일을 한다.
<aop:aspectj-autoproxy />는 스프링 프레임워크에게 AOP 프록시를 사용하라고 알려주는 지시자이다. 게다가 auto는 자동으로!
- 스프링 AOP는 인터페이스 기반이다.
- 스프링 AOP는 프록시(proxy)기반이다.
- 스프링 AOP는 런타임(runtime) 기반이다.
@Before가 있듯, @After도 있다. 프록시가 개입할 수 있는 시점은 무려 5개나 된다.


Pointcut 은 바로
* runSomething()
@Before("execution(* runSomething())")은 지금 선언하고 있는 메서드(public void before)를* runSomething()가 실행되기 전(@Before)에 실행하라는 의미
- Pointcut : 👉 횡단 관심사를 적용할 타깃 메서드를 선택하는 지시자(메서드 선택 필터)
- 타킷 클래스의 타깃 메서드 지정자
| public void aop002.Boy ~ | * runSomething() |
|---|---|
![]() ![]() | |
![]() | |
Pointcut은 JoinPoint의 부분 집합
스프링 AOP는 인터페이스를 기반으로 한다.
인터페이스란 추상 메서드의 집합
스프링 AOP는 메서드에만 적용 가능하다는 결론에 도달
Pointcut의 후보가 되는 모든 메서드들이 JoinPoint, 즉 Aspect 적용이 가능한 지점이 된다.
package org.AOP.aop002;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect // AOP에서 사용하겠다는 의미
public class MyAspect {
@Before("execution(* runSomething())") // 대상 메서드 실행 전에 이 메서드를 실행하겠다는 의미
👉 public void before(JoinPoint joinPoint){
// JoinPoint : @Before에서 선언된 메서드인 aop002.Boy.runSomething()을 의미한다.
System.out.println("얼굴 인식 확인: 문을 개방하라");
//System.out.println("열쇠로 문을 열고 집에 들어간다.");
}
}
- romeo.runSomething() 메서드를 호출한 상태
-> JoinPoint :romeo 객체의 runSomething() 메서드- juliet.runSomething() 메서드를 호출한 상태
-> JoinPoint:juliet 객체의 runSomething() 메서드
정리
- 광의의 JoinPoint란 Aspect 적용이 가능한 모든 지점
- 협의의 JoinPoint란 호출된 객체의 메서드이다.

- Aspect = Advice들 + Pointcut 들
When + Where + What (언제, 어디에, 무엇을)
- Advisor = 한 개의 Advice + 한 개의 Pointcut
| 변경 전 | 변경 후 |
|---|---|
![]() | ![]() |
MyAspect 변경

aop004.xml 추가



package org.AOP.aop006;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class MyAspect {
@Pointcut("execution(* runSomething())")
private void iampc(){
// 여긴 무엇을 작성해도 의미가 없어요
}
@Before("iampc()")
public void before(JoinPoint joinPoint){
System.out.println("얼굴 인식 확인: 문을 개방하라");
}
@After("iampc()")
public void lockDoor(JoinPoint joinPoint){
System.out.println("주인님 나갔다: 어이 문 잠가!");
}
}

- 서비스 추상화란?
- 어댑터 패턴을 적용해 같은 일을 하는 다수의 기술을 공통의 인터페이스로 제어할 수 있게 한 것
- 서비스 추상화를 해주면서 그것도 일관성 있는 방식을 제공 -> PSA(일관성 있는 서비스 추상화)