[Spring] AOP (Aspect Oriented Programming)


SpringSecurity - AOP (Aspect Oriented Programming)



AOP

AOP๋Š” Aspect Oriented Programming์˜ ์•ฝ์ž๋กœ ๊ด€์  ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ด๋ผ๊ณ  ๋ถˆ๋ฆฐ๋‹ค. ๊ด€์  ์ง€ํ–ฅ์€ ์‰ฝ๊ฒŒ ๋งํ•ด ์–ด๋–ค ๋กœ์ง์„ ๊ธฐ์ค€์œผ๋กœ ํ•ต์‹ฌ์ ์ธ ๊ด€์ , ๋ถ€๊ฐ€์ ์ธ ๊ด€์ ์œผ๋กœ ๋‚˜๋ˆ„์–ด์„œ ๋ณด๊ณ  ๊ทธ ๊ด€์ ์„ ๊ธฐ์ค€์œผ๋กœ ๊ฐ๊ฐ ๋ชจ๋“ˆํ™”ํ•˜๊ฒ ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ์—ฌ๊ธฐ์„œ ๋ชจ๋“ˆํ™”๋ž€ ์–ด๋–ค ๊ณตํ†ต๋œ ๋กœ์ง์ด๋‚˜ ๊ธฐ๋Šฅ์„ ํ•˜๋‚˜์˜ ๋‹จ์œ„๋กœ ๋ฌถ๋Š” ๊ฒƒ์„ ๋งํ•œ๋‹ค.

Spring์˜ ํ•ต์‹ฌ ๊ฐœ๋…์ค‘ ํ•˜๋‚˜์ธ DI๊ฐ€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ชจ๋“ˆ๋“ค ๊ฐ„์˜ ๊ฒฐํ•ฉ๋„๋ฅผ ๋‚ฎ์ถฐ์ค€๋‹ค๋ฉด, AOP๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ „์ฒด์— ๊ฑธ์ณ ์‚ฌ์šฉ๋˜๋Š” ๊ธฐ๋Šฅ์„ ์žฌ์‚ฌ์šฉํ•˜๋„๋ก ์ง€์›ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.


์˜ˆ๋กœ๋“ค์–ด ํ•ต์‹ฌ์ ์ธ ๊ด€์ ์€ ๊ฒฐ๊ตญ ์šฐ๋ฆฌ๊ฐ€ ์ ์šฉํ•˜๊ณ ์ž ํ•˜๋Š” ํ•ต์‹ฌ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์ด ๋œ๋‹ค. ๋˜ํ•œ ๋ถ€๊ฐ€์ ์ธ ๊ด€์ ์€ ํ•ต์‹ฌ ๋กœ์ง์„ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด์„œ ํ–‰ํ•ด์ง€๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ, ๋กœ๊น…, ํŒŒ์ผ ์ž…์ถœ๋ ฅ ๋“ฑ์„ ์˜ˆ๋กœ ๋“ค ์ˆ˜ ์žˆ๋‹ค.

  • OOP : ๋น„์ง€๋‹ˆ์Šค ๋กœ์ง์˜ ๋ชจ๋“ˆํ™”
    • ๋ชจ๋“ˆํ™”์˜ ํ•ต์‹ฌ ๋‹จ์œ„๋Š” ๋น„์ง€๋‹ˆ์Šค ๋กœ์ง
  • AOP : ์ธํ”„๋ผ ํ˜น์€ ๋ถ€๊ฐ€๊ธฐ๋Šฅ์˜ ๋ชจ๋“ˆํ™”
    • ๋Œ€ํ‘œ์  ์˜ˆ : ๋กœ๊น…, ํŠธ๋žœ์žญ์…˜, ๋ณด์•ˆ ๋“ฑ
    • ๊ฐ๊ฐ์˜ ๋ชจ๋“ˆ๋“ค์˜ ์ฃผ ๋ชฉ์  ์™ธ์— ํ•„์š”ํ•œ ๋ถ€๊ฐ€์ ์ธ ๊ธฐ๋Šฅ๋“ค


