생성자
public Ticket(long concertId, long ticketGradeId) {
this.concertId = concertId;
**this.ticketSerialNumber = UUID.randomUUID().toString();**
this.ticketGradeId = ticketGradeId;
}
피드백
- 이렇게 생성자 내부에서
ticketSerialNumber
를 생성해주도록 설정한 이유가 있을까요?
ticketSerialNumber
에는 별도의 비즈니스 로직은 넣지 않을 예정인가요? (추적이 편하도록 날짜_공연장_ID 형식으로 생성하기도 합니다)
ticketSerialNumber
를 생성하는 로직을 테스트할 수 있을까요?
생성자에서 작업 시 발생할 수 있는 문제점
- 테스트를 어렵게 만든다.
- 단일 책임 원칙 위반
- 클래스 상속 시 문제가 된다.
AOP 란?
-
트랜잭션 경계 설정처럼 비즈니스 로직을 수행하기 위해서 반드시 필요하지만 비즈니스 로직 코드와는
관심사가 다른 부가기능 역할을 하는 코드가 있다.
이 부가기능 코드는 프로그램 전반에 걸쳐 중복으로 등장하는데 이 코드들을 횡단 관심사라 한다.
-
횡단 관심사를 비즈니스 로직에서 분리하여 애스팩트라는 모듈화를 통해 AOP 라 한다.
-
AOP 로 부가기능을 비즈니스 로직에서 완전히 분리함으로써 핵심기능 설계에 OOP를 실현할 수 있다.
스프링에서 AOP 를 구현하는 방법
- 스프링은 프록시를 사용해 AOP를 구현한다.
프록시는 부가기능을 적용할 타깃 오브젝트로의 요청을 중간에서 대리하는 역할을 한다.
- 프록시 사용 목적에 따라 프록시 패턴, 데코레이터 패턴으로 구분한다.
- 프록시 패턴은 프록시가 타깃에 접근 제어
- 데코레이터 패턴은 프록시가 타깃에 부가기능 적용
- 스프링은 프록시 객체를 생성하는 방법에 두 가지 기술을 사용한다.
JDK dynamic proxy libraries
프록시가 타깃의 인터페이스를 구현하는 방식이다
CGLIB
프록시가 타깃을 상속하는 방식이다
프록시 기반 AOP 단점 : Self Invocation
- JDK dynamic proxy나 CGLIB 방식 모두 원리는 타깃 앞에서 타깃으로의 요청을 가로채서 부가기능을 적용한다.
- 프록시를 통한 타깃 메서드 호출이 아닌 타깃 오브젝트 내부에서 스스로 메서드를 호출하면 Proxy 가 부가기능을 적용할 방법이 없다.
- 프록시 기반 AOP 는 부가기능 적용이 타깃 메서드 호출시, 즉 런타임시에 적용되기 때문에 self invocation 을 방지할 방법이 없다.
- 런타임이 아닌 시점에 부가기능을 미리 적용하는 방법은 없을까?
Weaving
- weaving 이란 모듈화한 부가기능을 타깃에 적용하는 방법이다.
- weaving 에는 4가지 방법이 있다.
- Runtime Weaving
- Compile Time Weaving
- Load Time Weaving
- Post-Compile Weaving
잘 봤습니다. 좋은 글 감사합니다.