스프링19_AOP
AOP
- 관점 지향 프로그래밍
- aspectJ 를 사용하기 위해
spring-aop
추가
-> 그후aspectJ
추가(이미 있음)
pom.xml
- weaving : 완성된 코드에 내가 원하는 코드를 집어넣는 것
<org.aspectj-version>1.9.7</org.aspectj-version>
...
...
<!-- spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- AspectJ -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
root-context.xml
->
<!-- @Aspect 사용할 수 있도록 -->
<aop:aspectj-autoproxy/>
<!-- servlet-context 에서 이미 사용중?이기 때문에 false -->
<context:component-scan base-package="com.kh.app24" use-default-filters="false">
<context:include-filter type="annotation" expression="org.aspectj.lang.annotation.Aspect"/>
</context:component-scan>
- 이러면 이제
@Asepct
를 사용한 클래스에S
가 붙는다!!
MyAspect
@EnableAspectJAutoProxy
@Component
@Aspect
@Slf4j
public class MyAspect {
//advice, 조인포인트, 포인트컷
//이 안에서 사용할 메소드를 advice라고 명명한다.
//언제 : HomeController가 실행되기 전에 : @Before
//대상 : "target(대상)"
@Before("target(com.kh.app24.HomeController)")
public void myAdvice01() {
log.info("myAdvice01 called~~");
}
}
원리?
- 프록시 : HomeController를 감싸는 큰 네모가 프록시
- 프록시 안에 myAdvice01()
- home요청을 보내면 home으로 바로 가는 게 아니라 프록시로 감
- ✨프록시가 요청을 대신 해줌 && 대신 그전(
@Before
)에 자기가 할 거 하고
1) 언제
- @Before
- @After : 에러가 나든 말든
- @Around : before+after
- @AfterReturning : ??
- @AfterThrowing : 에러가 나면 aop 실행
2) 대상
("target(대상)")
: 대상에 클래스 또는 인터페이스 지정- within : 패키지 또는 클래스 지정
- execution : 표현식(접근제한자 반환형 패키지명.클래스명.메소드명(매개변수))
@EnableAspectJAutoProxy
@Component
@Aspect
@Slf4j
public class MyAspect {
//advice, 조인포인트, 포인트컷
//이 안에서 사용할 메소드를 advice라고 명명한다.
//언제 : HomeController가 실행되기 전에 : @Before
//대상 : "target(대상)"
@Before("target(com.kh.app24.HomeController)")
public void myAdvice01() {
log.info("Before =============");
}
@After("target(com.kh.app24.HomeController)")
public void myAdvice02() {
log.info("After ==============");
}
}
My
MyController
@Controller
@RequestMapping("my")
@Slf4j
public class MyController {
@Autowired
private MyService service;
@GetMapping("test")
@ResponseBody
public String test() {
log.info("test method called...");
service.test();
return "test~~~";
}
}
MyService
@Service
@Slf4j
public class MyService {
@Autowired
private MyDao dao;
public void test() {
log.info("test method called...");
dao.test();
}
}
MyDao
@Repository
@Slf4j
public class MyDao {
@Autowired
private SqlSession session;
public void test() {
log.info("test method called...");
}
}
실습
MyService 전후에 하나씩 해보자
@Before("target(com.kh.app24.aop.service.MyService)")
public void myAdvice03() {
log.info("MyService 클래스 실행 이전~~");
}
@After("target(com.kh.app24.aop.service.MyService)")
public void myAdvice04() {
long time = System.currentTimeMillis();
log.info("현재시간(ms) ::: {}", time);
}
@Before("target(com.kh.app24.aop.service.MyService)")
public void myAdvice03() {
log.info("MyService 클래스 실행 이전~~");
}
@After("target(com.kh.app24.aop.service.MyService)")
public void myAdvice04() {
long time = System.currentTimeMillis();
log.info("현재시간(ms) ::: {}", time);
}
@Around
/* @Around(대상)
* 리턴타입 : Object
* 파라미터 : ProceedingJoinPoint
* 예외 : Throwable
* Before, After 둘다 간섭 가능
* */
@Around("target(com.kh.app24.aop.service.MyService)")
public Object myAdvice05(ProceedingJoinPoint jp) throws Throwable {
//before
long start = System.currentTimeMillis();
//타겟 메소드 호출
Object obj = jp.proceed();
//after
long end = System.currentTimeMillis();
long elapse = end - start;
log.info("elapse : {}", elapse);
return obj;
}
within
- "within(대상)" : 대상에 패키지 또는 클래스 지정
// @Around("target(com.kh.app24.aop.service.MyService)")
// @Around("target(com.kh.app24.aop.dao.MyDao)")
@Around("within(com.kh.app24.aop..*)")
// @Around("within(com..*)")
public Object myAdvice05(ProceedingJoinPoint jp) throws Throwable {
System.out.println("elapse check start ==========com.kh.app24.aop..");
//before
long start = System.currentTimeMillis();
// long start = System.nanoTime();
//타겟 메소드 호출
Object obj = jp.proceed();
//after
long end = System.currentTimeMillis();
long elapse = end - start;
log.info("elapse : {}", elapse);
return obj;
}
execution
-
"execution(대상)" : 대상에 표현식(접근제한자 반환형 패키지명.클래스명.메소드명(매개변수))
-
public : 생략 가능
-
리턴타입에
*
: 리턴타입 상관없으면 -
매개변수에
*
: 매개변수 1개 이상 -
매개변수에
..
: 매개변수 0개 이상
1)
@Around("execution(public void com.kh.app24.aop.dao.MyDao.test())")
public Object myAdvice05(ProceedingJoinPoint jp) throws Throwable {
System.out.println("elapse check start ==========com.kh.app24.aop..");
//before
long start = System.currentTimeMillis();
// long start = System.nanoTime();
//타겟 메소드 호출
Object obj = jp.proceed();
//after
long end = System.currentTimeMillis();
long elapse = end - start;
log.info("elapse : {}", elapse);
return obj;
}
2)
// @Around("execution(public void com.kh.app24.aop.dao.MyDao.test())")
//public 은 생략 가능
//리턴타입 상관없으면 *
//매개변수에 * : 매개변수 1개 이상
//매개변수에 .. : 매개변수 0개 이상
//패키지명, 클래스명, 메소드명 : 표현식으로 처리 가능
// @Around("execution(* com.kh.app24.aop.dao.MyDao.select*(..))")
// @Around("execution(* com.kh.app24.aop.dao.MyDao.te*(..))")
// @Around("execution(* com.kh.app24.aop.dao.MyDao.*st(..))")
// @Around("execution(* com.kh.app24.aop.dao.*Dao.*(..))")
// @Around("execution(* com.kh.app24..*.*(..))")
// @Around("execution(* com..*Dao*.*(..))")
@Around("execution(* com..*.*(..))")
public Object myAdvice05(ProceedingJoinPoint jp) throws Throwable {
System.out.println("elapse check start ==========com.kh.app24.aop..");
//before
long start = System.currentTimeMillis();
// long start = System.nanoTime();
//타겟 메소드 호출
Object obj = jp.proceed();
//after
long end = System.currentTimeMillis();
long elapse = end - start;
log.info("elapse : {}", elapse);
return obj;
}
Author And Source
이 문제에 관하여(스프링19_AOP), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@lecharl/스프링19저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)