์ ๋ ธํ ์ด์ ๊ธฐ๋ฐ์ ์คํ๋ง @AOP
์์กด์ฑ ์ถ๊ฐ
<dependency>
<groupId>org.sringframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
Aspect ์ ์
- @Aspect
- ๋น์ผ๋ก ๋ฑ๋กํด์ผ ํ๋๊น (์ปดํฌ๋ํธ ์ค์บ์ ์ฌ์ฉํ๋ค๋ฉด) @Component๋ ์ถ๊ฐ
ํฌ์ธํธ์ปท ์ ์
- @PointCut(ํํ์)
- ์ฃผ์ ํํ์
- execution
@Service
public class SimpleEventService implements EventService{
@Override
public void createEvent() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("create an Event");
}
@Override
public void publishEvent() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("publish an Event");
}
@Override
public void deleteEvent(){
System.out.println("Delete an Event");
}
}
@Aspect //Aspect๋ผ๋๊ฒ์ ์๋ ค์ค๋ค.
@Component //๋น์ผ๋ก ๋ฑ๋กํด์ผ ํ๋๊น, ์ปดํฌ๋ํธ ์ค์บ์ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์.
public class PerfAspect {
@Around("execution(* com.example..*.EventService.*(..))")
//์๋ ์ฝ๋๋ค์ com.example์๋ ๋ชจ๋ ํด๋์ค๋ค ์ค์ EventServiceํด๋์ค์ ๋ชจ๋ ๋ฉ์๋์ ์ ์ฉ์ ํ๊ฒ ๋ค.
//Around๋ ๋ฉ์๋ ํธ์ถ์ ๊ฐ์ธ๊ณ ์๋ ํํ์ด๊ธฐ ๋๋ฌธ์, ๋ฉ์๋ ํธ์ถ ์ , ํ ๋๋ ์๋ฌ๊ฐ ๋ฐ์ํ์๋๋ ํน์ ํ ์ผ์ ํ ์๊ฐ ์๋ ๋ค์ฉ๋๋ก ์ฐ์ผ์ ์๋ ์ ๋
ธํ
์ด์
์ด๋ค.
//Advice
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 AppRunner implements ApplicationRunner {
@Autowired
EventService eventService; //interface๊ฐ ์๋ค๋ฉด interfaceํ์
์ผ๋ก ๋ฐ๋๊ฒ ๊ฐ์ฅ ์ข๋ค. ๊ตฌํ์ฒด๋ก ๋ฐ์ง๋ง๊ณ .
@Override
public void run(ApplicationArguments args) throws Exception {
eventService.createEvent();
eventService.publishEvent();
eventService.deleteEvent();
}
}
์คํ ๊ฒฐ๊ณผ
create an Event
1011
publish an Event
2001
Delete an Event
0
๋ฌธ์ ์ : deleteEvent ๋ฉ์๋์๋ ์ ์ฉํ๊ณ ์ถ์ง ์์๋ฐ , ๋ชจ๋ ๋ฉ์๋์ ์ ์ฉ์ด ๋๋ฒ๋ฆฐ๋ค.
(execution์ผ๋ก๋ ํ ์๊ฐ ์๊ธดํ๋ฐ, ๋๊ฒ ๋ณต์กํ๊ณ ์ด๋ ต๋ค..)
- @annotation
๋จผ์ Advice๋ฅผ ์ ์ฉ์ ํ ํ์๋ฅผ ํ๊ธฐ ์ํ ์ ๋ ธํ ์ด์ ์ ์์ฑํ๋ค.
@Target(ElementType.METHOD) //target์ด METHOD ๋ผ๋๊ฒ์ ๋ช
์ํด์ฃผ๋๊ฒ์ด ์ข๋ค.
@Retention(RetentionPolicy.CLASS) //RetentionPolicy๊ฐ ์๋ฏธํ๋๊ฒ์ ์ด ์ ๋
ธํ
์ด์
์ ๋ณด๋ฅผ ์ผ๋ง๋ ์ ์ง๋ฅผ ํ ๊ฒ์ธ๊ฐ์ด๋ค.
//SOURCE๋ก ๊ฐ์ ์ฃผ๋ฉด, ์ปดํ์ผ์ด ๋๋๋ฉด ์ฌ๋ผ์ ธ ๋ฒ๋ฆฐ๋ค. (์ฃผ์)
//RetentionPolicy.CLASS ์ด์ ๊ฐ์ ์ค์ผํ๋ค. (๊ธฐ๋ณธ๊ฐ : CLASS) ๊ธฐ๋ณธ๊ฐ์ ์ฌ์ฉํ๋๋ผ๋ ๋ช
์๋ฅผ ํด์ฃผ๋ฉด ์ข๋ค!
public @interface PerfLogging {
}
์ ์ฉํ ๋ฉ์๋์ @PerfLogging ์ด๋ผ๊ณ ์ ๋ ธํ ์ด์ ์ ๋ถ์ฌ์ค๋ค.
@Service
public class SimpleEventService implements EventService{
@PerfLogging // Advice๋ฅผ ์คํํ๊ณ ์ถ์ ๋ฉ์๋์๋ง ์ ๋
ธํ
์ด์
์ ๋ถ์ธ๋ค.
@Override
public void createEvent() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("create an Event");
}
@PerfLogging // Advice๋ฅผ ์คํํ๊ณ ์ถ์ ๋ฉ์๋์๋ง ์ ๋
ธํ
์ด์
์ ๋ถ์ธ๋ค.
@Override
public void publishEvent() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("publish an Event");
}
@Override
public void deleteEvent(){
System.out.println("Delete an Event");
}
}
@Aspect
@Component
public class PerfAspect {
@Around("@annotation(PerfLogging)")
// @PerfLogging ์ด๋ผ๋ ์ ๋
ธํ
์ด์
์ด ๋ถ์ ๋ฉ์๋์๋ง Advice๋ฅผ ์ํํ๊ฒ ๋ค.
//Advice
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) //target์ด METHOD ๋ผ๋๊ฒ์ ๋ช
์ํด์ฃผ๋๊ฒ์ด ์ข๋ค.
@Retention(RetentionPolicy.CLASS) //RetentionPolicy๊ฐ ์๋ฏธํ๋๊ฒ์ ์ด ์ ๋
ธํ
์ด์
์ ๋ณด๋ฅผ ์ผ๋ง๋ ์ ์ง๋ฅผ ํ ๊ฒ์ธ๊ฐ์ด๋ค.
//RetentionPolicy.CLASS ์ด์ ๊ฐ์ ์ค์ผํ๋ค. (๊ธฐ๋ณธ๊ฐ : CLASS) ๊ธฐ๋ณธ๊ฐ์ ์ฌ์ฉํ๋๋ผ๋ ๋ช
์๋ฅผ ํด์ฃผ๋ฉด ์ข๋ค!
public @interface PerfLogging {
}
์ด๋ฐ์์ผ๋ก ํด์ฃผ๋ฉด ํ์๋ค์ด๋ ๋๊ตฐ๊ฐ ์ด ์ฝ๋๋ฅผ ๋ดค์๋, "์~ ์ด ์ ๋ ธํ ์ด์ ์ ๋ถ์ด๋ฉด ์ฑ๋ฅ์ ๋ก๊น ํด์ฃผ๋๊ตฌ๋!" ํ๊ณ ์ฝ๊ฒ ์์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
์คํ ๊ฒฐ๊ณผ
create an Event
1011
publish an Event
2001
Delete an Event
์คํ๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ค์ํผ @PerfLogging ์ ๋ ธํ ์ด์ ์ด ๋ถ์ ๋ฉ์๋๋ง Advice๊ฐ ์คํ๋์๋ค.
- bean
๋น์ผ๋ก ๋ฑ๋ก๋ ํด๋์ค์ ๋ชจ๋ ๋ฉ์๋์ ๋ํด์ Advice๊ฐ ์ํ๋๋ค.
@Aspect //Aspect๋ผ๋๊ฒ์ ์๋ ค์ค๋ค.
@Component //๋น์ผ๋ก ๋ฑ๋กํด์ผ ํ๋๊น, ์ปดํฌ๋ํธ ์ค์บ์ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์.
public class PerfAspect {
@Around("bean(simpleEventService)") //๋น(simpleEventService)์ ๋ชจ๋ ๋ฉ์๋์ ์ ์ฉ์ด ๋๋ค.
//Around๋ ๋ฉ์๋ ํธ์ถ์ ๊ฐ์ธ๊ณ ์๋ ํํ์ด๊ธฐ ๋๋ฌธ์, ๋ฉ์๋ ํธ์ถ ์ , ํ ๋๋ ์๋ฌ๊ฐ ๋ฐ์ํ์๋๋ ํน์ ํ ์ผ์ ํ ์๊ฐ ์๋ ๋ค์ฉ๋๋ก ์ฐ์ผ์ ์๋ ์ ๋
ธํ
์ด์
์ด๋ค.
//Advice
public Object logPerf(ProceedingJoinPoint pjp) throws Throwable {
long begin = System.currentTimeMillis();
Object retVal = pjp.proceed(); //๋ฉ์๋ ํธ์ถ์ ๊ฐ์ธ๊ณ ์๋ค.
System.out.println(System.currentTimeMillis() - begin);
return retVal;
}
}
@Service
public class SimpleEventService implements EventService{
@Override
public void createEvent() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("create an Event");
}
@Override
public void publishEvent() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("publish an Event");
}
@Override
public void deleteEvent(){
System.out.println("Delete an Event");
}
}
@Component
public class AppRunner implements ApplicationRunner {
@Autowired
EventService eventService; //interface๊ฐ ์๋ค๋ฉด interfaceํ์
์ผ๋ก ๋ฐ๋๊ฒ ๊ฐ์ฅ ์ข๋ค. ๊ตฌํ์ฒด๋ก ๋ฐ์ง๋ง๊ณ .
@Override
public void run(ApplicationArguments args) throws Exception {
eventService.createEvent();
eventService.publishEvent();
eventService.deleteEvent();
}
}
์คํ ๊ฒฐ๊ณผ
create an Event
1011
publish an Event
2001
Delete an Event
0
- ํฌ์ธํธ์ปท ์กฐํฉ
- &&, || , !
Advice ์ ์
- @Before : ์ด๋๋ฐ์ด์ค ํ๊ฒ ๋ฉ์๋๊ฐ ํธ์ถ๋๊ธฐ ์ ์ ์ด๋๋ฐ์ด์ค ๊ธฐ๋ฅ์ ์ํ
@Around ๊ฐ์ด ๊ฐ๋ ฅํ Advice๋ฅผ ์ฌ์ฉ์ํ๊ณ ๊ฐ๋จํ๊ฒ "๋ฉ์๋๊ฐ ์คํ๋๊ธฐ ์ด์ ์ ๋ญ๊ฐ๋ฅผ ํ๊ณ ์ถ๋ค" ํ๋ฉด @Before๋ฅผ ์ฌ์ฉํด๋ ๋๋ค.
@Before(bean("simpleEventService")//๋น์ผ๋ก ๋ฑ๋ก๋ simpleEventService์ ๋ชจ๋ ๋ฉ์๋๊ฐ ์คํ๋๊ธฐ ์ด์ ์..
public void hello(){
System.out.pritnln("hello");
}
์คํ ๊ฒฐ๊ณผ
hello
create an Event
1011
hello
publish an Event
2001
hello
Delete an Event
0
๋ฉ์๋๊ฐ ์คํ๋๊ธฐ ์ด์ ์ hello๊ฐ ์ฐํ๋๊ฑธ ๋ณผ ์ ์๋ค.
- @AfterReturning (์ ์์ ๋ฐํ ์ดํ) : ํ๊ฒ ๋ฉ์๋๊ฐ ์ฑ๊ณต์ ์ผ๋ก ๊ฒฐ๊ณผ๊ฐ์ ๋ฐํ ํ์ ์ด๋๋ฐ์ด์ค ๊ธฐ๋ฅ์ ์ํ
- @AfterThrowing (์์ธ ๋ฐ์ ์ดํ) : ํ๊ฒ ๋ฉ์๋๊ฐ ์ํ ์ค ์์ธ๋ฅผ ๋์ง๊ฒ ๋๋ฉด, ์ด๋๋ฐ์ด์ค ๊ธฐ๋ฅ์ ์ํ
- @Around (๋ฉ์๋ ์คํ ์ ํ) : ์ด๋๋ฐ์ด์ค๊ฐ ํ๊ฒ ๋ฉ์๋๋ฅผ ๊ฐ์ธ์ ๋ฉ์๋ ํธ์ถ ์ ๊ณผ ํ์ ์ด๋๋ฐ์ด์ค ๊ธฐ๋ฅ์ ์ํ
์ถ์ฒ:
https://engkimbs.tistory.com/746
https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#aop- pointcuts