Spring-Annotaion,AOP
Annotation
AOP를 들어가기 앞서 사전지식이 필요한 개념이다.
Annotaion으로 인하여 데이터의 유효성 검사 등을 쉽게 할 수 있고, 이에 관련된 코드가 깔끔해지게 된다.
Annotaion으로 인하여 AOP를 편리하게 구성할 수 있게 하며 실제 데이터가 아닌 Data를 위한 데이터, 즉, Meta Data이다.
Java의 기본적인 Annotation
Annotaion | 설명 |
@Override |
|
@Deprecated |
|
@Suppress Warnings |
|
@SafeVarargs |
|
@FunctionalInterface |
|
Meta Annotation
Annotaion | 설명 |
@Retention |
|
@Target |
|
@Documented |
|
@Inherited |
|
@Repeatable |
|
Spring Annotation
Annotaion | 설명 |
@Component |
|
@RequestMapping |
|
@Required |
|
@Autowired |
|
@Qualifier |
|
@RequestParam |
|
@Path Variable |
|
@RequestBody |
|
@ModelAttribute |
|
AOP(Aspect Oriented Programming)
AOP란 관점지향 프로그래밍 이다.
공통적인 기능을 모든 모듈에 적용하기 위한 방법으로 상속을 이용한다.
JAVA에서는 다중상속이 불가능하기 때문에 AOP로서 한계를 극복한다.
이러한 AOP의 핵심기능은 공통 기능을 분리시키고 공통 기능을 필요로 하는 기능들에서 사용하는 방식이다.
AOP Annotaion
구성 요소 | 설명 |
JoinPoint | 관심 모듈의 기능이 삽입되어 동잘 할 수 있는 실행 가능한 특정 위치 |
Pointcut | 어떤 클래스의 어느 조인포인트를 사용할 것인지를 선택 가능 |
Weaving | 포인트컷에 의해서 결정된 조인포인트에 지정된 어드바이스를 삽입하는 과정 |
Aspect | Pointcut에서 Advice를 할 것인지 |
그림참조:I’s Stroy 블로그
init.xml
AOP를 사용하기 위한 환경 설정 이다.
<
aop:aspectj-autoproxy
/>: Java AOP를 사용하기 위하여 선언
<
context:component-scan base-package=”pack”
/>: 일일이 Bean을 등록하지 않고 사용하기 위하여 선언
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
<context:component-scan base-package="pack" />
<aop:aspectj-autoproxy />
</beans>
pack.model
DB와 연관되는 작업을 하는 곳이다.
ArticleInter: Interface를 사용하여 공동 작업시 충돌 방지
ArticleDAO: 실제 DB와 연결하여 작업(현재는 DB와 연결되어 있지 않으므로 간단한 출력형식을 사용하였다.)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//ArticleInter
package pack.model;
public interface ArticleInter {
void selectAll();
}
//ArticleDao
package pack.model;
import org.springframework.stereotype.Repository;
@Repository("articleDao")
public class ArticleDao implements ArticleInter{
@Override
public void selectAll() {
System.out.println("직원 테이블 전체자료 조사");
}
}
pack.BL
실제 Logic이 구현되는 곳이다.
LogicInter: Interface를 사용하여 공동 작업시 충돌 방지
LogicImpl: 실제 Logic이 실행되는 곳이다.
- Qualifier를 통하여 ArticleDao를 객체화 하여 사용
- articleInter.selectAll()를 통하여 DB와 연동되어 작업 Main: 실제 수행을 위하여 실행을 하는 곳
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
//LogicInter
package pack.BL;
public interface LogicInter {
void selectdataProcess();
}
//LogicImpl
package pack.BL;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import pack.model.ArticleInter;
@Service
public class LogicImpl implements LogicInter {
@Autowired
@Qualifier("articleDao")
private ArticleInter articleInter;
@Override
public void selectdataProcess() {
System.out.println("selectdataProcess 작업하는 중...");
articleInter.selectAll();
}
}
//Main
package pack.BL;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("init.xml");
LogicInter inter = context.getBean("logicImpl",LogicInter.class);
inter.selectdataProcess();
}
}
pack.Aspect
AOP를 사용하는 곳 이다.
ASPECT는 다음과 같은 형태로 정리될 수 있다.
// AspectJ의 Pointcut 표현식 정리
execution([접근자제어패턴], 리턴타입패턴 [패키지패턴]메서드이름패턴(파라메터패턴)) [ ] 안의 패턴은 생략 가능
execution(public void set*(..))
public에 리턴값이 없으며, 패키지명은 없고, 메서드는 set으로 시작하며 인자값은 0개 이상인 메서드 호출
execution(* com.people.*.*())
리턴타입에 상관없이 com.people패키지의 인자값이 없는 모든 메서드 호출
execution(* com.people..*.*(..))
리턴타입에 상관없이 com.people 패키지 및 하위 패키지에 있는, 인자값이 0개 이상인 메서드 호출
execution(Integer com.people.WriteService.write(..))
리턴 타입이 Integer인 WriteServlce의 인자값이 0개 이상인 write() 호출
execution(* get*(*))
메서드 이름이 get으로 시작하는 인자값이 1개인 메서드 호출
execution(* get*(*,*))
메서드 이름이 get으로 시작하는 인자값이 2개인 메서드 호출
execution(* get*(Integer, ..))
메서드 이름이 get으로 시작하고 첫번째 인자값의 데이터타입이 Integer이며, 1개 이상의 인자값을 갖는 메서드 호출
execution(* com..*(..)) && @annotation(@annotation)
@annotation이 있는 모든 메소드 호출
execution(* *(..,@annotation (*), ..))
@annotation을 파라메터로 갖고 있는 모든 메소드 호출
@Around(“execution(public * pack.BL..*
(
.
.
)
)
“)를 통하여 pack.BL에서 어떤한 작업이 일어날 경우 잡아오는 역할을 한다.
System.out.println(“Hello CheckPoint1”); => 작업 수행전 실행
Object object = joinPoint1.proceed(); => 잡아온 작업 수행
System.out.println(“Hello CheckPoint2”); => 작업 수행 후 실행
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package pack.Aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class OurAdvice {
@Around("execution(public * pack.BL..*(..))")
public Object kbs(ProceedingJoinPoint joinPoint1) throws Throwable {
System.out.println("Hello CheckPoint1");
Object object = joinPoint1.proceed();
System.out.println("Hello CheckPoint2");
return object;
}
}
실행결과
내용참조:I’s Story 블로그
내용참조:MHLab 블로그
내용참조:gmlwjd9405 블로그
내용참조:천프로 블로그
참조:원본코드
코드에 문제가 있거나 궁금한 점이 있으면 wjddyd66@naver.com으로 Mail을 남겨주세요.
Leave a comment