
@target, @within

- @target
- 실행 객체의 클래스에 주어진 타입의 애노테이션이 있는 조인 포인트
- 인스턴스의 모든 메서드를 조인 포인트로 적용한다.
- @within
- 주어진 애노테이션이 있는 타입 내 조인 포인트
- 해당 타입 내에 있는 메서드만 조인 포인트로 적용한다.
- @target 은 부모 클래스의 메서드까지 어드바이스를 다 적용하고, @within 은 자기 자신의 클래스에 정의된 메서드에만 어드바이스를 적용
- 주의
- args , @args , @target 같은 포인트컷 지시자가 있으면 스
프링은 모든 스프링 빈에 AOP를 적용하려고 시도한다
- 이렇게 모든 스프링 빈에 AOP 프록시를 적용하려고 하면 스프링이 내부에서 사용하는 빈 중에는 final로 지정된 빈들도 있기 때문에 오류가 발생
- 이러한 표현식은 최대한 프록시 적용 대상을 축소하는 표현식과 함께 사용해야 한다
예)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ClassAop {
}
@ClassAop
@Component
public class MemberServiceImpl implements MemberService {
@Override
public String hello(String param) {
return "ok";
}
public String internal(String param) {
return "ok";
}
}
@Slf4j
@Import({AtTargetAtWithinTest.Config.class})
@SpringBootTest
public class AtTargetAtWithinTest {
@Autowired
Child child;
@Test
void success() {
log.info("child Proxy={}", child.getClass());
child.childMethod();
child.parentMethod();
}
static class Config {
@Bean
public Parent parent() {
return new Parent();
}
@Bean
public Child child() {
return new Child();
}
@Bean
public AtTargetAtWithinAspect atTargetAtWithinAspect() {
return new AtTargetAtWithinAspect();
}
}
static class Parent {
public void parentMethod(){}
}
@ClassAop
static class Child extends Parent {
public void childMethod(){}
}
@Slf4j
@Aspect
static class AtTargetAtWithinAspect {
@Around("execution(* hello.aop..*(..)) && @target(hello.aop.member.annotation.ClassAop)")
public Object atTarget(ProceedingJoinPoint joinPoint) throws Throwable {
log.info("[@target] {}", joinPoint.getSignature());
return joinPoint.proceed();
}
@Around("execution(* hello.aop..*(..)) && @within(hello.aop.member.annotation.ClassAop)")
public Object atWithin(ProceedingJoinPoint joinPoint) throws Throwable {
log.info("[@within] {}", joinPoint.getSignature());
return joinPoint.proceed();
}
}
}