AOP์—์„œ ๊ฐ ๊ด€์ ์„ ๊ธฐ์ค€์œผ๋กœ ๋กœ์ง์„ ๋ชจ๋“ˆํ™”ํ•œ๋‹ค๋Š” ๊ฒƒ์€ ์ฝ”๋“œ๋“ค์„ ๋ถ€๋ถ„์ ์œผ๋กœ ๋‚˜๋ˆ„์–ด์„œ ๋ชจ๋“ˆํ™”ํ•˜๊ฒ ๋‹ค๋Š” ์˜๋ฏธ๋‹ค. ์ด๋•Œ, ์†Œ์Šค ์ฝ”๋“œ์ƒ์—์„œ ๋‹ค๋ฅธ ๋ถ€๋ถ„์— ๊ณ„์† ๋ฐ˜๋ณตํ•ด์„œ ์“ฐ๋Š” ์ฝ”๋“œ๋“ค์„ ๋ฐœ๊ฒฌํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐ ์ด๊ฒƒ์„ ํฉ์–ด์ง„ ๊ด€์‹ฌ์‚ฌ (Crosscutting Concerns)๋ผ ๋ถ€๋ฅธ๋‹ค.


img1 daumcdn

์œ„์™€ ๊ฐ™์ด ํฉ์–ด์ง„ ๊ด€์‹ฌ์‚ฌ๋ฅผ Aspect๋กœ ๋ชจ๋“ˆํ™”ํ•˜๊ณ  ํ•ต์‹ฌ์ ์ธ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์—์„œ ๋ถ„๋ฆฌํ•˜์—ฌ ์žฌ์‚ฌ์šฉํ•˜๊ฒ ๋‹ค๋Š” ๊ฒƒ์ด AOP์˜ ์ทจ์ง€๋‹ค.


