AOP(4) - AspectJ
Last updated
Was this helpful?
Last updated
Was this helpful?
Was this helpful?
AspectJ๋ ์์ Spring AOP API์์ ์ ๊ณตํ์ง ์์ ํ๋์ ๋ํ Advisor๋ฅผ ์ง์ํ๊ณ , CTW(Compile Time Weaving), LTW(Load Time Weaving)๊ณผ ๊ฐ์ ๋ค์ํ ์๋น ๋ฐฉ๋ฒ์ ์ ๊ณตํด ํ๋ก๊ทธ๋จ์ ํผํฌ๋จผ์ค๋ฅผ ํฅ์ ์ํฌ ์ ์๋๋ก ํด์ค๋ค.
๋ํ @Aspect
์ด๋
ธํ
์ด์
์ ๋ฐํ์ผ๋ก ๋ก์ง์ ์์ฑํ ์ ์์ด, xml ๋ฐฉ์๋ณด๋ค๋ ๋ ํธ๋ฆฌํ๋ค.
Weaving์ Aspect ํด๋์ค์ ์ ์ ํ Advice ๋ก์ง์ ํ๊ฒ์ ์ ์ฉํ๋ ๊ฒ์ ์๋ฏธํ๋ฉฐ, RTW, CTW, LTW 3๊ฐ์ง๊ฐ ์๋ค.
Spring AOP์์ ์ฌ์ฉํ๋ ๋ฐฉ์์ผ๋ก, Proxy๋ฅผ ์์ฑํด ์ค์ ํ๊น ์ค๋ธ์ ํธ์ ๋ณํ์์ด ์๋น์ ์ํํ๋ค. ์ค์ ๋ฐํ์์ Method ํธ์ถ ์์ ์๋น์ด ์ด๋ฃจ์ด์ง๋ ๋ฐฉ์์ด๋ค.
์์คํ์ผ, ํด๋์ค ํ์ผ์ ๋ณํ์ด ์๋ค๋ ์ฅ์ ์ด ์์ง๋ง, Point Cut์ ๋ํ Advice ์๊ฐ ๋์ด๋ ์๋ก ์ฑ๋ฅ์ด ๋จ์ด์ง๋ค๋ ๋จ์ ์ด ์๋ค.
AspectJ์๋ AJC (AspectJ Compiler)๋ผ๋ ์ปดํ์ผ๋ฌ๊ฐ ์๋๋ฐ Java Compiler๋ฅผ ํ์ฅํ ํํ์ ์ปดํ์ผ๋ฌ์ด๋ค. AJC๋ฅผ ํตํด javaํ์ผ์ ์ปดํ์ผ ํ๋ฉฐ, ์ปดํ์ผ ๊ณผ์ ์์ ๋ฐ์ดํธ ์ฝ๋ ์กฐ์์ ํตํด Advisor ์ฝ๋๋ฅผ ์ง์ ์ฝ์ ํ์ฌ ์๋น์ ์ํํ๋ค. ์ฅ์ ์ผ๋ก๋ 3๊ฐ์ง ์๋น ์ค์์๋ ๊ฐ์ฅ ๋น ๋ฅธ ํผํฌ๋จผ์ค๋ฅผ ๋ณด์ฌ์ค๋ค. ํ์ง๋ง ์ปดํ์ผ ๊ณผ์ ์์ lombok๊ณผ ๊ฐ์ด ์ปดํ์ผ ๊ณผ์ ์์ ์ฝ๋๋ฅผ ์กฐ์ํ๋ ํ๋ฌ๊ทธ์ธ๊ณผ ์ถฉ๋์ด ๋ฐ์ํ ๊ฐ๋ฅ์ฑ์ด ์์ฃผ ๋๋ค. (๊ฑฐ์ ๊ฐ์ด ์ฌ์ฉ ๋ถ๊ฐ)
ClassLoader๋ฅผ ์ด์ฉํด ํด๋์ค๊ฐ JVM์ ๋ก๋๋ ๋ ๋ฐ์ดํธ ์ฝ๋ ์กฐ์์ ํตํด ์๋น๋๋ ๋ฐฉ์์ผ๋ก ์ปดํ์ผ ์๊ฐ์ ์๋์ ์ผ๋ก CTW๋ณด๋ค ์งง๋ค. ํ์ง๋ง ์ค๋ธ์ ํธ๊ฐ ๋ฉ๋ชจ๋ฆฌ์ ์ฌ๋ผ๊ฐ๋ ๊ณผ์ ์์ ์๋น์ด ์ผ์ด๋๊ธฐ๋๋ฌธ์ ๋ฐํ์์ ์๊ฐ์ CTW๋ณด๋ค ์๋์ ์ผ๋ก ๋๋ฆฌ๋ค.
Application Context์ ๊ฐ์ฒด๊ฐ ๋ก๋๋ ๋, ๊ฐ์ฒด ํธ๋ค๋ง์ด ๋ฐ์ํ๋ฏ๋ก ํผํฌ๋จผ์ค๊ฐ ์ ํ๋๋ค.
Annotatoin
์ค๋ช
@Before
๋ฉ์๋ ์คํ ์ด์ ๋ถ๋ถ์ ๋ํ JoinPoint ์ค์
@Around
๋ฉ์๋ ์คํ ์ /ํ์ JoinPoint ์ค์
@After
๋ฉ์๋ ์คํ ์ดํ ๋ถใด์ ๋ํ JoinPoint์ค์
@AfterReturning
return ์คํ ์ดํ ๋ถ๋ถ์ ๋ํ JoinPoint ์ค์
@AfterThrowable
๋ฉ์๋ ์คํ์, Throw ์ดํ ๋ถ๋ถ์ ๋ํ Joinpoint ์ค์
์ ๊ทผ ์ ์ด์ ํจํด(public or protected)
*
์ธ ๊ฒฝ์ฐ(or ์๋ต) ๋ชจ๋ ์ ๊ทผ ์ ์ด์์ ๋ํด ์ค์ ๊ฐ๋ฅ
๋ฆฌํดํ์ : ๋ฉ์๋์ ๋ฆฌํดํ์ ์ ์ง์ (ํด๋น ํ์ ์ผ๋ก ๋ฆฌํด๋๋ ๋ชจ๋ ๋ฉ์๋์ ๋ํ point cut)
ํ์ ๊ธฐ์ฌ
Class ํ์ : ํด๋์ค ํ์ ํจํด(ํด๋น ํด๋์ค์ ๋ํ ๋ชจ๋ ๋ฉ์๋์ ๋ํด Point cut)
ํจํค์ง ๋ช ๋ ๊ธฐ์ฌ ํ์
ํ์ ๊ธฐ์ฌ
๋ฉ์๋ ๋ช : ํน์ ํด๋์ค ๋๋ ํจํค์ง ํ์์ ๋ฉ์๋ ๋ช ์ ๋ํด Point Cut
ํ์ ๊ธฐ์ฌ
์์ธํ์ : ์์ธ ํด๋์ค์ ๋ํด์ Jointpoint ์ค์ ๊ฐ๋ฅ
์คํ๋ง์ 3๊ฐ์ง ๋ฐฉ์์ผ๋ก AOP๋ฅผ ์ ๊ณตํ๋ค.
XML ์คํค๋ง ๊ธฐ๋ฐ์ POJOํด๋์ค๋ฅผ ์ด์ฉํ AOP ๊ตฌํ
AspectJ์์ ์ ์ํ @Aspect ์ด๋ ธํ ์ด์ ๊ธฐ๋ฐ์ AOP ๊ตฌํ
์ด์ค์์ @Aspect
์ด๋
ธํ
์ด์
๊ธฐ๋ฐ์ AOP ๊ตฌํ์ ์๋ก ๊ตฌํํด๋ณผ ๊ฒ์ด๋ค.
maven(pom.xml
) ์ค์
<!-- aop aspectj -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
@EnableAspectJAutoProxy ์ ์ฉ : ์ต์์ ํจํค์ง์ ํด๋์ค์ ์ ์ฉํด AOP๋ฅผ ์ฐพ์ ์ ์๊ฒํด์ค๋ค.
package com.example.practiceAop;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@EnableAspectJAutoProxy
@SpringBootApplication
public class PracticeAopApplication {
public static void main(String[] args) {
SpringApplication.run(PracticeAopApplication.class, args);
}
}
๊ณตํต๊ธฐ๋ฅ ์ ์ ๋ฐ ์์ ์ ์(๋ก๊ทธ ์ ์ฉ)
package com.example.practiceAop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
/**
* LoggerAspect
*
* pointcut ๊ธฐ์ค์ผ๋ก Log ๊ธฐ๋ก
* @Aspect : ๋ถ๊ฐ๊ธฐ๋ฅ ๋ชจ๋, ํต์ฌ๊ธฐ๋ฅ์ ๋ถ๊ฐ๋์ด ์๋ฏธ๋ฅผ ๊ฐ๋ ํน๋ณํ ๋ชจ๋(Pointcut + Advice)
* Advice : ์ค์ ๋ก ๋ถ๊ฐ๊ธฐ๋ฅ์ ๋ด์ ๊ตฌํ์ฒด
* PointCut : ๋ณต์์ ์กฐ์ธ ํฌ์ธํธ๋ฅผ ํ๋๋ก ๋ฌถ์ ๊ฒ
* JoinPoint : Advice๊ฐ ์ ์ฉ๋ ์์น
*/
@Aspect
@Component
public class LoggerAspect {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
// AOP Point Cut
// Controller, ServiceImpl, Repository ๊ธฐ์ค์ผ๋ก ๋ก๊ทธ ์ถ๋ ฅ
@Around("execution(* com.example.practiceAop.controller.*Controller.*(..)) or execution(* com.example.practiceAop.service.impl.*Impl.*(..)) or execution(* com.example.practiceAop.repository.*Repository.*(..))")
public Object printLog(ProceedingJoinPoint joinPoint) throws Throwable {
String type = "";
String name = joinPoint.getSignature().getDeclaringTypeName(); // ์คํ๋๋ ๋์ ๋ฉ์๋ ์ ๋ณด
if (name.contains("Controller") == true) {
type = "Controller ===> ";
}else if (name.contains("Service") == true) {
type = "ServiceImpl ===> ";
}else if (name.contains("Repository") == true) {
type = "Repository ===> ";
}
logger.info(type + name + "." + joinPoint.getSignature().getName() + "( )" );
return joinPoint.proceed();
}
}
@Pointcut
Pointcut์ ๋ํ ํํ์์ ๊ฐ์ง๋ฉฐ, @Pointcut์ด ์ ์ฉ๋ ๋ฉ์๋๋ ๋ฐ๋์ ๋ฆฌํดํ์ ์ด void์ฌ์ผํ๋ค.