반응형
스프링 AOP 특징
- 프록시 기반의 AOP 구현체
- 스프링 빈에만 AOP를 적용할 수 있다.
- 모든 AOP 기능을 제공하는 것이 목적이 아니라, 스프링 IoC와 연동하여 엔터프라이즈 애플리케이션에서 가장 흔한 문제(중복코드, 프록시 클래스를 만드는 비용과 수고, 객체들 간 관계 복잡 등등)에 대한 해결책을 제공하는 것이 목적.
프록시 패턴
(기존 코드 변경 없이) 접근 제어 또는 부가 기능 추가
프록시 패턴을 이용하여 기존 코드를 건드리지 않고 성능을 측정해보겠다.
@Component
public class AppRunner implements ApplicationRunner {
@Autowired
EventService eventService; //interface가 있다면 interface타입으로 받는게 가장 좋다. 구현체로 받지말고.
@Override
public void run(ApplicationArguments args) throws Exception {
eventService.createEvent();
eventService.publishEvent();
eventService.deleteEvent();
}
}
public interface EventService {
void createEvent();
void publishEvent();
void deleteEvent();
}
@Service
public class SimpleEventService implements EventService{
@Override
public void createEvent() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("create an Event");
}
@Override
public void publishEvent() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("publish an Event");
}
@Override
public void deleteEvent(){
System.out.println("Delete an Event");
}
}
Real Subject 클래스에 아래 코드들을 추가해주면 된다.
@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(System.currentTimeMillis() - begin);//시작시간을 뺀 시간을 출력해주면 된다.
}
@Override
public void publishEvent() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("publish an Event");
}
}
하지만, 기존 코드들을 건들이지 않고 성능을 측정하고 싶다.
Proxy패턴을 이용해본다. 새로운 클래스들을 만들어주고 메소드들 실행전과 후에 코드들을 넣어준다.
@Primary //@Service 애노테이션이 여러개 있을경우 이 빈을 우선으로 사용.
@Service
public class ProxySimpleEventService implements EventService{
@Autowired
SimpleEventService simpleEventService;//이번만은 interface형식으로 말고, 우리가 변경하고자 하는 구현체를 주입받는다.
@Override
public void createEvent() {
long begin = System.currentTimeMillis();
simpleEventService.createEvent();
System.out.println(System.currentTimeMillis() - begin);
}
@Override
public void publishEvent() {
long begin = System.currentTimeMillis();
simpleEventService.publishEvent();
System.out.println(System.currentTimeMillis() - begin);
}
@Override
public void deleteEvent() {
simpleEventService.deleteEvent();
}
}
문제점
- 매번 프록시 클래스를 작성해야 하는가? (클래스를 만드는 비용과 수고)
- 여러 클래스 여러 메소드에 적용하려면..?
- 프록시 클래스에도 생기는 중복 코드
그래서 등장한 것이 스프링 AOP
- 스프링 IoC 컨테이너가 제공하는 기반 시설과 Dynamic 프록시를 사용하여 *여러 복잡한 문제 해결. *중복코드, 객체간 관계 복잡함 등
- 동적 프록시 : 동적으로 프록시 객체 생성하는 방법 (동적 이란? Runtime,즉 애플리케이션이 동작하는 중에 동적으로 어떤 객체를 Runtime에 만든다.
- 자바가 제공하는 방법은 인터페이스 기반 프록시 생성
- CGlib은 클래스 기반 프록시도 지원
- 스프링 IoC: 기존 빈을 대체하는 동적 프록시 빈을 만들어 등록 시켜준다.
- 클라이언트 코드 변경 없음.
- AbstractAutoProxyCreator implements BeanPostProcessor
반응형