AOP ์ฃผ์š” ๊ฐœ๋…

  • Aspect : ์œ„์—์„œ ์„ค๋ช…ํ•œ ํฉ์–ด์ง„ ๊ด€์‹ฌ์‚ฌ๋ฅผ ๋ชจ๋“ˆํ™” ํ•œ ๊ฒƒ. ์ฃผ๋กœ ๋ถ€๊ฐ€๊ธฐ๋Šฅ ๋ชจ๋“ˆ์„ Aspect๋ผ๊ณ  ๋ถ€๋ฅด๋ฉฐ ํ•ต์‹ฌ๊ธฐ๋Šฅ์— ๋ถ€๊ฐ€๋˜์–ด ์˜๋ฏธ๋ฅผ ๊ฐ–๋Š” ํŠน๋ณ„ํ•œ ๋ชจ๋“ˆ์ด๋ผ ์ƒ๊ฐํ•˜๋ฉด ๋œ๋‹ค.

  • Target : Aspect๋ฅผ ์ ์šฉํ•˜๋Š” ๊ณณ (ํด๋ž˜์Šค, ๋ฉ”์„œ๋“œ .. )

  • Advice : ์‹ค์งˆ์ ์œผ๋กœ ์–ด๋–ค ์ผ์„ ํ•ด์•ผํ•  ์ง€์— ๋Œ€ํ•œ ๊ฒƒ, ์‹ค์งˆ์ ์ธ ๋ถ€๊ฐ€๊ธฐ๋Šฅ์„ ๋‹ด์€ ๊ตฌํ˜„์ฒด

    • Advice์˜ ๊ฒฝ์šฐ ํƒ€๊ฒŸ ์˜คํ”„์ ํŠธ์— ์ข…์†๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์ˆœ์ˆ˜ํ•˜๊ฒŒ ๋ถ€๊ฐ€๊ธฐ๋Šฅ์—๋งŒ ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ๋‹ค.

    • Advice๋Š” Aspect๊ฐ€ โ€œ๋ฌด์—‡์„โ€, โ€œ์–ธ์ œโ€ ํ• ์ง€๋ฅผ ์˜๋ฏธํ•˜๊ณ  ์žˆ๋‹ค.

  • JointPoint : Advice๊ฐ€ ์ ์šฉ๋  ์œ„์น˜, ๋ผ์–ด๋“ค ์ˆ˜ ์žˆ๋Š” ์ง€์ . ๋ฉ”์„œ๋“œ ์ง„์ž… ์ง€์ , ์ƒ์„ฑ์ž ํ˜ธ์ถœ ์‹œ์ , ํ•„๋“œ์—์„œ ๊ฐ’์„ ๊บผ๋‚ด์˜ฌ ๋•Œ ๋“ฑ ๋‹ค์–‘ํ•œ ์‹œ์ ์— ์ ์šฉ๊ฐ€๋Šฅ , Spring์—์„œ๋Š” ๋ฉ”์†Œ๋“œ ์กฐ์ธํฌ์ธํŠธ๋งŒ ์ œ๊ณต

  • PointCut : JointPoint์˜ ์ƒ์„ธํ•œ ์ŠคํŽ™์„ ์ •์˜ํ•œ ๊ฒƒ. โ€˜A๋ž€ ๋ฉ”์„œ๋“œ์˜ ์ง„์ž… ์‹œ์ ์— ํ˜ธ์ถœํ•  ๊ฒƒโ€™๊ณผ ๊ฐ™์ด ๋”์šฑ ๊ตฌ์ฒด์ ์œผ๋กœ Advice๊ฐ€ ์‹คํ–‰๋  ์ง€์ ์„ ์ •ํ•  ์ˆ˜ ์žˆ์Œ (๋ถ€๊ฐ€๊ธฐ๋Šฅ์ด ์ ์šฉ๋  ๋Œ€์ƒ(๋ฉ”์†Œ๋“œ)๋ฅผ ์„ ์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์–˜๊ธฐํ•œ๋‹ค.) ์ฆ‰, ์–ด๋“œ๋ฐ”์ด์Šค๋ฅผ ์ ์šฉํ•  ์กฐ์ธํฌ์ธํŠธ๋ฅผ ์„ ๋ณ„ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ •์˜ํ•œ ๋ชจ๋“ˆ์„ ์–˜๊ธฐํ•œ๋‹ค.

    (์–ด๋“œ๋ฐ”์ด์Šค์˜ value๋กœ ๋“ค์–ด๊ฐ„ ๋ฌธ์ž์—ด์„ ํฌ์ธํŠธ์ปท ํ‘œํ˜„์‹์ด๋ผ๊ณ  ํ•œ๋‹ค.)

    • ํฌ์ธํŠธ์ปท ํ‘œํ˜„์‹์€ 2๊ฐ€์ง€๋กœ ๋‚˜๋ˆ ์ง€๋Š”๋ฐ, execution์„ ์ง€์ •์ž๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.
    • (* com.hojin2world..*.EventService.*(..)))๋Š” ํƒ€๊ฒŸ ๋ช…์„ธ๋ผ๊ณ  ํ•œ๋‹ค.
  • Proxy : ํƒ€๊ฒŸ์„ ๊ฐ์‹ธ์„œ ํƒ€๊ฒŸ์˜ ์š”์ฒญ์„ ๋Œ€์‹  ๋ฐ›์•„์ฃผ๋Š” ๋žฉํ•‘(Wrapping) ์˜ค๋ธŒ์ ํŠธ์ด๋‹ค. ํ˜ธ์ถœ์ž (ํด๋ผ์ด์–ธํŠธ)์—์„œ ํƒ€๊ฒŸ์„ ํ˜ธ์ถœํ•˜๊ฒŒ ๋˜๋ฉด ํƒ€๊ฒŸ์ด ์•„๋‹Œ ํƒ€๊ฒŸ์„ ๊ฐ์‹ธ๊ณ  ์žˆ๋Š” Proxy๊ฐ€ ํ˜ธ์ถœ๋˜์–ด, ํƒ€๊ฒŸ ๋ฉ”์†Œ๋“œ ์‹คํ–‰์ „์— ์„ ์ฒ˜๋ฆฌ, ํƒ€๊ฒŸ ๋ฉ”์†Œ๋“œ ์‹คํ–‰ ํ›„, ํ›„์ฒ˜๋ฆฌ๋ฅผ ์‹คํ–‰์‹œํ‚ค๋„๋ก ๊ตฌ์„ฑ๋˜์–ด์žˆ๋‹ค. img1 daumcdn

