1. AOP์ ์ ์ ๋ฐ ์๋ฆฌ
AOP : ๊ด์ ์งํฅ ํ๋ก๊ทธ๋๋ฐ (Aspect Oriented Programming)
- ๊ด์ ์งํฅ์ ์ด๋ค ๋ก์ง์ ๊ธฐ์ค์ผ๋ก ํต์ฌ์ ์ธ ๊ด์ , ๋ถ๊ฐ์ ์ธ ๊ด์ ์ผ๋ก ๋๋์ด์ ๋ณด๊ณ ๊ทธ ๊ด์ ์ ๊ธฐ์ค์ผ๋ก ๋ชจ๋ํํ๋ ๊ฒ
ํต์ฌ์ ์ธ ๊ด์ ์ ๋น์ฆ๋์ค ๋ก์ง์ผ๋ก ๋ณผ ์ ์๊ณ , ๋ถ๊ฐ์ ์ธ ๊ด์ ์ ํต์ฌ ๋ก์ง์ ์คํํ๊ธฐ ์ํด ํํด์ง๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ, ๋ก๊น , ํ์ผ ์ ์ถ๋ ฅ ๋ฑ์ด ์๋ค.
AOP์์ ๊ฐ ๊ด์ ์ ๊ธฐ์ค์ผ๋ก ๋ก์ง์ ๋ชจ๋ํํ๋ค๋ ๊ฒ์ ์ฝ๋๋ค์ ๋ถ๋ถ์ ์ผ๋ก ๋๋์ด์ ๋ชจ๋ํํ๊ฒ ๋ค๋ ์๋ฏธ์ด๋ค. ์ด๋, ์์ค ์ฝ๋์์์ ๋ค๋ฅธ ๋ถ๋ถ์ ๊ณ์ ๋ฐ๋ณตํด์ ์ฐ๋ ์ฝ๋๋ค์ ๋ฐ๊ฒฌํ ์ ์๋ ๋ฐ ์ด๊ฒ์ ํฉ์ด์ง ๊ด์ฌ์ฌ (Crosscutting Concerns)๋ผ๊ณ ํ๋ค.
์ด์ ๊ฐ์ด AOP๋ฅผ ์ฌ์ฉํ๋ฉด ์ฝ๋์ ๊ฐ๋ ์ฑ๊ณผ ์ ์ง ๋ณด์์ฑ์ ๋์ผ ์ ์๋ค.


