본문 바로가기

Spring/Spring

(SPRING) 스프링 AOP : 프록시 기반 AOP

스프링 AOP 특징 

  • 프록시 기반의 기반의 AOP 구현체 
  • 스프링 빈에만 AOP를 적용할 수 있다. 
  • 모든 AOP 기능을 제공하는 것이 목적이 아니라, 스프링 IoC와 연동하여 엔터프라이즈 애플리케이션에서 가장 흔한 문제에 대한 해결책을 제공하는 것이 목적.

프록시 패턴

왜 쓰는가?

(기존 코드 변경 없이) 접근 제어 또는 부가 기능 추가

프록시 패턴

 

Client

@Component
public class AppRunner implements ApplicationRunner {
    @Autowired
    EventService eventService ;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        eventService.publishEvent();
        eventService.createEvent();
    }
}

Subject

public interface EventService {

    void createEvent();

    void publishEvent();
}

RealSubject

@Service
public class SimpleEventService implements EventService{

    @Override
    public void createEvent() {
        long begin = System.currentTimeMillis();

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Create an event!");

        System.out.println("createEvent 실행시간: "+(System.currentTimeMillis()-begin));
    }

    @Override
    public void publishEvent() {
        long begin = System.currentTimeMillis();

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Published an event!");
        System.out.println("publishEvent 실행시간: "+(System.currentTimeMillis()-begin));
    }

    @Override
    public void deleteEvent() {
        System.out.println("Delete an event!");
    }
}

이때 RealSubject의 코드를 건드리지 않고 createEvent, publicEvent 메서드의 실행시간을 측정하는 Proxy를 생성해보자!

 

  • ProxySimpleEventService 프록시 클래스 생성
  • 리얼 서브젝트와 동일한 인터페이스를 구현한다.
  • 리얼 서브젝트를 참조
@Primary
@Service
public class ProxySimpleEventService implements EventService{

    @Autowired
    EventService simpleEventService;

    
//    SimpleEventService simpleEventService;
//    SimpleEventService simpleEventService;
//
//    ProxySimpleEventService(SimpleEventService simpleEventService) {
//        this.simpleEventService = simpleEventService;
//    }

    @Override
    public void createEvent() {
        long begin = System.currentTimeMillis();
        simpleEventService.createEvent();
        System.out.println("createEvent 실행시간: "+(System.currentTimeMillis()-begin));
    }

    @Override
    public void publishEvent() {
        long begin = System.currentTimeMillis();
        simpleEventService.publishEvent();
        System.out.println("createEvent 실행시간: "+(System.currentTimeMillis()-begin));
    }

    @Override
    public void deleteEvent() {
        simpleEventService.deleteEvent();
    }
}

리얼 서브젝트에 있는 실행시간 측정 내용을 Proxy 클래스로 위임

실행결과


문제점 발생

1. 중복된 코드 발생

2. Proxy클래스를 만드는데 cost가 든다.

 

그래서 등장한 것이 스프링 AOP 

  • 스프링 IoC 컨테이너가 제공하는 기반 시설과 Dynamic 프록시를 사용하여 여러 복잡한 문제 해결. 
  • 동적 프록시: 동적으로 프록시 객체 생성하는 방법 
  • 자바가 제공하는 방법은 인터페이스 기반 프록시 생성. 
  • CGlib은 클래스 기반 프록시도 지원. 
  • 스프링 IoC: 기존 빈을 대체하는 동적 프록시 빈을 만들어 등록시켜준다. 

클라이언트 코드 변경 없음. 

AbstractAutoProxyCreator implements BeanPostProcessor

 

SimpleEventServcie가 빈으로 등록될때 AbstractAutoProxyCreator라는 빈 포스트 프로세서로

해당 bean을 감싸는 proxy bean을 만들어서 해당 bean을 SimpleEventServcie대신에 등록한다.

 

 

https://jwdeveloper.tistory.com/47

 

(JAVA) 다이나믹 프록시

다이내믹 프록시란? 런타임 시점에(컴파일 시점이 아닌) 특정 인터페이스들을 구현하는 클래스 혹은 인스턴스를 만드는 기술 https://docs.oracle.com/javase/8/docs/technotes/guides/reflection/proxy.html Dyna..

jwdeveloper.tistory.com

 

 

코드 참고

https://github.com/mike6321/Spring/tree/master/Spring/AOP

 

mike6321/Spring

Contribute to mike6321/Spring development by creating an account on GitHub.

github.com