(AOP์—์„œ ํ”„๋ก์‹œ๋Š” ํ˜ธ์ถœ์„ ๊ฐ€๋กœ์ฑˆ ํ›„, ์–ด๋“œ๋ฐ”์ด์Šค์— ๋“ฑ๋ก๋œ ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ ํ›„ ํƒ€๊ฒŸ ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.)


AOP ํŠน์ง•

  • ํ”„๋ก์‹œ ํŒจํ„ด ๊ธฐ๋ฐ˜์˜ AOP ๊ตฌํ˜„์ฒด, ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ์“ฐ๋Š” ์ด์œ ๋Š” ์ ‘๊ทผ ์ œ์–ด ๋ฐ ๋ถ€๊ฐ€๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜๊ธฐ ์œ„ํ•ด์„œ์ž„
  • ์Šคํ”„๋ง ๋นˆ์—๋งŒ AOP๋ฅผ ์ ์šฉ ๊ฐ€๋Šฅ
  • ๋ชจ๋“  AOP ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ ์Šคํ”„๋ง IoC์™€ ์—ฐ๋™ํ•˜์—ฌ ์—”ํ„ฐํ”„๋ผ์ด์ฆˆ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๊ฐ€์žฅ ํ”ํ•œ ๋ฌธ์ œ(์ค‘๋ณต์ฝ”๋“œ, ํ”„๋ก์‹œ ํด๋ž˜์Šค ์ž‘์„ฑ์˜ ๋ฒˆ๊ฑฐ๋กœ์›€, ๊ฐ์ฒด๋“ค ๊ฐ„ ๊ด€๊ณ„ ๋ณต์žก๋„ ์ฆ๊ฐ€ โ€ฆ)์— ๋Œ€ํ•œ ํ•ด๊ฒฐ์ฑ…์„ ์ง€์›ํ•˜๋Š” ๊ฒƒ์ด ๋ชฉ์ 


AOP์˜ ์žฅ์ 

  • ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ „์ฒด์— ํฉ์–ด์ง„ ๊ณตํ†ต ๊ธฐ๋Šฅ์ด ํ•˜๋‚˜์˜ ์žฅ์†Œ์—์„œ ๊ด€๋ฆฌ๋œ๋‹ค๋Š” ์ 
  • ๋‹ค๋ฅธ ์„œ๋น„์Šค ๋ชจ๋“ˆ๋“ค์ด ๋ณธ์ธ์˜ ๋ชฉ์ ์—๋งŒ ์ถฉ์‹คํ•˜๊ณ  ๊ทธ์™ธ ์‚ฌํ•ญ๋“ค์€ ์‹ ๊ฒฝ์“ฐ์ง€ ์•Š์•„๋„ ๋œ๋‹ค๋Š” ์ 


์Šคํ”„๋ง AOP : @AOP

์Šคํ”„๋ง @AOP๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์˜์กด์„ฑ์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•œ๋‹ค.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>


๋‹ค์Œ์—๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด @Aspect ์–ด๋…ธํ…Œ์ด์…˜์„ ๋ถ™์—ฌ ์ด ํด๋ž˜์Šค๊ฐ€ Aspect๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ํด๋ž˜์Šค๋ผ๋Š” ๊ฒƒ์„ ๋ช…์‹œํ•˜๊ณ  @Component๋ฅผ ๋ถ™์—ฌ ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•œ๋‹ค.