์๋ฅผ ๋ค์ด, ์ฒซ๋ฒ์งธ ๊ทธ๋ฆผ์์ Class A, B, C์๋ ๊ณตํต์ ์ธ ๋ด์ฉ์ด ํฌํจ๋์ด ์๋ค. ์ด๋ฌํ ๊ณตํต์ ์ธ ๋ด์ฉ์ ์๊น๋ก ๊ตฌ๋ถํ์ฌ ํํํ์์ผ๋ฉฐ, ์ด๋ฌํ ๊ณตํต์ ์ธ ๋ด์ฉ์๋ ๋ฉ์๋๋ ํ๋ ๋ฑ์ด ์๋ค. ๊ณตํต์ ์ธ ๋ถ๋ถ์ด ๋ค๋ฅธ ํด๋์ค๋ค ๋ด๋ถ์ ์กด์ฌํ๋ค๋ฉด, ๊ฐ์ ๋ธ๋ก์ ์์ ํ๋๋ฐ ์ฌ๋ฌ ํด๋์ค์ ๋ธ๋ก๋ค์ ๋ฐ๋ก ์์ ํด์ผ ํ๋ ์ํฉ์ด ๋ฐ์ํ๋ค.
์ด์ ๊ฐ์ ๋ฌธ์ ๋ SOLID์์น์ ์๋ฐฐํ๋ฉฐ ์ ์ง๋ณด์๋ฅผ ์ด๋ ต๊ฒ ๋ง๋ ๋ค. ์ด๋์ ์ฃผํฉ, ํ๋, ๋นจ๊ฐ ๋ธ๋ก์ ํฉ์ด์ง ๊ด์ฌ์ฌ(Crosscutting Concerns)๋ผ๊ณ ํ๋ค. ์ด๋ฌํ ํฉ์ด์ง ๊ด์ฌ์ฌ๋ค์ ๋ชจ๋ํํ๊ณ ํด๋น ๊ธฐ๋ฅ์ด ํ์ํ ๋ธ๋ญ์ ์ ์ฉํด์ฃผ๋ ๊ฒ์ด AOP์ ์๋ฆฌ์ด๋ค. ์ด๋, ๋ชจ๋ํ ์์ผ๋์ ๋ธ๋ญ์ Aspect๋ผ๊ณ ํ๋ค.
๋๋ฒ์งธ ๊ทธ๋ฆผ์์ ๊ณ์ข์ด์ฒด, ๋์ถ์น์ธ, ์ด์๊ณ์ฐ ๋ฑ์ ํต์ฌ๋ก์ง์ ํด๋น๋๋ค๊ณ ๋ณผ ์ ์๊ณ , ๋ก๊น ์ด๋ ๋ณด์, ํธ๋์ญ์ ๋ฑ์ ๊ณตํต๋๋ ๊ธฐ๋ฅ๋ค์ ๋ถ๊ฐ ๊ธฐ๋ฅ์ด๋ผ๊ณ ๋ณผ ์ ์๋ค.
2. AOP ์ฉ์ด ์ ๋ฆฌ
1) Advice: ๋ถ๊ฐ๊ธฐ๋ฅ์ ์ํํ ๋ฉ์๋ ์์ฑ
2) Pointcut: ๋ถ๊ฐ ๊ธฐ๋ฅ์ ์ ์ฉํ ํต์ฌ๋ก์ง์ ๊ฒฐ์ ํฉ๋๋ค.
3) Aspect: ๋ถ๊ฐ ๊ธฐ๋ฅ๊ณผ ํด๋น ๋ถ๊ฐ ๊ธฐ๋ฅ์ ์ด๋์ ์ ์ฉํ ์ง ์ ์ํ ๊ฒ์ ๋๋ค. (ํด๋์ค ์์ฑ Advice + Pointcut)
4) Joinpoint : ๋ถ๊ฐ๊ธฐ๋ฅ์ด ํต์ฌ๋ก์ง ์คํ์ ์ ์คํ๋ ์ง ํ์ ์คํ๋ ์ง๋ฅผ ๊ฒฐ์ ํฉ๋๋ค.
[ex] ๋ก๊ทธ์ธ ๋ฉ์๋๊ฐ ์๋ค. ๋ฉ์๋์ ์ด๋ฆ์ login() ์ด๊ณ ์ด ๋ฉ์๋๋ ํต์ฌ๋ก์ง์ด๋ค. ๋ก๊ทธ์ธ ๋ฉ์๋๊ฐ ์คํ๋ ๋ ๋ง๋ค ๋ก๊ทธ๋ฅผ ๋จ๊ธฐ๊ณ ์ถ๋ค๋ฉด (>> ๋ถ๊ฐ๊ธฐ๋ฅ), ๋ก๊ทธ๋ฅผ ๋จ๊ธธ ๋ฉ์๋๋ฅผ ๋ง๋ค์ด์ผ ํ๋ค. ์ด๊ฒ์ ๋ถ๊ฐ๋ก์ง์ด๋ผ๊ณ ํ๋ค.
๐ฅ๏ธ ํต์ฌ๋ก์ง, ๋ถ๊ฐ๋ก์ง
login(){} // ํต์ฌ๋ก์ง
log(){ // ๋ถ๊ฐ๋ก์ง
System.out.println("๋ก๊ทธ ์คํ๋จ");
}
์ด์ ๋ถ๊ฐ๋ก์ง์ pointcut์ ์ ์ฉํ์ฌ login() ๋ฉ์๋๊ฐ ์คํ๋ ๋๋ง๋ค ๋ฐ๋ํ๊ฒ ํ๋ค.
pointcut(login()) // point cut : ๋ถ๊ฐ๋ก์ง ์คํํ ํต์ฌ๋ก์ง ๊ฒฐ์
log(){
System.out.println("๋ก๊ทธ ์คํ๋จ");
}
๋ง์ง๋ง์ผ๋ก joinpoint๋ฅผ ํตํด์ ์ธ์ ์คํ๋ ์ง ๊ฒฐ์ ํ๋ค.
Before // join point : ํต์ฌ ๋ก์ง ์ or ํ ๊ฒฐ์
pointcut(login())
log(){
System.out.println("๋ก๊ทธ ์คํ๋จ");
}
์ ๋ฐฉ์์ผ๋ก ์์ฑํ๊ฒ ๋๋ฉด join() ๋ฉ์๋๊ฐ ์คํ๋ ๋ ๋ก๊ทธ๋ฅผ ๋จ๊ธธ์๋ ์๋ค. ๊ทธ๋์ ์ด๋ ธํ ์ด์ ์ ๋ง๋๋ ๊ฒ์ด ์ข๋ค. ์๋์ ๊ฐ์ด ์ ์ฉํ๋ฉด @MyLog ์ด๋ ธํ ์ด์ ์ด ๋ถ์ด์์ผ๋ฉด ๋ก๊ทธ๊ฐ ์คํํ๋ค.
@MyLog
login(){} // login ๋ฉ์๋๊ฐ ์คํ๋ ๋
@MyLog
join(){} // join ๋ฉ์๋๊ฐ ์คํ๋ ๋
After
pointcut(@MyLog)
log(){
System.out.println("๋ก๊ทธ ์คํ๋จ");
}
3. AOP ์ ์ฉ๋ฐฉ๋ฒ 3๊ฐ์ง
1) ์ฒซ๋ฒ์งธ ๋ฐฉ๋ฒ - ์ด๋ ธํ ์ด์ ์์ฑ
- ์ด๋ ธํ ์ด์ ์ ๋ง๋ค๊ณ ๊ทธ ์๋ํ ์ด์ ์ PointCut์ผ๋ก ๋ฑ๋กํ๋ค.
- Advice๋ฅผ ๋ง๋ ๋ค. (๋ฉ์๋ ํ์)
- JoinPoint๋ฅผ ์ ์ฉํ๋ค
์์ ์์์์ ์ค๋ช ํ ๋ฐฉ๋ฒ๊ณผ ๊ฐ๋ค.
@Target(ElementType.METHOD) // method์ ๋ถ์ฐฉ๊ฐ๋ฅ
@Retention(RetentionPolicy.RUNTIME) // ๋ฐํ์ ์์ ๊น์ง ์ด๋
ธํ
์ด์
์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ฐ์ ธ๊ฐ
public @interface Hello {
}
@Aspect
@Component
public class HelloAdvice {
// ํฌ์ธํธ ์ปท์ ์ด๋
ธํ
์ด์
์ ์ ์ฉ
@Pointcut("@annotation(Hello)")
public void hello(){}
// JoinPoint ์ ์ฉ
@Before("hello()")
public void helloAdvice(JoinPoint jp) throws Throwable {
Object[] args = jp.getArgs();
if(args.length < 1){
System.out.println("์๋ฌด๊ฐ๋ ์๋
");
}
else{
for (Object arg : args) {
if(arg instanceof String){
String username = (String) arg;
System.out.println(username+"๋ ์๋
");
}
}
}
}
}
2) ๋๋ฒ์งธ ๋ฐฉ๋ฒ - PointCut๋ง ๋ฑ๋ก
- ์ด๋ฏธ ๋ง๋ค์ด์ ธ ์๋ ์ด๋ ธํ ์ด์ ์ PointCut ๋ฑ๋ก ํ๋ค.
- Advice๋ฅผ ๋ง๋ ๋ค. (๋ฉ์๋ ํ์)
- JoinPoint๋ฅผ ์ ์ฉํ๋ค
@Aspect
@Component
public class ValidAdvice {
@Pointcut("@annotation(org.springframework.web.bind.annotation.PostMapping)")
public void postMapping() {}
@Pointcut("@annotation(org.springframework.web.bind.annotation.PutMapping)")
public void putMapping() {}
@Before("postMapping() || putMapping()")
public void validationAdvice(JoinPoint jp) throws Throwable {
Object[] args = jp.getArgs();
for (Object arg : args) {
if (arg instanceof BindingResult) {
Errors errors = (Errors) arg;
if (errors.hasErrors()) {
Map<String, String> errorMap = new HashMap<>();
for (FieldError error : errors.getFieldErrors()) {
errorMap.put(error.getField(),
error.getDefaultMessage());
}
throw new MyValidationException(errorMap);
}
}
}
}
}
3) ์ธ๋ฒ์งธ ๋ฐฉ๋ฒ - ์๋ํ ์ด์ x, ํน์ ํจํด
๊น๋ฐ์ ์์ฑํ์ง ์๊ณ , ํน์ ํ ํจํด์ด ์ํ๋ ๋ ์ ์๋ advice๋ฅผ ์คํํ๊ฒ ํ ์๋ ์๋ค.
Spring Framework์์๋ XML์ ์ด์ฉํ์ฌ Aspect-Oriented Programming (AOP)์ ์ค์ ํ๋ ๋ฐฉ๋ฒ์ด ์๋ค.
๊ทธ๋ฌ๋ Spring Boot์์๋ ์ฃผ๋ก ์ด๋ ธํ ์ด์ ๊ธฐ๋ฐ์ AOP๋ฅผ ์ฌ์ฉํ๋ฉฐ, execution expression์ ์ด์ฉํ์ฌ pointcut์ ๋ฑ๋กํ ์ ์๋ค.
ํ์ง๋ง, ์ง์ ์ ์ผ๋ก execution expression์ ์ด์ฉํ์ฌ pointcut์ ๋ฑ๋กํ๋ ค๋ฉด ์ฌ๋ฌ๊ฐ์ง ์ค์ ์ ํด ์ฃผ์ด์ผ ํ๋ค. ๋์ , Spring Boot์์๋ AspectJ๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐํธํ๊ฒ pointcut์ ๋ฑ๋กํ ์ ์๋ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ค.
AspectJ๋ Java์ ๋น์ทํ ๋ฌธ๋ฒ์ ๊ฐ์ง๋ฉฐ, execution expression์ ์ด์ฉํ์ฌ pointcut์ ๋ฑ๋กํ๋ ๋ฐฉ๋ฒ์ด ์๋ค.
Execution Expression | Point Cut |
execution(* onj.spring.aop..(..)) | ํจํค์ง์ ๋ชจ๋ ๋ฉ์๋๊ฐ ํฌ์ธํธ ์ปท |
execution(* onj.spring.aop...(..)) | onj.spring.aop ํจํค์ง์ ํ์ ํจํค์ง์ ๋ชจ๋ ๋ฉ์๋๊ฐ ํฌ์ธํธ ์ปท |
execution(public void insert*(..)) | public์ ๋ฆฌํด๊ฐ, ํจํค์ง๋ช
์๊ณ ๋ฉ์๋ ์ด๋ฆ์ insert๋ก ์์, ์ธ์๊ฐ์ 0๊ฐ ์ด์์ธ ๋ฉ์๋๊ฐ ํฌ์ธํธ ์ปท |
execution(public * *(..)) | public ๋ฉ์๋๊ฐ ํฌ์ธํธ ์ปท |
execution(* onj.spring.aop..()) | ๋ฆฌํดํ ๊ด๊ณ์๊ณ onj.spring.aop ํจํค์ง์ ๋ชจ๋ ํด๋์ค, ์ธ์๊ฐ์ด ์๋ ๋ชจ๋ ๋ฉ์๋๊ฐ ํฌ์ธํธ ์ปท |
execution(* onj.spring.aop...(..)) | ๋ฆฌํดํ ๊ด๊ณ์๊ณ onj.spring.aop ํจํค์ง ๋ฐ ํ์ ํจํค์ง์ ์๋ ๋ชจ๋ ํด๋์ค, ์ธ์๊ฐ์ด 0๊ฐ ์ด์์ธ ๋ฉ์๋๊ฐ ํฌ์ธํธ ์ปท |
execution(* delete()) | ๋ฉ์๋ ์ด๋ฆ์ด delete์ผ๋ก ์์ํ๋ ์ธ์๊ฐ์ด 1๊ฐ์ธ ๋ฉ์๋๊ฐ ํฌ์ธํธ ์ปท |
execution(* delete(,*)) | ๋ฉ์๋ ์ด๋ฆ์ด delete๋ก ์์ํ๋ ์ธ์๊ฐ์ด 2๊ฐ์ธ ๋ฉ์๋๊ฐ ํฌ์ธํธ ์ปท |
ํน์ ์ด๋ ธํ ์ด์ ์ ํ๋ผ๋ฏธํฐ๋ก ์๋ ๋ฉ์๋๋ฅผ pointcut์ผ๋ก ์ก์ผ๋ ค๋ฉด, execution expression์ ์ด์ฉํ์ฌ ์ด๋ ธํ ์ด์ ์ด ์ ์ฉ๋ ๋ฉ์๋๋ฅผ ๋์์ผ๋ก pointcut์ ์์ฑํ๋ค. ๋ค๋ง, ์ด ๊ฒฝ์ฐ์๋ @annotation ๋์ ์ @args ํค์๋๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค.
4. @Before, @After, @Around
AOP์์ Before, After, Around๋ ๊ฐ๊ฐ ๋ค๋ฅธ ์์ ์์ AOP ์ด๋๋ฐ์ด์ค๋ฅผ ์คํํ๋ ๋ฐฉ๋ฒ์ด๋ค.
1. @Before
: ๋ฉ์๋ ์คํ ์ ์ ์ด๋๋ฐ์ด์ค๋ฅผ ์คํํ๋ค. ์ด ์์ ์์ JoinPoint ๊ฐ์ฒด๋ฅผ ํตํด ๋ฉ ์๋์ ์ธ์, ํด๋์ค, ๋ฉ์๋ ์ด๋ฆ ๋ฑ์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ฌ ์ ์๋ค. @Before ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ์ฌ ์ ์ธํ๋ค.
@Before("execution(* com.example.myapp.service.MyService.*(..))")
public void beforeAdvice(JoinPoint joinPoint) {
System.out.println("Before Advice: " + joinPoint.getSignature().getName());
}
@Before ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ์ฌ com.example.myapp.service.MyService ํด๋์ค์ ๋ชจ๋ ๋ฉ์๋์ ์ ์ฉ๋ ์ด๋๋ฐ์ด์ค๋ฅผ ์์ฑํ๋ค. ๋ฉ์๋ ์คํ ์ ์ ํด๋น ๋ฉ์๋์ ์๊ทธ๋์ฒ ์ ๋ณด๋ฅผ ์ถ๋ ฅํ๋ ๊ธฐ๋ฅ์ ์ํํ๋ค.
2. @After
: ๋ฉ์๋ ์คํ ํ์ ์ด๋๋ฐ์ด์ค๋ฅผ ์คํ. ์ด ์์ ์์ JoinPoint ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ ์ ์์ผ๋ฉฐ, ๋ฉ์๋์ ์คํ ๊ฒฐ๊ณผ๋ ์์ธ ์ ๋ณด ๋ฑ์ ๊ฐ์ ธ์ฌ ์ ์๋ค. @After ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ์ฌ ์ ์ธํ๋ค.
@After("execution(* com.example.myapp.service.MyService.*(..))")
public void afterAdvice(JoinPoint joinPoint) {
System.out.println("After Advice: " + joinPoint.getSignature().getName());
}
@After ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ์ฌ com.example.myapp.service.MyService ํด๋์ค์ ๋ชจ๋ ๋ฉ์๋์ ์ ์ฉ๋ ์ด๋๋ฐ์ด์ค๋ฅผ ์์ฑํ๋ค. ๋ฉ์๋ ์คํ ํ ํด๋น ๋ฉ์๋์ ์๊ทธ๋์ฒ ์ ๋ณด๋ฅผ ์ถ๋ ฅ ํ๋ ๊ธฐ๋ฅ์ ์ํํฉ๋๋ค.
3. @Around
: ๋ฉ์๋ ์คํ ์ ํ ๋ชจ๋ ์ด๋๋ฐ์ด์ค๋ฅผ ์คํํ๋ค. ์ด ์์ ์์ ProceedingJoinPoint ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ์ฌ ๋ฉ์๋ ์คํ์ ์ํํ๊ณ , ์คํ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ ์ ์๋ค. @Around ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ์ฌ ์ ์ธํ๋ฉฐ, ๋ฉ์๋ ์คํ ์ ํ์ ์ถ๊ฐ์ ์ธ ๋ก์ง์ ์ํ ํ ์ ์๋ค.
@Around("execution(* com.example.myapp.service.MyService.*(..))")
public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("Before Advice: " + joinPoint.getSignature().getName());
Object result = joinPoint.proceed();
System.out.println("After Advice: " + joinPoint.getSignature().getName());
return result;
}
@Around ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ์ฌ com.example.myapp.service.MyService ํด๋์ค ์ ๋ชจ๋ ๋ฉ์๋์ ์ ์ฉ๋ ์ด๋๋ฐ์ด์ค๋ฅผ ์์ฑํ๋ค. ๋ฉ์๋ ์คํ ์ ํ์ ํด๋น ๋ฉ์๋์ ์๊ทธ๋์ฒ ์ ๋ณด๋ฅผ ์ถ๋ ฅํ๊ณ , ๋ฉ์๋ ์คํ์ ์ํํ ํ ์คํ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํฉ๋๋ค.
์ฆ, @Before ๋ ๋ฉ์๋ ์คํ ์ ์ ์ถ๊ฐ์ ์ธ ๋ก์ง์ ์ํํ๋ ์ด๋๋ฐ์ด์ค์ด๊ณ @After ๋ ๋ฉ์๋ ์คํ ํ์ ์ถ๊ฐ์ ์ธ ๋ก์ง์ ์ํํ๋ ์ด๋๋ฐ์ด์ค์ด๋ค. @Around ๋ ๋ฉ์๋ ์คํ ์ ํ์ ์ถ๊ฐ์ ์ธ ๋ก์ง์ ์ํํ ์ ์๋ ๊ฐ์ฅ ๋ฒ์ฉ์ ์ธ ์ด๋๋ฐ์ด์ค์ ํด๋นํ๋ค.
AOP์์ ๋ฉ์๋์ ํ๋ผ๋ฏธํฐ ๊ฐ์ ๊ฒ์ฌํ๊ฑฐ๋ ๋ณ๊ฒฝํ๋ ์์ ์ ์ํํ ๋๋ @Before ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ๊ณ , ๋ฉ์๋ ์คํ ์์ ์๋ก์ด ๊ฐ์ ์ฃผ์ ํ๊ฑฐ๋, ๊ฒฐ๊ณผ๋ฅผ ๊ฐ๊ณตํ๋ ์์ ์ ์ํํ ๋๋ @Around ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ผ๋ฐ์ ์ด๋ค
์ฐธ๊ณ ์๋ฃ
1. https://code-lab1.tistory.com/193
[Spring] AOP(Aspect Oriented Programming)๋? ์คํ๋ง AOP๋?
AOP (Aspect Oriented Programming)๋? AOP๋ Aspect Oriented Programming์ ์ฝ์๋ก ๊ด์ ์งํฅ ํ๋ก๊ทธ๋๋ฐ์ด๋ผ๊ณ ๋ถ๋ฆฐ๋ค. ๊ด์ ์งํฅ์ ์ด๋ค ๋ก์ง์ ๊ธฐ์ค์ผ๋ก ํต์ฌ์ ์ธ ๊ด์ , ๋ถ๊ฐ์ ์ธ ๊ด์ ์ผ๋ก ๋๋์ด์ ๋ณด๊ณ ๊ทธ
code-lab1.tistory.com
2. https://engkimbs.tistory.com/746
[Spring] ์คํ๋ง AOP (Spring AOP) ์ด์ ๋ฆฌ : ๊ฐ๋ , ํ๋ก์ ๊ธฐ๋ฐ AOP, @AOP
| ์คํ๋ง AOP ( Aspect Oriented Programming ) AOP๋ Aspect Oriented Programming์ ์ฝ์๋ก ๊ด์ ์งํฅ ํ๋ก๊ทธ๋๋ฐ์ด๋ผ๊ณ ๋ถ๋ฆฐ๋ค. ๊ด์ ์งํฅ์ ์ฝ๊ฒ ๋งํด ์ด๋ค ๋ก์ง์ ๊ธฐ์ค์ผ๋ก ํต์ฌ์ ์ธ ๊ด์ , ๋ถ๊ฐ์ ์ธ ๊ด์ ์ผ๋ก
engkimbs.tistory.com
'๐ป cs' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[CS] APS, ์๊ฐ ๋ณต์ก๋ ์ ๋ฆฌ (1) | 2024.01.30 |
---|---|
IT ์๋น์ค, Cloud ์๋น์ค์ ๋ํด ์์๋ณด์ (0) | 2023.07.12 |
์นดํ ์ผ | 2์ฃผ์ฐจ ๊ณผ์ issue ํด๊ฒฐ (3) | 2023.07.11 |
WEB | API ์์๋ณด๊ธฐ (0) | 2023.06.29 |
GIT | GIT ์์ ์ ๋ณต (1) (0) | 2023.06.15 |
1. AOP์ ์ ์ ๋ฐ ์๋ฆฌ
AOP : ๊ด์ ์งํฅ ํ๋ก๊ทธ๋๋ฐ (Aspect Oriented Programming)
- ๊ด์ ์งํฅ์ ์ด๋ค ๋ก์ง์ ๊ธฐ์ค์ผ๋ก ํต์ฌ์ ์ธ ๊ด์ , ๋ถ๊ฐ์ ์ธ ๊ด์ ์ผ๋ก ๋๋์ด์ ๋ณด๊ณ ๊ทธ ๊ด์ ์ ๊ธฐ์ค์ผ๋ก ๋ชจ๋ํํ๋ ๊ฒ
ํต์ฌ์ ์ธ ๊ด์ ์ ๋น์ฆ๋์ค ๋ก์ง์ผ๋ก ๋ณผ ์ ์๊ณ , ๋ถ๊ฐ์ ์ธ ๊ด์ ์ ํต์ฌ ๋ก์ง์ ์คํํ๊ธฐ ์ํด ํํด์ง๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ, ๋ก๊น , ํ์ผ ์ ์ถ๋ ฅ ๋ฑ์ด ์๋ค.
AOP์์ ๊ฐ ๊ด์ ์ ๊ธฐ์ค์ผ๋ก ๋ก์ง์ ๋ชจ๋ํํ๋ค๋ ๊ฒ์ ์ฝ๋๋ค์ ๋ถ๋ถ์ ์ผ๋ก ๋๋์ด์ ๋ชจ๋ํํ๊ฒ ๋ค๋ ์๋ฏธ์ด๋ค. ์ด๋, ์์ค ์ฝ๋์์์ ๋ค๋ฅธ ๋ถ๋ถ์ ๊ณ์ ๋ฐ๋ณตํด์ ์ฐ๋ ์ฝ๋๋ค์ ๋ฐ๊ฒฌํ ์ ์๋ ๋ฐ ์ด๊ฒ์ ํฉ์ด์ง ๊ด์ฌ์ฌ (Crosscutting Concerns)๋ผ๊ณ ํ๋ค.
์ด์ ๊ฐ์ด AOP๋ฅผ ์ฌ์ฉํ๋ฉด ์ฝ๋์ ๊ฐ๋ ์ฑ๊ณผ ์ ์ง ๋ณด์์ฑ์ ๋์ผ ์ ์๋ค.


