
spring-aop 추가aspectJ 추가(이미 있음)<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>		
		


->

	<!-- @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가 붙는다!!
@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~~");
	}
	
}


@Before)에 자기가 할 거 하고("target(대상)") : 대상에 클래스 또는 인터페이스 지정@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 ==============");
	}
	
}


@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~~~";
	}
}
@Service
@Slf4j
public class MyService {
	@Autowired
	private MyDao dao;
	
	public void test() {
		log.info("test method called...");
		dao.test();
	}
	
}
@Repository
@Slf4j
public class MyDao {
	@Autowired
	private SqlSession session;
	
	public void test() {
		log.info("test method called...");
	}
}

	@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(대상)
	 * 리턴타입 : 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;
	}
	

//	@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(대상)" : 대상에 표현식(접근제한자 반환형 패키지명.클래스명.메소드명(매개변수))
public : 생략 가능
리턴타입에 * : 리턴타입 상관없으면
매개변수에 * : 매개변수 1개 이상
매개변수에 .. : 매개변수 0개 이상
	@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;
	}

//	@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;
	}
	