@Component
@Aspect
public class PerfAspect {

// Around -> ์–ด๋“œ๋ฐ”์ด์Šค (Advice๋Š” Aspect๊ฐ€ "๋ฌด์—‡์„", "์–ธ์ œ" ํ• ์ง€๋ฅผ ์˜๋ฏธํ•˜๊ณ  ์žˆ๋‹ค.)
// ์—ฌ๊ธฐ์„œ "๋ฌด์—‡"์€ logPerf() ๋ฉ”์†Œ๋“œ๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค.
/* ๊ทธ๋ฆฌ๊ณ  "์–ธ์ œ"๋Š” @Around๊ฐ€ ๋˜๋Š”๋ฐ , ์ด ์–ธ์ œ๋ผ๋Š” ์‹œ์ ์˜ ๊ฒฝ์šฐ @Around๋งŒ ์กด์žฌํ•˜์ง€ ์•Š๊ณ  ์ด 5๊ฐ€์ง€์˜
   ํƒ€์ž…์ด ์กด์žฌํ•œ๋‹ค. @Before, @After ... */ 
// execution -> ํฌ์ธํŠธ์ปท ์ง€์ •์ž 
// *๋ฆฌํ„ด ํƒ€์ž…์„ ๋‚˜ํƒ€๋‚ธ๋‹ค.            ํ˜„์žฌ : ๋ชจ๋“  ํƒ€์ž… ๋ฆฌํ„ด ๊ฐ€๋Šฅ 
// com.hojin2world..*.EventService.* ํƒ€๊ฒŸ์ด ๋˜๋Š” ๋ฉ”์†Œ๋“œ ์ง€์ • 
// (..) -> ์ธ์ž(argument)ํƒ€์ž…      ํ˜„์žฌ : ๋ชจ๋“  ํƒ€์ž… ์ธ์ž ํ—ˆ์šฉ
@Around("execution(* com.hojin2world..*.EventService.*(..))")
public Object logPerf(ProceedingJoinPoint pjp) throws Throwable{
			long begin = System.currentTimeMillis();
			Object retVal = pjp.proceed(); // ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ ์ž์ฒด๋ฅผ ๊ฐ์Œˆ
			System.out.println(System.currentTimeMillis() - begin);
			return retVal;
	}
}

@Around ์–ด๋…ธํ…Œ์ด์…˜์€ ํƒ€๊ฒŸ ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ์‹ธ์„œ ํŠน์ • Advice๋ฅผ ์‹คํ–‰ํ•œ๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค. ์œ„ ์ฝ”๋“œ์˜ Advice๋Š” ํƒ€๊ฒŸ ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋œ ์‹œ๊ฐ„์„ ์ธก์ •ํ•˜๊ธฐ ์œ„ํ•œ ๋กœ์ง์„ ๊ตฌํ˜„ํ•˜์˜€๋‹ค. ์ถ”๊ฐ€์ ์œผ๋กœ execution(* com.hojin2world..*.EventService.*(..))๊ฐ€ ์˜๋ฏธํ•˜๋Š” ๋ฐ”๋Š” com.hojin2world ์•„๋ž˜์˜ ํŒจํ‚ค์ง€ ๊ฒฝ๋กœ์˜ EventService ๊ฐ์ฒด์˜ ๋ชจ๋“  ๋ฉ”์„œ๋“œ์— ์ด Aspect๋ฅผ ์ ์šฉํ•˜๊ฒ ๋‹ค๋Š” ์˜๋ฏธ๋‹ค.

public interface EventService {
    void createEvent();
    void publishEvent();
    void deleteEvent();
}
@Component
public class SimpleEventService implements EventService {
    
