framework/spring AOP(관점지ν–₯)

[springAOP] 8. μ–΄λ…Έν…Œμ΄μ…˜κΈ°λ°˜μ˜ AOP λ§Œλ“€μ–΄ μ‚¬μš©ν•˜κΈ° | Advisor 클래슀

jeri 2024. 7. 31. 16:18
λ°˜μ‘ν˜•

01. πŸ’–Spring Bean Configuration File

[07-5_aopAnnotation.xml]
  • bean , context , aop κΈ°λŠ₯κΉŒμ§€ λͺ¨λ‘ μ΄μš©ν•˜λ―€λ‘œ 3개 λ‹€ μ„€μ •ν•΄μ„œ 생성해야함!!
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="<http://www.springframework.org/schema/beans>"
	xmlns:xsi="<http://www.w3.org/2001/XMLSchema-instance>"
	xmlns:aop="<http://www.springframework.org/schema/aop>"
	xmlns:context="<http://www.springframework.org/schema/context>"
	xsi:schemaLocation="<http://www.springframework.org/schema/beans> <http://www.springframework.org/schema/beans/spring-beans.xsd>
		<http://www.springframework.org/schema/context> <http://www.springframework.org/schema/context/spring-context.xsd>
		<http://www.springframework.org/schema/aop> <http://www.springframework.org/schema/aop/spring-aop.xsd>">

  		<!-- 이제 ν΄λž˜μŠ€μ— @ μ–΄λ…Έν…Œμ΄μ…˜μ„ μ‚¬μš©ν•΄μ„œ μŠ€ν”„λ§ 빈으둜 등둝 κ°€λŠ₯해짐! -->
		<context:component-scan base-package="xyz.itwill07.aop"/>

		<!-- aspectj-autoproxy : Spring Annotationλ₯Ό μ΄μš©ν•˜μ—¬ AOP κΈ°λŠ₯을 μ œκ³΅ν•˜κΈ° μœ„ν•œ μ—˜λ¦¬λ¨ΌνŠΈ -->
		<!-- => AOP κ΄€λ ¨ Annotation을 μ‚¬μš©ν•˜μ—¬ ν•΅μ‹¬κ΄€μ‹¬μ½”λ“œμ— νš‘λ‹¨κ΄€μ‹¬μ½”λ“œλ₯Ό μ‚½μž…ν•˜μ—¬ μ‹€ν–‰λ˜λ„λ‘ μ„€μ • -->
		<aop:aspectj-autoproxy/>
</beans>

 

 

02. [핡심관심λͺ¨λ“ˆ]

AopAnnotationBean.java
package xyz.itwill07.aop;

import org.springframework.stereotype.Component;

//Component μ–΄λ…Έν…Œμ΄μ…˜μ— μ˜ν•΄ Spring Bean으둜 등둝됨
@Component
public class AopAnnotationBean {
	public void display1() {
		System.out.println("### AopAnnotationBean 클래슀의 display1() λ©”μ†Œλ“œ 호좜 ###");
	}
	public void display2() {
		System.out.println("### AopAnnotationBean 클래슀의 display2() λ©”μ†Œλ“œ 호좜 ###");
	}
	public void display3() {
		System.out.println("### AopAnnotationBean 클래슀의 display3() λ©”μ†Œλ“œ 호좜 ###");
		throw new RuntimeException(); //after-throwing μ–΄λ…Έν…Œμ΄μ…˜μ„ μ΄μš©ν•˜κΈ° μœ„ν•΄ μΈμœ„μ μ˜ˆμ™Έλ°œμƒ
	}
}

 

 

03. [νš‘λ‹¨κ΄€μ‹¬λͺ¨λ“ˆ] : Advisor클래슀

AopAnnotationAdvice.java
package xyz.itwill07.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

//Advisor 클래슀 : JoinPoint κΉŒμ§€ λͺ¨λ‘ μ§€μ •λœ 클래슀

