์ค๋์ Spring AOP์ ๋ํด ์ ๋ฆฌํด๋ณผ๋ ค๊ณ ํ๋ค.
ํ๋ก์ ํธ๋ฅผ ํ๋ค ๋ณด๋ฉด ํต์ฌ ๋ก์ง ๋ง๊ณ ๋ ๋ก๊น , ๊ถํ ์ฒดํฌ, ์์ธ ์ฒ๋ฆฌ ๊ฐ์ ๋ถ๊ฐ์ ์ธ ๊ธฐ๋ฅ์ ๋ฃ์ด์ผ ํ ๋๊ฐ ๋ง๋ค. ๊ทธ๋ฐ๋ฐ ์ด๋ฐ ์ฝ๋๋ค์ด ์ฌ๊ธฐ์ ๊ธฐ ์์ฌ๋ฒ๋ฆฌ๋ฉด ๋์ค์ ๊ด๋ฆฌํ๊ธฐ๊ฐ ๋๋ฌด ํ๋ค์ด์ง๋ค.
๊ทธ๋์ โ์ด๋ฐ ๊ณตํต์ ์ธ ์์ ๋ค์ ๊น๋ํ๊ฒ ๋ฐ๋ก ๊ด๋ฆฌํ ์ ์์๊น?โ ๋ผ๋ ๊ณ ๋ฏผ์์ Spring AOP๋ฅผ ๊ณต๋ถํ๊ฒ ๋์๊ณ , ์ด๋ฒ์ ์ ๋ฆฌํ ๋ด์ฉ์ ๋ฐํ์ผ๋ก ์ค์ ๋ด ํ๋ก์ ํธ์๋ ์ ์ฉํด๋ณด๋ ค๊ณ ํ๋ค.
AOP ๋ ํ๋ก๊ทธ๋จ ์ ๋ฐ์ ๊ฑธ์ณ ๊ณตํต์ ์ผ๋ก ์ฌ์ฉ๋๋ ๊ธฐ๋ฅ์ ๋ชจ๋ํํ์ฌ ์ฝ๋์ ๋ณต์ก๋๋ฅผ ๊ฐ์ ์ํค๊ณ , ์ ์ง๋ณด์๋ฅผ ์ฝ๊ฒ ๋ง๋๋ ๊ฒ์ ๋ชฉํ๋ก ํ๋ค.
AOP ์ ํ์์ฑ์ ์ดํดํ๋๋ฐ ๊ฐ์ฅ ๊ธฐ์ด๊ฐ ๋๋ ๊ฐ๋
์ ๊ด์ฌ์ฌ์ ๋ถ๋ฆฌ(Separation of Concerns) ์ด๋ค.
์๋ก ๋ค๋ฅธ ๊ด์ฌ์ฌ(Concerns)๊ฐ ํ ์ฝ๋์ ์์ฌ ์๋ค๋ฉด, ํ๋์ ๊ธฐ๋ฅ์ ์์ ํ ๊ฒฝ์ฐ, ์๋์น ์์ ๋ค๋ฅธ ๊ธฐ๋ฅ์ ์ํฅ์ ๋ฏธ์น ์ ์๋ค.
๋ฐ๋ผ์ AOP๋ ํต์ฌ ๊ด์ฌ์ฌ(Core Concern) ์ ํก๋จ ๊ด์ฌ์ฌ(Cross-cutting Concern) ๋ฅผ ๋๋์ด์ ๊ด๋ฆฌ๋ฅผ ํ๋ค.