    @Override
    public void createEvent() {
        try {
            Thread.sleep(1000);
        } catch(InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Created an event");
    }

    @Override
    public void publishEvent() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e){
            e.printStackTrace();;
        }
        System.out.println("Published an event");
    }

    public void deleteEvent() {
        System.out.println("Delete an event");
    }
}
@Service
public class AppRunner implements ApplicationRunner {

    @Autowired
    EventService eventService;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        eventService.createEvent();
        eventService.publishEvent();
        eventService.deleteEvent();
    }
}
Created an event
1003
Published an event
1000
Delete an event
0


๋˜ํ•œ ๊ฒฝ๋กœ์ง€์ • ๋ฐฉ์‹๋ง๊ณ  ํŠน์ • ์–ด๋…ธํ…Œ์ด์…˜์ด ๋ถ™์€ ํฌ์ธํŠธ์— ํ•ด๋‹น Aspect๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ๋„ ์ œ๊ณตํ•œ๋‹ค.

@Component
@Aspect
public class PerfAspect {   
@Around("@annotation(PerLogging)")
public Object logPerf(ProceedingJoinPoint pjp) throws Throwable{
			long begin = System.currentTimeMillis();
			Object retVal = pjp.proceed(); // ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ ์ž์ฒด๋ฅผ ๊ฐ์Œˆ
			System.out.println(System.currentTimeMillis() - begin);
			return retVal;
	}
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.CLASS)
	public @interface PerLogging {
}
@Component
public class SimpleEventService implements EventService {

    @PerLogging
    @Override
    public void createEvent() {
        try {
            Thread.sleep(1000);
        } catch(InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Created an event");
    }

    @Override
    public void publishEvent() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e){
            e.printStackTrace();;
        }
        System.out.println("Published an event");
    }

    @PerLogging
    @Override
    public void deleteEvent() {
        System.out.println("Delete an event");
    }
}
Created an event
1003
Published an event
Delete an event
0

์œ„ ์ถœ๋ ฅ ๊ฒฐ๊ณผ์—์„œ @PerLogging ์–ด๋…ธํ…Œ์ด์…˜์ด ๋ถ™์€ ๋ฉ”์„œ๋“œ๋งŒ Aspect๊ฐ€ ์ ์šฉ๋œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.


๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์Šคํ”„๋ง ๋นˆ์˜ ๋ชจ๋“  ๋ฉ”์„œ๋“œ์— ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ๋„ ์ œ๊ณตํ•œ๋‹ค.

@Component
@Aspect
public class PerfAspect {

@Around("bean(simpleEventService)")
public Object logPerf(ProceedingJoinPoint pjp) throws Throwable{
			long begin = System.currentTimeMillis();
			Object retVal = pjp.proceed(); // ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ ์ž์ฒด๋ฅผ ๊ฐ์Œˆ
			System.out.println(System.currentTimeMillis() - begin);
		return retVal;
	}
}
@Component
public class SimpleEventService implements EventService {

    @Override
    public void createEvent() {
        try {
            Thread.sleep(1000);
        } catch(InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Created an event");
    }

    @Override
    public void publishEvent() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e){
            e.printStackTrace();;
        }
        System.out.println("Published an event");
    }
    
    @Override
    public void deleteEvent() {
        System.out.println("Delete an event");
    }
}
@Service
public class AppRunner implements ApplicationRunner {

    @Autowired
    EventService eventService;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        eventService.createEvent();
        eventService.publishEvent();
        eventService.deleteEvent();
    }
}
Created an event
1002
Published an event
1001
Delete an event
0

์œ„ ์ถœ๋ ฅ๊ฒฐ๊ณผ๋กœ SimpleEventService์˜ ๋ชจ๋“  ๋ฉ”์„œ๋“œ์— ํ•ด๋‹น Aspect๊ฐ€ ์ถ”๊ฐ€๋œ ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.