@Component
//@Aspect : ν•΅μ‹¬κ΄€μ‹¬μ½”λ“œμ— νš‘λ‹¨κ΄€μ‹¬μ½”λ“œλ₯Ό μ‚½μž…ν•˜μ—¬ μ‹€ν–‰ν•˜κΈ° μœ„ν•œ κΈ°λŠ₯을 μ œκ³΅ν•˜λŠ” μ–΄λ…Έν…Œμ΄μ…˜
//=> Spring Bean Configuration File의 aspect μ—˜λ¦¬λ¨ΌνŠΈμ™€ μœ μ‚¬ν•œ κΈ°λŠ₯ 제곡
//=> Spring Bean Configuration File에 aspectj-autoproxy μ—˜λ¦¬λ¨ΌνŠΈ μΆ”κ°€ν•΄μ•Ό μ‚¬μš© κ°€λŠ₯
@Aspect
public class AopAnnotationAdvice {
	public static final Logger logger=LoggerFactory.getLogger(AopAnnotationBean.class);
    
    
    //1.
    //@Pointcut : νƒ€κ²Ÿλ©”μ†Œλ“œλ₯Ό μ§€μ •ν•˜κΈ° μœ„ν•œ μ–΄λ…Έν…Œμ΄μ…˜
	//=> λ©”μ†Œλ“œ ν˜ΈμΆœμ„ μ΄μš©ν•˜μ—¬ νƒ€κ²Ÿλ©”μ†Œλ“œλ₯Ό μ§€μ •ν•œ PointCut ν‘œν˜„μ‹μ„ μ œκ³΅ν•˜κΈ° μœ„ν•΄ μ‚¬μš©
	// => Spring Bean Configuration File의 pointcut μ—˜λ¦¬λ¨ΌνŠΈμ™€ μœ μ‚¬ν•œ κΈ°λŠ₯ 제곡
	//value 속성 : νƒ€κ²Ÿλ©”μ†Œλ“œλ₯Ό μ§€μ •ν•˜κΈ° μœ„ν•œ PointCut ν‘œν˜„μ‹μ„ μ†μ„±κ°’μœΌλ‘œ μ„€μ •
	// => λ‹€λ₯Έ 속성이 μ—†λŠ” 경우 μ†μ„±κ°’λ§Œ μ„€μ • κ°€λŠ₯
	@Pointcut("within(xyz.itwill07.aop.AopAnnotationBean)")
	public void aopPointCut() {}
    
    
    
    //2.
    //Before Advice λ©”μ†Œλ“œ
	//@Before : ν•΅μ‹¬κ΄€μ‹¬μ½”λ“œ μ‹€ν–‰ 전에 νš‘λ‹¨κ΄€μ‹¬μ½”λ“œλ₯Ό μ‹€ν–‰ν•˜λŠ” κΈ°λŠ₯을 μ œκ³΅ν•˜λŠ” μ–΄λ…Έν…Œμ΄μ…˜
	// => Spring Bean Configuration File의 before μ—˜λ¦¬λ¨ΌνŠΈμ™€ μœ μ‚¬ν•œ κΈ°λŠ₯ 제곡
	//value 속성 : νƒ€κ²Ÿλ©”μ†Œλ“œλ₯Ό μ§€μ •ν•˜κΈ° μœ„ν•œ PointCut ν‘œν˜„μ‹μ„ μ†μ„±κ°’μœΌλ‘œ μ„€μ •
	// => λ‹€λ₯Έ 속성이 μ—†λŠ” 경우 μ†μ„±κ°’λ§Œ μ„€μ • κ°€λŠ₯
	//@Before("within(xyz.itwill07.aop.AopAnnotationBean)")
	//value μ†μ„±κ°’μœΌλ‘œ @Pointcut μ–΄λ…Έν…Œμ΄μ…˜μ„ μ‚¬μš©ν•œ λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•˜λ©΄ λ“±λ‘λœ PointCut ν‘œν˜„μ‹μ„ μ œκ³΅λ°›μ•„ μ‚¬μš© κ°€λŠ₯
	@Before("aopPointCut()")
	public void beforeLog() {
		logger.info("[before]ν•΅μ‹¬κ΄€μ‹¬μ½”λ“œ μ‹€ν–‰ μ „ μ‚½μž…λ˜μ–΄ 싀행될 νš‘λ‹¨κ΄€μ‹¬μ½”λ“œ");
	}
    
    
    
    //3.
    //After Advice λ©”μ†Œλ“œ
	//@After : ν•΅μ‹¬κ΄€μ‹¬μ½”λ“œ μ‹€ν–‰ 후에 무쑰건 νš‘λ‹¨κ΄€μ‹¬μ½”λ“œλ₯Ό μ‹€ν–‰ν•˜λŠ” κΈ°λŠ₯을 μ œκ³΅ν•˜λŠ” μ–΄λ…Έν…Œμ΄μ…˜
	// => Spring Bean Configuration File의 after μ—˜λ¦¬λ¨ΌνŠΈμ™€ μœ μ‚¬ν•œ κΈ°λŠ₯ 제곡
	//@After(value = "within(xyz.itwill07.aop.AopAnnotationBean)")
	@After("aopPointCut()")
	public void afterLog() {
		logger.info("[after]ν•΅μ‹¬κ΄€μ‹¬μ½”λ“œ μ‹€ν–‰ ν›„ 무쑰건 μ‚½μž…λ˜μ–΄ 싀행될 νš‘λ‹¨κ΄€μ‹¬μ½”λ“œ");
	}
    
    
    