์๋ฅผ ๋ค์ด, ์ฒซ๋ฒ์งธ ๊ทธ๋ฆผ์์ Class A, B, C์๋ ๊ณตํต์ ์ธ ๋ด์ฉ์ด ํฌํจ๋์ด ์๋ค. ์ด๋ฌํ ๊ณตํต์ ์ธ ๋ด์ฉ์ ์๊น๋ก ๊ตฌ๋ถํ์ฌ ํํํ์์ผ๋ฉฐ, ์ด๋ฌํ ๊ณตํต์ ์ธ ๋ด์ฉ์๋ ๋ฉ์๋๋ ํ๋ ๋ฑ์ด ์๋ค. ๊ณตํต์ ์ธ ๋ถ๋ถ์ด ๋ค๋ฅธ ํด๋์ค๋ค ๋ด๋ถ์ ์กด์ฌํ๋ค๋ฉด, ๊ฐ์ ๋ธ๋ก์ ์์ ํ๋๋ฐ ์ฌ๋ฌ ํด๋์ค์ ๋ธ๋ก๋ค์ ๋ฐ๋ก ์์ ํด์ผ ํ๋ ์ํฉ์ด ๋ฐ์ํ๋ค.
์ด์ ๊ฐ์ ๋ฌธ์ ๋ SOLID์์น์ ์๋ฐฐํ๋ฉฐ ์ ์ง๋ณด์๋ฅผ ์ด๋ ต๊ฒ ๋ง๋ ๋ค. ์ด๋์ ์ฃผํฉ, ํ๋, ๋นจ๊ฐ ๋ธ๋ก์ ํฉ์ด์ง ๊ด์ฌ์ฌ(Crosscutting Concerns)๋ผ๊ณ ํ๋ค. ์ด๋ฌํ ํฉ์ด์ง ๊ด์ฌ์ฌ๋ค์ ๋ชจ๋ํํ๊ณ ํด๋น ๊ธฐ๋ฅ์ด ํ์ํ ๋ธ๋ญ์ ์ ์ฉํด์ฃผ๋ ๊ฒ์ด AOP์ ์๋ฆฌ์ด๋ค. ์ด๋, ๋ชจ๋ํ ์์ผ๋์ ๋ธ๋ญ์ Aspect๋ผ๊ณ ํ๋ค.
๋๋ฒ์งธ ๊ทธ๋ฆผ์์ ๊ณ์ข์ด์ฒด, ๋์ถ์น์ธ, ์ด์๊ณ์ฐ ๋ฑ์ ํต์ฌ๋ก์ง์ ํด๋น๋๋ค๊ณ ๋ณผ ์ ์๊ณ , ๋ก๊น ์ด๋ ๋ณด์, ํธ๋์ญ์ ๋ฑ์ ๊ณตํต๋๋ ๊ธฐ๋ฅ๋ค์ ๋ถ๊ฐ ๊ธฐ๋ฅ์ด๋ผ๊ณ ๋ณผ ์ ์๋ค.
2. AOP ์ฉ์ด ์ ๋ฆฌ
1) Advice: ๋ถ๊ฐ๊ธฐ๋ฅ์ ์ํํ ๋ฉ์๋ ์์ฑ
2) Pointcut: ๋ถ๊ฐ ๊ธฐ๋ฅ์ ์ ์ฉํ ํต์ฌ๋ก์ง์ ๊ฒฐ์ ํฉ๋๋ค.
3) Aspect: ๋ถ๊ฐ ๊ธฐ๋ฅ๊ณผ ํด๋น ๋ถ๊ฐ ๊ธฐ๋ฅ์ ์ด๋์ ์ ์ฉํ ์ง ์ ์ํ ๊ฒ์ ๋๋ค. (ํด๋์ค ์์ฑ Advice + Pointcut)
4) Joinpoint : ๋ถ๊ฐ๊ธฐ๋ฅ์ด ํต์ฌ๋ก์ง ์คํ์ ์ ์คํ๋ ์ง ํ์ ์คํ๋ ์ง๋ฅผ ๊ฒฐ์ ํฉ๋๋ค.
[ex] ๋ก๊ทธ์ธ ๋ฉ์๋๊ฐ ์๋ค. ๋ฉ์๋์ ์ด๋ฆ์ login() ์ด๊ณ ์ด ๋ฉ์๋๋ ํต์ฌ๋ก์ง์ด๋ค. ๋ก๊ทธ์ธ ๋ฉ์๋๊ฐ ์คํ๋ ๋ ๋ง๋ค ๋ก๊ทธ๋ฅผ ๋จ๊ธฐ๊ณ ์ถ๋ค๋ฉด (>> ๋ถ๊ฐ๊ธฐ๋ฅ), ๋ก๊ทธ๋ฅผ ๋จ๊ธธ ๋ฉ์๋๋ฅผ ๋ง๋ค์ด์ผ ํ๋ค. ์ด๊ฒ์ ๋ถ๊ฐ๋ก์ง์ด๋ผ๊ณ ํ๋ค.
๐ฅ๏ธ ํต์ฌ๋ก์ง, ๋ถ๊ฐ๋ก์ง
login(){} // ํต์ฌ๋ก์ง
log(){ // ๋ถ๊ฐ๋ก์ง
System.out.println("๋ก๊ทธ ์คํ๋จ");
}
์ด์ ๋ถ๊ฐ๋ก์ง์ pointcut์ ์ ์ฉํ์ฌ login() ๋ฉ์๋๊ฐ ์คํ๋ ๋๋ง๋ค ๋ฐ๋ํ๊ฒ ํ๋ค.
pointcut(login()) // point cut : ๋ถ๊ฐ๋ก์ง ์คํํ ํต์ฌ๋ก์ง ๊ฒฐ์
log(){
System.out.println("๋ก๊ทธ ์คํ๋จ");
}
๋ง์ง๋ง์ผ๋ก joinpoint๋ฅผ ํตํด์ ์ธ์ ์คํ๋ ์ง ๊ฒฐ์ ํ๋ค.
Before // join point : ํต์ฌ ๋ก์ง ์ or ํ ๊ฒฐ์
pointcut(login())
log(){
System.out.println("๋ก๊ทธ ์คํ๋จ");
}
์ ๋ฐฉ์์ผ๋ก ์์ฑํ๊ฒ ๋๋ฉด join() ๋ฉ์๋๊ฐ ์คํ๋ ๋ ๋ก๊ทธ๋ฅผ ๋จ๊ธธ์๋ ์๋ค. ๊ทธ๋์ ์ด๋ ธํ ์ด์ ์ ๋ง๋๋ ๊ฒ์ด ์ข๋ค. ์๋์ ๊ฐ์ด ์ ์ฉํ๋ฉด @MyLog ์ด๋ ธํ ์ด์ ์ด ๋ถ์ด์์ผ๋ฉด ๋ก๊ทธ๊ฐ ์คํํ๋ค.
@MyLog
login(){} // login ๋ฉ์๋๊ฐ ์คํ๋ ๋
@MyLog
join(){} // join ๋ฉ์๋๊ฐ ์คํ๋ ๋
After
pointcut(@MyLog)
log(){
System.out.println("๋ก๊ทธ ์คํ๋จ");
}
3. AOP ์ ์ฉ๋ฐฉ๋ฒ 3๊ฐ์ง
1) ์ฒซ๋ฒ์งธ ๋ฐฉ๋ฒ - ์ด๋ ธํ ์ด์ ์์ฑ
- ์ด๋ ธํ ์ด์ ์ ๋ง๋ค๊ณ ๊ทธ ์๋ํ ์ด์ ์ PointCut์ผ๋ก ๋ฑ๋กํ๋ค.
- Advice๋ฅผ ๋ง๋ ๋ค. (๋ฉ์๋ ํ์)
- JoinPoint๋ฅผ ์ ์ฉํ๋ค
์์ ์์์์ ์ค๋ช ํ ๋ฐฉ๋ฒ๊ณผ ๊ฐ๋ค.
@Target(ElementType.METHOD) // method์ ๋ถ์ฐฉ๊ฐ๋ฅ
@Retention(RetentionPolicy.RUNTIME) // ๋ฐํ์ ์์ ๊น์ง ์ด๋
ธํ
์ด์
์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ฐ์ ธ๊ฐ
public @interface Hello {
}
@Aspect
@Component
public class HelloAdvice {
// ํฌ์ธํธ ์ปท์ ์ด๋
ธํ
์ด์
์ ์ ์ฉ
@Pointcut("@annotation(Hello)")
public void hello(){}
// JoinPoint ์ ์ฉ
@Before("hello()")
public void helloAdvice(JoinPoint jp) throws Throwable {
Object[] args = jp.getArgs();
if(args.length < 1){
System.out.println("์๋ฌด๊ฐ๋ ์๋
");
}
else{
for (Object arg : args) {
if(arg instanceof String){
String username = (String) arg;
System.out.println(username+"๋ ์๋
");
}
}
}
}
}
2) ๋๋ฒ์งธ ๋ฐฉ๋ฒ - PointCut๋ง ๋ฑ๋ก
- ์ด๋ฏธ ๋ง๋ค์ด์ ธ ์๋ ์ด๋ ธํ ์ด์ ์ PointCut ๋ฑ๋ก ํ๋ค.
- Advice๋ฅผ ๋ง๋ ๋ค. (๋ฉ์๋ ํ์)
- JoinPoint๋ฅผ ์ ์ฉํ๋ค
@Aspect
@Component
public class ValidAdvice {
@Pointcut("@annotation(org.springframework.web.bind.annotation.PostMapping)")
public void postMapping() {}
@Pointcut("@annotation(org.springframework.web.bind.annotation.PutMapping)")
public void putMapping() {}
@Before("postMapping() || putMapping()")
public void validationAdvice(JoinPoint jp) throws Throwable {
Object[] args = jp.getArgs();
for (Object arg : args) {
if (arg instanceof BindingResult) {
Errors errors = (Errors) arg;
if (errors.hasErrors()) {
Map<String, String> errorMap = new HashMap<>();
for (FieldError error : errors.getFieldErrors()) {
errorMap.put(error.getField(),
error.getDefaultMessage());
}
throw new MyValidationException(errorMap);
}
}
}
}
}
3) ์ธ๋ฒ์งธ ๋ฐฉ๋ฒ - ์๋ํ ์ด์ x, ํน์ ํจํด
๊น๋ฐ์ ์์ฑํ์ง ์๊ณ , ํน์ ํ ํจํด์ด ์ํ๋ ๋ ์ ์๋ advice๋ฅผ ์คํํ๊ฒ ํ ์๋ ์๋ค.
Spring Framework์์๋ XML์ ์ด์ฉํ์ฌ Aspect-Oriented Programming (AOP)์ ์ค์ ํ๋ ๋ฐฉ๋ฒ์ด ์๋ค.
๊ทธ๋ฌ๋ Spring Boot์์๋ ์ฃผ๋ก ์ด๋ ธํ ์ด์ ๊ธฐ๋ฐ์ AOP๋ฅผ ์ฌ์ฉํ๋ฉฐ, execution expression์ ์ด์ฉํ์ฌ pointcut์ ๋ฑ๋กํ ์ ์๋ค.
ํ์ง๋ง, ์ง์ ์ ์ผ๋ก execution expression์ ์ด์ฉํ์ฌ pointcut์ ๋ฑ๋กํ๋ ค๋ฉด ์ฌ๋ฌ๊ฐ์ง ์ค์ ์ ํด ์ฃผ์ด์ผ ํ๋ค. ๋์ , Spring Boot์์๋ AspectJ๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐํธํ๊ฒ pointcut์ ๋ฑ๋กํ ์ ์๋ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ค.
AspectJ๋ Java์ ๋น์ทํ ๋ฌธ๋ฒ์ ๊ฐ์ง๋ฉฐ, execution expression์ ์ด์ฉํ์ฌ pointcut์ ๋ฑ๋กํ๋ ๋ฐฉ๋ฒ์ด ์๋ค.
Execution Expression | Point Cut |
execution(* onj.spring.aop..(..)) | ํจํค์ง์ ๋ชจ๋ ๋ฉ์๋๊ฐ ํฌ์ธํธ ์ปท |
execution(* onj.spring.aop...(..)) | onj.spring.aop ํจํค์ง์ ํ์ ํจํค์ง์ ๋ชจ๋ ๋ฉ์๋๊ฐ ํฌ์ธํธ ์ปท |
execution(public void insert*(..)) | public์ ๋ฆฌํด๊ฐ, ํจํค์ง๋ช
์๊ณ ๋ฉ์๋ ์ด๋ฆ์ insert๋ก ์์, ์ธ์๊ฐ์ 0๊ฐ ์ด์์ธ ๋ฉ์๋๊ฐ ํฌ์ธํธ ์ปท |
execution(public * *(..)) | public ๋ฉ์๋๊ฐ ํฌ์ธํธ ์ปท |
execution(* onj.spring.aop..()) | ๋ฆฌํดํ ๊ด๊ณ์๊ณ onj.spring.aop ํจํค์ง์ ๋ชจ๋ ํด๋์ค, ์ธ์๊ฐ์ด ์๋ ๋ชจ๋ ๋ฉ์๋๊ฐ ํฌ์ธํธ ์ปท |
execution(* onj.spring.aop...(..)) | ๋ฆฌํดํ ๊ด๊ณ์๊ณ onj.spring.aop ํจํค์ง ๋ฐ ํ์ ํจํค์ง์ ์๋ ๋ชจ๋ ํด๋์ค, ์ธ์๊ฐ์ด 0๊ฐ ์ด์์ธ ๋ฉ์๋๊ฐ ํฌ์ธํธ ์ปท |
execution(* delete()) | ๋ฉ์๋ ์ด๋ฆ์ด delete์ผ๋ก ์์ํ๋ ์ธ์๊ฐ์ด 1๊ฐ์ธ ๋ฉ์๋๊ฐ ํฌ์ธํธ ์ปท |
execution(* delete(,*)) | ๋ฉ์๋ ์ด๋ฆ์ด delete๋ก ์์ํ๋ ์ธ์๊ฐ์ด 2๊ฐ์ธ ๋ฉ์๋๊ฐ ํฌ์ธํธ ์ปท |
ํน์ ์ด๋ ธํ ์ด์ ์ ํ๋ผ๋ฏธํฐ๋ก ์๋ ๋ฉ์๋๋ฅผ pointcut์ผ๋ก ์ก์ผ๋ ค๋ฉด, execution expression์ ์ด์ฉํ์ฌ ์ด๋ ธํ ์ด์ ์ด ์ ์ฉ๋ ๋ฉ์๋๋ฅผ ๋์์ผ๋ก pointcut์ ์์ฑํ๋ค. ๋ค๋ง, ์ด ๊ฒฝ์ฐ์๋ @annotation ๋์ ์ @args ํค์๋๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค.
4. @Before, @After, @Around
AOP์์ Before, After, Around๋ ๊ฐ๊ฐ ๋ค๋ฅธ ์์ ์์ AOP ์ด๋๋ฐ์ด์ค๋ฅผ ์คํํ๋ ๋ฐฉ๋ฒ์ด๋ค.
1. @Before
: ๋ฉ์๋ ์คํ ์ ์ ์ด๋๋ฐ์ด์ค๋ฅผ ์คํํ๋ค. ์ด ์์ ์์ JoinPoint ๊ฐ์ฒด๋ฅผ ํตํด ๋ฉ ์๋์ ์ธ์, ํด๋์ค, ๋ฉ์๋ ์ด๋ฆ ๋ฑ์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ฌ ์ ์๋ค. @Before ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ์ฌ ์ ์ธํ๋ค.
@Before("execution(* com.example.myapp.service.MyService.*(..))")
public void beforeAdvice(JoinPoint joinPoint) {
System.out.println("Before Advice: " + joinPoint.getSignature().getName());
}
@Before ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ์ฌ com.example.myapp.service.MyService ํด๋์ค์ ๋ชจ๋ ๋ฉ์๋์ ์ ์ฉ๋ ์ด๋๋ฐ์ด์ค๋ฅผ ์์ฑํ๋ค. ๋ฉ์๋ ์คํ ์ ์ ํด๋น ๋ฉ์๋์ ์๊ทธ๋์ฒ ์ ๋ณด๋ฅผ ์ถ๋ ฅํ๋ ๊ธฐ๋ฅ์ ์ํํ๋ค.
2. @After
: ๋ฉ์๋ ์คํ ํ์ ์ด๋๋ฐ์ด์ค๋ฅผ ์คํ. ์ด ์์ ์์ JoinPoint ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ ์ ์์ผ๋ฉฐ, ๋ฉ์๋์ ์คํ ๊ฒฐ๊ณผ๋ ์์ธ ์ ๋ณด ๋ฑ์ ๊ฐ์ ธ์ฌ ์ ์๋ค. @After ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ์ฌ ์ ์ธํ๋ค.
@After("execution(* com.example.myapp.service.MyService.*(..))")
public void afterAdvice(JoinPoint joinPoint) {
System.out.println("After Advice: " + joinPoint.getSignature().getName());
}
@After ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ์ฌ com.example.myapp.service.MyService ํด๋์ค์ ๋ชจ๋ ๋ฉ์๋์ ์ ์ฉ๋ ์ด๋๋ฐ์ด์ค๋ฅผ ์์ฑํ๋ค. ๋ฉ์๋ ์คํ ํ ํด๋น ๋ฉ์๋์ ์๊ทธ๋์ฒ ์ ๋ณด๋ฅผ ์ถ๋ ฅ ํ๋ ๊ธฐ๋ฅ์ ์ํํฉ๋๋ค.
3. @Around
: ๋ฉ์๋ ์คํ ์ ํ ๋ชจ๋ ์ด๋๋ฐ์ด์ค๋ฅผ ์คํํ๋ค. ์ด ์์ ์์ ProceedingJoinPoint ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ์ฌ ๋ฉ์๋ ์คํ์ ์ํํ๊ณ , ์คํ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ ์ ์๋ค. @Around ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ์ฌ ์ ์ธํ๋ฉฐ, ๋ฉ์๋ ์คํ ์ ํ์ ์ถ๊ฐ์ ์ธ ๋ก์ง์ ์ํ ํ ์ ์๋ค.
@Around("execution(* com.example.myapp.service.MyService.*(..))")
public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("Before Advice: " + joinPoint.getSignature().getName());
Object result = joinPoint.proceed();
System.out.println("After Advice: " + joinPoint.getSignature().getName());
return result;
}
@Around ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ์ฌ com.example.myapp.service.MyService ํด๋์ค ์ ๋ชจ๋ ๋ฉ์๋์ ์ ์ฉ๋ ์ด๋๋ฐ์ด์ค๋ฅผ ์์ฑํ๋ค. ๋ฉ์๋ ์คํ ์ ํ์ ํด๋น ๋ฉ์๋์ ์๊ทธ๋์ฒ ์ ๋ณด๋ฅผ ์ถ๋ ฅํ๊ณ , ๋ฉ์๋ ์คํ์ ์ํํ ํ ์คํ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํฉ๋๋ค.
์ฆ, @Before ๋ ๋ฉ์๋ ์คํ ์ ์ ์ถ๊ฐ์ ์ธ ๋ก์ง์ ์ํํ๋ ์ด๋๋ฐ์ด์ค์ด๊ณ @After ๋ ๋ฉ์๋ ์คํ ํ์ ์ถ๊ฐ์ ์ธ ๋ก์ง์ ์ํํ๋ ์ด๋๋ฐ์ด์ค์ด๋ค. @Around ๋ ๋ฉ์๋ ์คํ ์ ํ์ ์ถ๊ฐ์ ์ธ ๋ก์ง์ ์ํํ ์ ์๋ ๊ฐ์ฅ ๋ฒ์ฉ์ ์ธ ์ด๋๋ฐ์ด์ค์ ํด๋นํ๋ค.
AOP์์ ๋ฉ์๋์ ํ๋ผ๋ฏธํฐ ๊ฐ์ ๊ฒ์ฌํ๊ฑฐ๋ ๋ณ๊ฒฝํ๋ ์์ ์ ์ํํ ๋๋ @Before ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ๊ณ , ๋ฉ์๋ ์คํ ์์ ์๋ก์ด ๊ฐ์ ์ฃผ์ ํ๊ฑฐ๋, ๊ฒฐ๊ณผ๋ฅผ ๊ฐ๊ณตํ๋ ์์ ์ ์ํํ ๋๋ @Around ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ผ๋ฐ์ ์ด๋ค
์ฐธ๊ณ ์๋ฃ
1. https://code-lab1.tistory.com/193
[Spring] AOP(Aspect Oriented Programming)๋? ์คํ๋ง AOP๋?
AOP (Aspect Oriented Programming)๋? AOP๋ Aspect Oriented Programming์ ์ฝ์๋ก ๊ด์ ์งํฅ ํ๋ก๊ทธ๋๋ฐ์ด๋ผ๊ณ ๋ถ๋ฆฐ๋ค. ๊ด์ ์งํฅ์ ์ด๋ค ๋ก์ง์ ๊ธฐ์ค์ผ๋ก ํต์ฌ์ ์ธ ๊ด์ , ๋ถ๊ฐ์ ์ธ ๊ด์ ์ผ๋ก ๋๋์ด์ ๋ณด๊ณ ๊ทธ
code-lab1.tistory.com
2. https://engkimbs.tistory.com/746
[Spring] ์คํ๋ง AOP (Spring AOP) ์ด์ ๋ฆฌ : ๊ฐ๋ , ํ๋ก์ ๊ธฐ๋ฐ AOP, @AOP
| ์คํ๋ง AOP ( Aspect Oriented Programming ) AOP๋ Aspect Oriented Programming์ ์ฝ์๋ก ๊ด์ ์งํฅ ํ๋ก๊ทธ๋๋ฐ์ด๋ผ๊ณ ๋ถ๋ฆฐ๋ค. ๊ด์ ์งํฅ์ ์ฝ๊ฒ ๋งํด ์ด๋ค ๋ก์ง์ ๊ธฐ์ค์ผ๋ก ํต์ฌ์ ์ธ ๊ด์ , ๋ถ๊ฐ์ ์ธ ๊ด์ ์ผ๋ก
engkimbs.tistory.com
'๐ป cs' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[CS] APS, ์๊ฐ ๋ณต์ก๋ ์ ๋ฆฌ (1) | 2024.01.30 |
---|---|
IT ์๋น์ค, Cloud ์๋น์ค์ ๋ํด ์์๋ณด์ (0) | 2023.07.12 |
์นดํ ์ผ | 2์ฃผ์ฐจ ๊ณผ์ issue ํด๊ฒฐ (3) | 2023.07.11 |
WEB | API ์์๋ณด๊ธฐ (0) | 2023.06.29 |
GIT | GIT ์์ ์ ๋ณต (1) (0) | 2023.06.15 |