์ด ๋ฐ–์—๋„ @Around ์™ธ์— ํƒ€๊ฒŸ ๋ฉ”์„œ๋“œ์˜ Aspect ์‹คํ–‰ ์‹œ์ ์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์–ด๋…ธํ…Œ์ด์…˜์ด ์žˆ๋‹ค.

  • @Before (์ด์ „) : ์–ด๋“œ๋ฐ”์ด์Šค ํƒ€๊ฒŸ ๋ฉ”์†Œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜๊ธฐ ์ „์— ์–ด๋“œ๋ฐ”์ด์Šค ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰

  • @After (์ดํ›„) : ํƒ€๊ฒŸ ๋ฉ”์†Œ๋“œ์˜ ๊ฒฐ๊ณผ์— ๊ด€๊ณ„์—†์ด(์ฆ‰ ์„ฑ๊ณต, ์˜ˆ์™ธ ๊ด€๊ณ„์—†์ด) ํƒ€๊ฒŸ ๋ฉ”์†Œ๋“œ๊ฐ€ ์™„๋ฃŒ ๋˜๋ฉด ์–ด๋“œ๋ฐ”์ด์Šค ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰
  • @AfterReturning (์ •์ƒ์  ๋ฐ˜ํ™˜ ์ดํ›„)ํƒ€๊ฒŸ ๋ฉ”์†Œ๋“œ๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ๊ฒฐ๊ณผ๊ฐ’์„ ๋ฐ˜ํ™˜ ํ›„์— ์–ด๋“œ๋ฐ”์ด์Šค ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰
  • @AfterThrowing (์˜ˆ์™ธ ๋ฐœ์ƒ ์ดํ›„) : ํƒ€๊ฒŸ ๋ฉ”์†Œ๋“œ๊ฐ€ ์ˆ˜ํ–‰ ์ค‘ ์˜ˆ์™ธ๋ฅผ ๋˜์ง€๊ฒŒ ๋˜๋ฉด ์–ด๋“œ๋ฐ”์ด์Šค ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰
  • @Around (๋ฉ”์†Œ๋“œ ์‹คํ–‰ ์ „ํ›„) : ์–ด๋“œ๋ฐ”์ด์Šค๊ฐ€ ํƒ€๊ฒŸ ๋ฉ”์†Œ๋“œ๋ฅผ ๊ฐ์‹ธ์„œ ํƒ€๊ฒŸ ๋ฉ”์†Œ๋“œ ํ˜ธ์ถœ์ „๊ณผ ํ›„์— ์–ด๋“œ๋ฐ”์ด์Šค ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰
    • @Around์˜ ๊ฒฝ์šฐ ๋ฐ˜๋“œ์‹œ proceed() ๋ฉ”์†Œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜์–ด์•ผ ํ•œ๋‹ค.
    • proceed() ๋ฉ”์†Œ๋“œ๋Š” ํƒ€๊ฒŸ ๋ฉ”์†Œ๋“œ๋ฅผ ์ง€์นญํ•˜๊ธฐ ๋•Œ๋ฌธ์— proceed ๋ฉ”์†Œ๋“œ๋ฅผ ์‹คํ–‰์‹œ์ผœ์•ผ๋งŒ ํƒ€๊ฒŸ ๋ฉ”์†Œ๋“œ๊ฐ€ ์ˆ˜ํ–‰์ด ๋œ๋‹ค๋Š”๊ฒƒ์„ ์žŠ์ง€ ๋ง์ž.
//์˜ˆ๋ฅผ ๋“ค์–ด ํƒ€๊ฒŸ ๋ฉ”์†Œ๋“œ์˜ ์ด์ „ ์‹œ์ ์—์„œ๋งŒ ์–ด๋“œ๋ฐ”์ด์Šค ๋ฉ”์†Œ๋“œ๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด,
@Before("ํฌ์ธํŠธ์ปท ํ‘œํ˜„์‹")
public void ์–ด๋“œ๋ฐ”์ด์Šค๋ฉ”์†Œ๋“œ() {
    ....
}


reference

https://engkimbs.tistory.com/746 
https://jojoldu.tistory.com/71