    //4.
    //After Returning Advice λ©”μ†Œλ“œ
	//@AfterReturning : ν•΅μ‹¬κ΄€μ‹¬μ½”λ“œκ°€ μ •μƒμ μœΌλ‘œ μ‹€ν–‰λœ ν›„ νš‘λ‹¨κ΄€μ‹¬μ½”λ“œλ₯Ό μ‹€ν–‰ν•˜λŠ” κΈ°λŠ₯을 μ œκ³΅ν•˜λŠ” μ–΄λ…Έν…Œμ΄μ…˜
	// => Spring Bean Configuration File의 after-returning μ—˜λ¦¬λ¨ΌνŠΈμ™€ μœ μ‚¬ν•œ κΈ°λŠ₯ 제곡
	//@AfterReturning("aopPointCut()")
	//returning 속성 :  νƒ€κ²Ÿλ©”μ†Œλ“œμ˜ λ°˜ν™˜κ°’μ„ μ €μž₯ν•˜κΈ° μœ„ν•œ λ§€κ°œλ³€μˆ˜μ˜ 이름을 μ†μ„±κ°’μœΌλ‘œ μ„€μ •
	@AfterReturning(value="aopPointCut()", returning="object")
	public void afterReturningLog(Object object) {
		logger.info("[after-returning]ν•΅μ‹¬κ΄€μ‹¬μ½”λ“œκ°€ μ •μƒμ μœΌλ‘œ μ‹€ν–‰λœ ν›„ μ‚½μž…λ˜μ–΄ 싀행될 νš‘λ‹¨κ΄€μ‹¬μ½”λ“œ");
	}
    
    
    
    //5.
    //After Throwing Advice λ©”μ†Œλ“œ
	//@AfterThrowing : ν•΅μ‹¬κ΄€μ‹¬μ½”λ“œ μ‹€ν–‰μ‹œ μ˜ˆμ™Έκ°€ λ°œμƒλœ 경우 νš‘λ‹¨κ΄€μ‹¬μ½”λ“œλ₯Ό μ‹€ν–‰ν•˜λŠ” κΈ°λŠ₯을 μ œκ³΅ν•˜λŠ” μ–΄λ…Έν…Œμ΄μ…˜
	// => Spring Bean Configuration File의 after-throwing μ—˜λ¦¬λ¨ΌνŠΈμ™€ μœ μ‚¬ν•œ κΈ°λŠ₯ 제곡
	//throwing 속성 :  νƒ€κ²Ÿλ©”μ†Œλ“œμ—μ„œ λ°œμƒλœ μ˜ˆμ™Έλ₯Ό μ €μž₯ν•˜κΈ° μœ„ν•œ λ§€κ°œλ³€μˆ˜μ˜ 이름을 μ†μ„±κ°’μœΌλ‘œ μ„€μ •
	@AfterThrowing(value="aopPointCut()", throwing ="exception" )
	public void afterThrowingLog(Exception exception) {
		logger.info("[after-throwing]ν•΅μ‹¬κ΄€μ‹¬μ½”λ“œ μ‹€ν–‰μ‹œ μ˜ˆμ™Έκ°€ λ°œμƒλ˜λ©΄ μ‚½μž…λ˜μ–΄ 싀행될 νš‘λ‹¨κ΄€μ‹¬μ½”λ“œ");
	}
    
    
    
    //6.
    //Around Advice λ©”μ†Œλ“œ
	//@Around : ν•΅μ‹¬κ΄€μ‹¬μ½”λ“œ μ‹€ν–‰ μ „κ³Ό 후에 νš‘λ‹¨κ΄€μ‹¬μ½”λ“œλ₯Ό μ‹€ν–‰ν•˜λŠ” κΈ°λŠ₯을 μ œκ³΅ν•˜λŠ” μ–΄λ…Έν…Œμ΄μ…˜
	// => Spring Bean Configuration File의 around μ—˜λ¦¬λ¨ΌνŠΈμ™€ μœ μ‚¬ν•œ κΈ°λŠ₯ 제곡
	@Around("aopPointCut()")
	public Object aroundLog(ProceedingJoinPoint joinPoint) throws Throwable {
		logger.info("[around]ν•΅μ‹¬κ΄€μ‹¬μ½”λ“œ μ‹€ν–‰ 전에 μ‚½μž…λ˜μ–΄ 싀행될 νš‘λ‹¨κ΄€μ‹¬μ½”λ“œ");
		Object object=joinPoint.proceed();
		logger.info("[around]ν•΅μ‹¬κ΄€μ‹¬μ½”λ“œ μ‹€ν–‰ 후에 μ‚½μž…λ˜μ–΄ 싀행될 νš‘λ‹¨κ΄€μ‹¬μ½”λ“œ");
		return object;
	}

}

04. μ‹€ν–‰ν”„λ‘œκ·Έλž¨

AopAnnotationApp.java
package xyz.itwill07.aop;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AopAnnotationApp {
	public static void main(String[] args) throws Exception {
		ApplicationContext context = new ClassPathXmlApplicationContext("07-5_aopAnnotation.xml");
		AopAnnotationBean bean = context.getBean("aopAnnotationBean",AopAnnotationBean.class);
		System.out.println("======================================================");
		bean.display1();
		System.out.println("======================================================");
		bean.display2();
		System.out.println("======================================================");
		bean.display3();
		System.out.println("======================================================");
		((ClassPathXmlApplicationContext)context).close();
	}
}

 

λ°˜μ‘ν˜•