ํต์ฌ ๊ด์ฌ์ฌ(Core Concern), ํก๋จ ๊ด์ฌ์ฌ(Cross-cutting Concern)... ์์งํ ์ด๋ ๊ฒ ๋งํ๋ฉด ์ฐ๋ฆฌ ๊ฐ๋ฐ์๋ค์ "๋ญ ์๋ฆฌ์ผ?" ๋ผ๋ ๋ง์ด ๋์ฌ ์๋ ์๋ค.
์ฝ๋๋ก ํ๋ฒ ์ดํดํด๋ณด์! ๐
ํ์๊ฐ์ ์ ํ๋ ๊ฐ๋จํ ์ฝ๋๋ฅผ ๊ฐ์ ธ์๋ดค๋ค. ์ฌ๊ธฐ๊น์ง๋ ๋ฌธ์ ๊ฐ ์๋ค.
@Transactional
public Member signUp(String name, String email) {
// ํต์ฌ ๋ก์ง: ํ์ ์ ๋ณด ์ ์ฅ
Member member = new Member(name, email);
return memberRepository.save(member);
}
ํต์ฌ ๋ก์ง๋ง ๊น๋ํ๊ฒ ์์ด์ ๋ณด๊ธฐ๋ ์ข๊ณ , ์ดํดํ๊ธฐ๋ ์ฝ๋ค. โจ
ํ์ง๋ง ์ ๋ ์ฌ์ฅ๋์ด "๊ฑฐ๊ธฐ ์ ์ ! ๋ฉ์๋๊ฐ ์คํ๋๋ ์๊ฐ ์ธก์ ํด๋ด!" ์ด๋ ๊ฒ ์๊ตฌ๋ฅผ ํ๋ฉด ์ฐ๋ฆฌ๋ ์ด๋ ๊ฒ ์ธก์ ์ ํด์ผ ํ๋ค.
@Transactional
public Member signUp(String name, String email) {
long start = System.currentTimeMillis(); // ์์ ์๊ฐ ์ธก์
// ํต์ฌ ๋ก์ง: ํ์ ์ ๋ณด ์ ์ฅ
Member member = new Member(name, email);
Member savedMember = memberRepository.save(member);
long end = System.currentTimeMillis(); // ๋ ์๊ฐ ์ธก์
System.out.println("signUp ๋ฉ์๋ ์คํ ์๊ฐ: " + (end - start) + "ms");
return savedMember;
}
์... ์์งํ ์ฌ๊ธฐ๊น์ง๋ ๊ด์ฐฎ๋ค. ์ฝ๋๊ฐ ์ข ์ง์ ๋ถํด์ก์ง๋ง ํ ๋งํ๋ค.
ํ์ง๋ง ์ ๋ ์ฌ์ฅ๋์ด "์๋ ํ์๊ฐ์ ๋ง๊ณ ํํด, ์์ , ํ์ ์กฐํ๋ ๋ค ์ธก์ ํด๋ด! ์ ๊ทธ๋ฆฌ๊ณ ์ฃผ๋ฌธ, ์ฃผ๋ฌธ ์ทจ์, ๋ฐฐ์ก, ๊ฒฐ์ ๋!" ๋ผ๊ณ ํ๋ฉด...
@Transactional
public void withdrawMember(Long memberId) {
long start = System.currentTimeMillis();
// ํต์ฌ ๋ก์ง
memberRepository.deleteById(memberId);
long end = System.currentTimeMillis();
System.out.println("withdrawMember ์คํ ์๊ฐ: " + (end - start) + "ms");
}
@Transactional
public void updateMember(Long memberId, String name) {
long start = System.currentTimeMillis();
// ํต์ฌ ๋ก์ง
Member member = memberRepository.findById(memberId);
member.updateName(name);
long end = System.currentTimeMillis();
System.out.println("updateMember ์คํ ์๊ฐ: " + (end - start) + "ms");
}
@Transactional
public Order createOrder(Long memberId, Long productId) {
long start = System.currentTimeMillis();
// ํต์ฌ ๋ก์ง
Order order = new Order(memberId, productId);
orderRepository.save(order);
long end = System.currentTimeMillis();
System.out.println("createOrder ์คํ ์๊ฐ: " + (end - start) + "ms");
}
@Transactional
public void cancelOrder(Long orderId) {
long start = System.currentTimeMillis();
// ํต์ฌ ๋ก์ง
Order order = orderRepository.findById(orderId);
order.cancel();
long end = System.currentTimeMillis();
System.out.println("cancelOrder ์คํ ์๊ฐ: " + (end - start) + "ms");
}
์์ด ์ํ๋ค... ๐ญ ๊ทธ๋ฆฌ๊ณ ์ด๊ฑด ์๊ฐ ์ธก์ ๋ง ์ถ๊ฐํ ๊ฑด๋ฐ, ๋ง์ฝ ์ฌ๊ธฐ์ ๋ก๊น , ๋ณด์ ์ฒดํฌ, ํธ๋์ญ์ ์ฒ๋ฆฌ๊น์ง ์ถ๊ฐํ๋ผ๊ณ ํ๋ฉด?
์ด๋ ๊ฒ ๋ชจ๋ ๋ฉ์๋์ ๋๊ฐ์ ์ฝ๋๋ฅผ ๋ณต์ฌ-๋ถ์ฌ๋ฃ๊ธฐ ํ๋ค ๋ณด๋ฉด:
๋ฐ๋ก ์ด๋ด ๋ AOP(Aspect-Oriented Programming, ๊ด์ ์งํฅ ํ๋ก๊ทธ๋๋ฐ)๊ฐ ํ์ํ๋ค!
AOP๋ฅผ ์ฌ์ฉํ๋ฉด ์ด๋ ๊ฒ ๋ฐ๋๋ค:
// ํต์ฌ ๋ก์ง๋ง ๊น๋ํ๊ฒ!
@Transactional
public Member signUp(String name, String email) {
Member member = new Member(name, email);
return memberRepository.save(member);
}
@Transactional
public void withdrawMember(Long memberId) {
memberRepository.deleteById(memberId);
}
@Transactional
public Order createOrder(Long memberId, Long productId) {
Order order = new Order(memberId, productId);
return orderRepository.save(order);
}
์๊ฐ ์ธก์ ๋ก์ง์ ๋ฑ ํ ๊ณณ์๋ง!
@Aspect
@Component
public class ExecutionTimeAspect {
@Around("execution(* com.example.service..*(..))")
public Object measureExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
Object result = joinPoint.proceed(); // ์ค์ ๋ฉ์๋ ์คํ
long end = System.currentTimeMillis();
String methodName = joinPoint.getSignature().getName();
System.out.println(methodName + " ์คํ ์๊ฐ: " + (end - start) + "ms");
return result;
}
}
AOP๋ ํก๋จ ๊ด์ฌ์ฌ๋ฅผ ํต์ฌ ๋ก์ง์์ ๋ถ๋ฆฌํด์ ํ ๊ณณ์์ ๊ด๋ฆฌํ ์ ์๊ฒ ํด์ค๋ค!
์ด์ ์ ๋ ์ฌ์ฅ๋์ด "๋ก๊น ๋ ์ถ๊ฐํด!" ๋ผ๊ณ ํด๋ ๋นํฉํ์ง ์์๋ ๋๋ค. ๐
๋ง ๊ทธ๋๋ก Target, ์ฆ, ๋ถ๊ฐ ๊ธฐ๋ฅ์ ๋ถ์ฌํ ๋์์ ์๋ฏธํ๋ค.
์๋ฅผ ๋ค์ด ์๊ฐ ์ธก์ ๊ธฐ๋ฅ์ ์ ์ฉํ MemberService, OrderService ๊ฐ์ ํด๋์ค๋ค์ด ๋ฐ๋ก Target์ด๋ค.
// ์ด ํด๋์ค๊ฐ ๋ฐ๋ก Target!
@Service
public class MemberService {
public Member signUp(String name, String email) {
// ๋น์ฆ๋์ค ๋ก์ง
}
}
ํ๊น์๊ฒ ์ ๊ณตํ ๋ถ๊ฐ๊ธฐ๋ฅ์ ๋ด์ ๋ชจ๋์ ์๋ฏธํ๋ค.
์ฝ๊ฒ ๋งํด์ "๋ฌด์จ ๊ธฐ๋ฅ? ์ด๋ ์์ ์?"๋ฅผ ์ ์ํ๋ค. ์๊ฐ ์ธก์ ์ฝ๋, ๋ก๊น ์ฝ๋๊ฐ ๋ฐ๋ก Advice๋ค.
Advice ์ข ๋ฅ:
@Before: ๋ฉ์๋ ์คํ ์ @After: ๋ฉ์๋ ์คํ ํ (์์ธ ๋ฐ์ ์ฌ๋ถ ์๊ด์์ด)@AfterReturning: ๋ฉ์๋ ์ ์ ์ข
๋ฃ ํ@AfterThrowing: ์์ธ ๋ฐ์ ์@Around: ๋ฉ์๋ ์คํ ์ ํ (๊ฐ์ฅ ๊ฐ๋ ฅํจ!)@Around("execution(* com.example.service..*(..))")
public Object measureExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
// ์ด ๋ฉ์๋ ์ ์ฒด๊ฐ Advice!
long start = System.currentTimeMillis();
Object result = joinPoint.proceed();
long end = System.currentTimeMillis();
return result;
}
Advice๊ฐ ์ ์ฉ๋ ์ ์๋ ์์น๋ฅผ ์๋ฏธํ๋ค.
๋ฉ์๋ ์คํ ์์ , ์์ฑ์ ํธ์ถ ์์ , ํ๋ ๊ฐ ์ ๊ทผ ์์ ๋ฑ์ด ๋ ์ ์๋ค. Spring AOP์์๋ ์ฃผ๋ก ๋ฉ์๋ ์คํ ์์ ์ ์ฌ์ฉํ๋ค.
public Object advice(ProceedingJoinPoint joinPoint) throws Throwable {
// joinPoint๋ฅผ ํตํด ์คํ๋๋ ๋ฉ์๋ ์ ๋ณด๋ฅผ ์ ์ ์์
String methodName = joinPoint.getSignature().getName(); // ๋ฉ์๋ ์ด๋ฆ
Object[] args = joinPoint.getArgs(); // ๋ฉ์๋ ํ๋ผ๋ฏธํฐ
return joinPoint.proceed(); // ์ค์ ๋ฉ์๋ ์คํ
}
Advice๋ฅผ ์ ์ฉํ Join Point๋ฅผ ์ ๋ณํ๋ ๊ธฐ๋ฅ์ด๋ค.
์ฝ๊ฒ ๋งํด์ "์ด๋ค ๋ฉ์๋์ ์ ์ฉํ ๊ฒ์ธ๊ฐ"๋ฅผ ์ ์ํ๋ ํํฐ ์ญํ ์ ํ๋ค.
// service ํจํค์ง์ ๋ชจ๋ ํด๋์ค, ๋ชจ๋ ๋ฉ์๋์ ์ ์ฉ
@Around("execution(* com.example.service..*(..))")
// MemberService์ ๋ชจ๋ ๋ฉ์๋์ ์ ์ฉ
@Around("execution(* com.example.service.MemberService.*(..))")
// signUp์ผ๋ก ์์ํ๋ ๋ชจ๋ ๋ฉ์๋์ ์ ์ฉ
@Around("execution(* com.example.service.*Service.signUp*(..))")
Pointcut ํํ์ ์์:
execution(* com.example.service..*(..)): service ํจํค์ง์ ํ์ ํจํค์ง์ ๋ชจ๋ ๋ฉ์๋execution(public * *(..)): ๋ชจ๋ public ๋ฉ์๋execution(* save*(..)): save๋ก ์์ํ๋ ๋ชจ๋ ๋ฉ์๋Advice + Pointcut์ ํฉ์น ๊ฒ์ด๋ค.
"์ด๋์(Pointcut), ๋ฌด์์(Advice) ์ ์ฉํ ๊ฒ์ธ๊ฐ"๋ฅผ ํ๋๋ก ๋ฌถ์ ๋ชจ๋์ด๋ค.
@Aspect // ์ด ํด๋์ค๊ฐ Aspect!
@Component
public class ExecutionTimeAspect {
// Pointcut + Advice = Aspect
@Around("execution(* com.example.service..*(..))") // Pointcut
public Object measureExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable { // Advice
long start = System.currentTimeMillis();
Object result = joinPoint.proceed();
long end = System.currentTimeMillis();
System.out.println(joinPoint.getSignature().getName() + " ์คํ ์๊ฐ: " + (end - start) + "ms");
return result;
}
}
Pointcut์ผ๋ก ์ง์ ํ Target์ Advice๋ฅผ ์ ์ฉํ๋ ๊ณผ์ ์ ์๋ฏธํ๋ค.
์ฝ๊ฒ ๋งํด์ ํต์ฌ ๋ก์ง์ ๋ถ๊ฐ ๊ธฐ๋ฅ์ "์ง ๋ฃ๋" ์์ ์ด๋ค.
Weaving ์์ :
.java โ .class ํ์ผ ์์ฑ ์ (AspectJ)// Spring AOP๋ ๋ฐํ์ ์๋น ์ฌ์ฉ
// ์ค์ ๋ก๋ ํ๋ก์ ๊ฐ์ฒด๊ฐ ๋ง๋ค์ด์ ธ์ ์คํ๋จ
MemberService memberService = new MemberService(); // ์๋ณธ ๊ฐ์ฒด
// ํ์ง๋ง ์ค์ ๋ก ์ฃผ์
๋๋ ๊ฒ์...
MemberService$$EnhancerBySpringCGLIB$$... // ํ๋ก์ ๊ฐ์ฒด!
Aspect = Pointcut + Advice
Target โ (Pointcut์ผ๋ก ์ ๋ณ) โ Advice ์ ์ฉ (Weaving)
โ
Join Point (์ค์ ์คํ ์ง์ )
ํ ์ค ์์ฝ:
Spring์์ AOP๋ ํ๋ก์ ๋ฐฉ์์ผ๋ก ๋์ํ๋ค.
ํ๋ก์ ํจํด์ด๋, ์ด๋ค ๊ฐ์ฒด(ํ๊ฒ)๋ฅผ ์ง์ ์ฐธ์กฐํ์ง ์๊ณ , ๋์ ๊ทธ ๊ฐ์ฒด๋ฅผ ๋์ ์ํํ๋ ํ๋ก์(proxy) ๊ฐ์ฒด๋ฅผ ํตํด ์ ๊ทผํ๋ ๋ฐฉ์์ ๋งํ๋ค.
๋จผ์ BeanPostProcessor์ ๋ํด ์์๋ณด์
์์ฑ๋ ๋น ๊ฐ์ฒด๋ฅผ ์คํ๋ง ์ปจํ ์ด๋์ ๋ฑ๋กํ๊ธฐ ์ ์ ์กฐ์ํ๋ ๊ฐ์ฒด

