분류 전체보기 1341

Ch12. 스프링 AOP(실전 예제) - 프록시 기술과 한계(JDK 동적 프록시)

타입 캐스팅 JDK 동적 프록시와 CGLIB를 사용해서 AOP 프록시를 만드는 방법에는 각각 장단점이 있다. JDK 동적 프록시는 인터페이스가 필수이고, 인터페이스를 기반으로 프록시를 생성한다. CGLIB는 구체 클래스를 기반으로 프록시를 생성한다 스프링이 프록시를 만들 때 제공하는 ProxyFactory에 proxyTargetClass 옵션에 따라 둘 중 하나를 선택해서 프록시를 만들 수 있다. proxyTargetClass=false JDK 동적 프록시를 사용해서 인터페이스 기반 프록시 생성 proxyTargetClass=true CGLIB를 사용해서 구체 클래스 기반 프록시 생성 참고로 옵션과 무관하게 인터페이스가 없으면 JDK 동적 프록시를 적용할 수 없으므로 CGLIB를 사용한다. JDK 동적 ..

Ch12. 스프링 AOP(실전 예제) - 프록시와 내부 호출(대안)

자기 자신 주입 내부 호출을 해결하는 가장 간단한 방법은 자기 자신을 의존관계 주입받는 것이다.(프록시를 의존관계 주입) @Slf4j @Component public class CallServiceV1 { private CallServiceV1 callServiceV1; @Autowired public void setCallServiceV1(CallServiceV1 callServiceV1){ log.info("callServiceV1 setter={}", callServiceV1.getClass()); this.callServiceV1 = callServiceV1; } /* @Autowired public CallServiceV1(CallServiceV1 callServiceV1){ //빈등록 전에 나..

Ch12. 스프링 AOP(실전 예제) - 프록시와 내부 호출(문제)

스프링은 프록시 방식의 AOP를 사용한다. 따라서 AOP를 적용하려면 항상 프록시를 통해서 대상 객체(Target)를 호출해야 한다. 이렇게 해야 프록시에서 먼저 어드바이스를 호출하고, 이후에 대상 객체를 호출한다. 만약 프록시를 거치지 않고 대상 객체를 직접 호출하게 되면 AOP가 적용되지 않고, 어드바이스도 호출되지 않는다 AOP를 적용하면 스프링은 대상 객체 대신에 프록시를 스프링 빈으로 등록한다. 따라서 스프링은 의존관계 주입 시에 항상 프록시 객체를 주입한다. 프록시 객체가 주입되기 때문에 대상 객체를 직접 호출하는 문제는 일반적으로 발생하지 않는다. 하지만 대상 객체의 내부에서 메서드 호출이 발생하면 프록시를 거치지 않고 대상 객체를 직접 호출하는 문제가 발생한다 CallServiceV0 @S..

Ch12. 스프링 AOP(실전 예제) - 재시도 AOP

Retry 어노테이션 작성 @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Retry { int value() default 3; } 기본 Value를 줄 수가 있다 RetryAspect 작성 @Slf4j @Aspect public class RetryAspect { @Around("@annotation(retry)") public Object doRetry(ProceedingJoinPoint joinPoint, Retry retry) throws Throwable {//파라미터로 전달 log.info("[retry] {} retry={}", joinPoint.getSignature(), retry); in..

Ch12. 스프링 AOP(실전 예제) - 예제 만들기 & 로그 출력 AOP

Repository(5번에 한 번씩 예외가 발생) @Repository public class ExamRepository { private static int seq = 0; /** * 5번에 1번 실패하는 요청 */ public String save(String itemId){ seq++; if(seq % 5 == 0){ //5번 한번 오류 throw new IllegalStateException("예외 발생"); } return "ok"; } } Service @Service @RequiredArgsConstructor public class ExamService { private final ExamRepository examRepository; public void request(String ite..

Ch11. 스프링 AOP(포인트컷) - this, target

this : 스프링 빈 객체(스프링 AOP 프록시)를 대상으로 하는 조인 포인트 target : Target 객체(스프링 AOP 프록시가 가리키는 실제 대상)를 대상으로 하는 조인 포인트 this , target 은 다음과 같이 적용 타입 하나를 정확하게 지정해야 한다. this(hello.aop.member.MemberService) target(hello.aop.member.MemberService) * 같은 패턴을 사용할 수 없다. 부모 타입을 허용한다 차이점 : 스프링에서 AOP를 적용하면 실제 target 객체 대신에 프록시 객체가 스프링 빈으로 등록된다. this는 스프링 빈으로 등록되어 있는 프록시 객체를 대상으로 포인트 컷을 매칭 한다. target 은 실제 target 객체를 대상으로 포..

Ch11. 스프링 AOP(포인트컷) - 매개변수 전달

포인트 컷 표현식을 사용해서 어드바이스에 매개변수를 전달할 수 있다. this, target, args,@target, @within, @annotation, @args @Slf4j @Import(ParameterTest.ParameterAspect.class) @SpringBootTest public class ParameterTest { @Autowired MemberService memberService; @Test public void success(){ log.info("memberService Proxy={}", memberService.getClass()); memberService.hello("helloA"); } @Slf4j @Aspect static class ParameterAspec..

Ch11. 스프링 AOP(포인트컷) - @annotation, @args, bean

@annotation @annotation : 메서드가 주어진 애노테이션을 가지고 있는 조인 포인트를 매칭 @annotation(hello.aop.member.annotation.MethodAop) Test @Slf4j @Import(AtAnnotationTest.AtAnnotationAspect.class) @SpringBootTest public class AtAnnotationTest { @Autowired MemberService memberService; @Test public void success() { log.info("memberService Proxy ={}", memberService.getClass()); memberService.hello("helloA"); } @Slf4j @As..

Ch11. 스프링 AOP(포인트컷) - @target, @within

@target : 실행 객체의 클래스에 주어진 타입의 애노테이션이 있는 조인 포인트 @within : 주어진 애노테이션이 있는 타입 내 조인 포인트 @target , @within 은 다음과 같이 타입에 있는 애노테이션으로 AOP 적용 여부를 판단한다. @target(hello.aop.member.annotation.ClassAop) @within(hello.aop.member.annotation.ClassAop) @target vs @within @target 은 인스턴스의 모든 메서드를 조인 포인트로 적용한다. @within 은 해당 타입 내에 있는 메서드만 조인 포인트로 적용한다 Test @Slf4j @Import({AtTargetAtWithinTest.Config.class}) @SpringBoo..

Ch11. 스프링 AOP(포인트컷) - within, args

Within within 지시자는 특정 타입 내의 조인 포인트에 대한 매칭을 제한한다. 쉽게 이야기해서 해당 타입이 매칭 되면 그 안의 메서드(조인 포인트)들이 자동으로 매칭 된다. 문법은 단순한데 execution에서 타입 부분만 사용한다고 보면 된다 Test @Test public void withinExact(){ pointcut.setExpression("within(hello.aop.member.MemberServiceImpl)"); assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue(); } @Test public void withinStar(){ pointcut.setExpression("within(hello...