์ฝ๊ฒ ๋งํด์, ๋น์ด ์์ฑ๋๊ณ ๋์ "์ ๊น! ์ด ๋น์ ๊ทธ๋๋ก ๋ฑ๋กํ์ง ๋ง๊ณ ๋ด๊ฐ ์ ์ข ๋ด์ผ๊ฒ ์ด!" ํ๊ณ ์ค๊ฐ์ ๋ผ์ด๋๋ ์ญํ ์ ํ๋ค.
public interface BeanPostProcessor {
// Bean ์ด๊ธฐํ ์ ์ ์คํ
default Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
return bean;
}
// Bean ์ด๊ธฐํ ํ์ ์คํ โญ (AOP๋ ์ฌ๊ธฐ์ ํ๋ก์๋ก ๋ฐ๊ฟ!)
default Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
return bean;
}
}
ํ๋์ผ
1. ์์ฑ๋ ๋น ์ ๋ฌ
2. ๋น ๊ต์ฒด ๋์ ํ์ธ
3. ๋น ๊ต์ฒด ๋์์ด ๋ง๋ค๋ฉด ์ด๋ฅผ ์กฐ์ ๋๋ ๊ต์ฒด
4. ๊ต์ฒดํ๊ฑฐ๋ ์ ๋ฌ๋ฐ์ ๋น์ ๋ฐํํ๋ค.
5. ๋ฐํ๋ ๋น ๊ฐ์ฒด๋ฅผ ์ปจํ
์คํธ์ ๋ฑ๋ก
์คํ๋ง AOP์์ ์๋ฏธํ๋ ํ๋ก์(proxy)๋ ๋ถ๊ฐ๊ธฐ๋ฅ์ ์ถ๊ฐํ ๋ ์ฌ์ฉํ๋ ํจํด์ด๋ค.

๋น ๊ฐ์ฒด๋ฅผ ์์ฑํ ๋ค ๋น ํ์ฒ๋ฆฌ๊ธฐ์๊ฒ ์ ๋ฌํ๋ค.
๋น ํ์ฒ๋ฆฌ๊ธฐ๋ ์ด๋๋ฐ์ด์ ๋ฅผ ์น ํ์ด๋ณธ๋ค. ๊ทธ๋ฆฌ๊ณ ์ด๋๋ฐ์ด์ ๋ด์ ํฌ์ธํธ ์ปท(Pointcut)๋ฅผ ์ด์ฉํด ์ ๋ฌ๋ฐ์ ๋น์ด ํ๋ก์ ์ ์ฉ ๋์์ธ์ง ํ์ธํ๋ค.
์ ์ฉ ๋์์ธ์ง ํ์ธํ๋ฉด '์ ์๋ ๋ถ๊ฐ๊ธฐ๋ฅ์ ๋ถ์ฌํ ๋งํ ๋์์ด์ผ' ๋ผ๊ณ ํ๋จ๋๋ฉด ํ๋ก์ ์์ฑ๊ธฐ์ ์ ๋ฌํด์ค๋ค. ๊ทธ๋ฆฌ๊ณ ํ๋ก์ ์์ฑ ๋์ ๋น๋ค์ ๋์์ผ๋ก ํ๋ก์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ค.
ํ๋ก์๋ฅผ ์์ฑํ ๋น์ด๋ผ๋ฉด ํ๋ก์ ๊ฐ์ฒด๋ฅผ, ํ๋ก์๋ฅผ ์์ฑํ์ง ์์ ๋น์ด๋ผ๋ฉด ๊ทธ๋ฅ ๋น์ ๋ฐํํ๋ค.
๋น ํ์ฒ๋ฆฌ๊ธฐ์ ์ ๋ฌ๋ฐ์ ๊ฐ์ฒด๋ฅผ ์ปจํ ์ด๋ ๋น์ผ๋ก ๋ฑ๋กํ๋ค.
์คํ๋ง AOP๋ฅผ ๊ตฌํํ๋ ๋ฐฉ์์ ์ข ๋ค์ํ์ง๋ง ๋๋ ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉํ๊ณ ์ฑ
์์๋ ๊ถ์ฅํ๋ ๋ฐฉ์์ธ @AspectJ๋ฅผ ์ฌ์ฉํด๋ณด๊ฒ ๋ค.
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-aop'
}
AspectJ๋ ํฌ์ธํธ์ปท์ ํธ๋ฆฌํ๊ฒ ํํํ๊ธฐ ์ํ ํน๋ณํ ํํ์์ ์ ๊ณตํ๋ค.
execution
within
args
this
target
@target
@within
@annotation
@args
bean
ํฌ์ธํธ์ปท์ โAdvice๋ฅผ ์ด๋์ ์ ์ฉํ ์ง ์ง์ ํ๋ ๊ธฐ์คโ์ด๊ณ ,
execution,within,args,annotation๋ฑ ๋ค์ํ ๋ฐฉ์์ผ๋ก ๋์์ ์ ํํ ์ ์๋ค.
๊ฐ์ฅ ๋ง์ด ์ฌ์ฉํ๋ execution ์ ์ดํด๋ณด์
execution(์ ๊ทผ์ ์ด์? ๋ฐํํ์
ํจํค์ง.ํด๋์ค.๋ฉ์๋(ํ๋ผ๋ฏธํฐ) ์์ธ?)
? ํ์๋ ์๋ต ๊ฐ๋ฅ* ๋ ๋ชจ๋ ๊ฐ์ ์๋ฏธ.. ๋ 0๊ฐ ์ด์์ ์๋ฏธ// 1. ๋ชจ๋ public ๋ฉ์๋
execution(public * *(..))
// 2. ๋ฐํ ํ์
์ด void์ธ ๋ชจ๋ ๋ฉ์๋
execution(void *(..))
// 3. ๋ฉ์๋ ์ด๋ฆ์ด set์ผ๋ก ์์ํ๋ ๋ชจ๋ ๋ฉ์๋
execution(* set*(..))
// 4. service ํจํค์ง์ ๋ชจ๋ ๋ฉ์๋
execution(* com.example.service.*.*(..))
// 5. service ํจํค์ง์ ํ์ ํจํค์ง์ ๋ชจ๋ ๋ฉ์๋
execution(* com.example.service..*.*(..))
// 6. MemberService ํด๋์ค์ ๋ชจ๋ ๋ฉ์๋
execution(* com.example.service.MemberService.*(..))
// 7. ์ ํํ int minus(int, int) ๋ฉ์๋๋ง
// ๋ฐํ ํ์
์ int ์ด๊ณ , ๋ ๊ฐ์ int ํ์
ํ๋ฆฌ๋ฏธํฐ๋ฅผ ์ ๋ฌ๋ฐ๋ minus๋ผ๋ ์ด๋ฆ์ ๋ฉ์๋
execution(int minus(int, int))
// ๋ฐํ ํ์
๊ณผ๋ ์๊ด ์๊ณ , ๋ ๊ฐ์ int ํ์
ํ๋ผ๋ฏธํฐ๋ฅผ ์ ๋ฌ๋ฐ๋ minus๋ผ๋ ์ด๋ฆ์ ๋ฉ์๋
execution(* minus(int, int)
// 8. ํ๋ผ๋ฏธํฐ๊ฐ String ํ๋์ธ ๋ชจ๋ ๋ฉ์๋
execution(* *(String))
// 9. ์ฒซ ๋ฒ์งธ ํ๋ผ๋ฏธํฐ๊ฐ String์ธ ๋ชจ๋ ๋ฉ์๋
execution(* *(String, ..))
// 10. Member ํ์
์ ๋ฐํํ๋ ๋ชจ๋ ๋ฉ์๋
execution(com.example.domain.Member *(..))
AspectJ ์ด๋๋ฐ์ด์ค
(1) After: ๋ฉ์๋๊ฐ ๋ฐํ๋๊ฑฐ๋ ์์ธ ์ํฉ์ด ๋ฐ์ํ ์ดํ์ ํธ์ถ
(2) AfterReturning: ๋ฉ์๋๊ฐ ๋ฐํ๋ ์ดํ์ ํธ์ถ
(3) AfterThrowing: ๋ฉ์๋๊ฐ ์์ธ ์ํฉ์ ๋ฐ์์ํจ ์ดํ์ ํธ์ถ
(4) Before: ๋ฉ์๋๊ฐ ํธ์ถ๋๊ธฐ ์ด์ ์ ํธ์ถ
(5) Around: ๋ฉ์๋์ ํธ์ถ ์ ๊ณผ ๋ฐํ๋๊ฑฐ๋ ์์ธ ์ํฉ ์ดํ์ ํธ์ถ
@AspectJ ์ ๋ํ
์ด์
์ ์ฌ์ฉํด ์ด๋๋ฐ์ด์ ๋ฅผ ์์ฑํ๋ฉด ์ด๋ฅผ ๋น์ผ๋ก ๋ฑ๋กํด์ผํ๋ค.
๊ฐ๋ฐ์๊ฐ ์ง์ ์ ์ํ ํด๋์ค๋ฅผ ์ธ์ ํ์ ์ผ๋ก ๋ฐ์ ๋๋ ํจํค์ง๋ช ๋ ์ถ๊ฐํด์ผํ๋ค.
@Aspect // ์ด๋๋ฐ์ด์ ์์ฑ
@Component // ๋น ๋ฑ๋ก
public class CartExecutionTimeAspect {
// ํฌ์ธํธ์ปท ์ค์
@Pointcut("execution(void putItemIntoCart(Long, cart.dto.AuthorizationInformation))")
public void pointcut() {}
// ์ด๋๋ฐ์ด์ค ์ ์ + ํฌ์ธํธ์ปท ์ค์
@Around("pointcut()")
public Object advice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
long start = System.currentTimeMillis(); // ์์ ์๊ฐ ์ฒดํฌ
Object result = proceedingJoinPoint.proceed(); // ํ๊น ๋ฉ์๋ ํธ์ถ
long end = System.currentTimeMillis(); // ๋๋๋ ์๊ฐ ์ฒดํฌ
System.out.printf("%s ๋ฉ์๋์ ์คํ ์๊ฐ: %d ๋ฐ๋ฆฌ ์ด%n",
proceedingJoinPoint.getSignature().getName(), (end - start)); // ์คํ์๊ฐ ์ถ๋ ฅ
return result; // ํ๊น ๋ฉ์๋์ ๊ฒฐ๊ณผ ๋ฐํ
}
}
@Configuration
@EnableAspectJAutoProxy
public class AopConfiguration {
}
putItemIntoCart ๋ฉ์๋์ ์คํ ์๊ฐ: 153 ๋ฐ๋ฆฌ ์ด
์ฐธ๊ณ :