AOP ( Aspect Oriented Programming , 관점(관심) 지향적인 프로그래밍 )
- OOP(Object Oriented Programming, 객체지향프로그래밍)를 보완하는 확장적인 개념
- Aspect(측면, 관점, 관심) : 핵심적인 비즈니스 로직은 아니지만 반드시 해야 하는 작업들
- 관심의 분리(Separation of Concerns)를 통해 핵심관점(업무로직) + 횡단관점(트랜잭션,로그,보안,인증 처리 등)으로 관심의 분리를 실현
- 장점 : 중복되는 코드 제거, 효율적인 유지 보수, 높은 생산성, 재활용성 극대화, 변화 수용의 용이성
?
* AOP의 주요 용어
- Aspect : 공통 관심사(로깅, 보안, 트랜잭션 등)
- Join Points : method를 호출하는 시점, 예외가 발생하는 시점 등과 같이 특정 작업이 실행되는 시점을 의미함
- Advice : Join Points에서 실행되어야 하는 코드(실제로 AOP 기능을 구현한 객체)
- Pointcuts : 실제로 Advice를 적용시킬 대상 method
- Proxy : Advice가 적용되었을 때 만들어지는 객체
* Advice의 종류
- Before : target method 호출 전에 적용
- After : target method 호출 후에 적용
- Around : target method 호출 이전과 이후 모두 적용(가장 광범위하게 사용됨)
* AOP의 설정 방법
1. pom.xml 에 라이브러리 추가
스프링 4.0
라이브러리 버전에 따라 실행이 안되는 경우가 있다.
첫번째 선택 AOP 라이브러리 버전
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.11</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.8</version>
</dependency>
두번째 선택 AOP 라이브러리 버전
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency
세번째 선택 AOP 라이브러리 버전
<dependency>
<groupId>aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.5.4</version>
</dependency>
<dependency>
<groupId>aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.5.4</version>
</dependency>
스프링의 AOP 를 활용하려면 AOP 관련 라이브러리가 필요하고,
트랜잭션 처리를 위해서 'spring-tx' 라이브러리가 사용돼야 합니다.
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${org.springframework-version}</version>
</dependency>
실행이 유무에 안되면 위 라이브러리 추가 또는 제거
설정 내용이 없으면 추가
스프링에서 AOP 를 처리하기 위해서는 Proxy 객체를 생성할 필요가 있습니다.
스프링에서 Proxy 객체를 만드는 방법은 크게 JDK 의 InvocationHandler 를 이용하는 Dynamic Proxy 방식과 CGLIB 를 이용하는 방식이
사용됩니다.
2. servlet-context.xml의 Namespace에 aop와 tx 추가
root-context.xml 에 AOP의 설정을 통한 자동적인 Proxy 객체 생성을 위해서 아래와 같이 설정을
한다.
<aop:config></aop:config>
<!-- aop의 설정을 통한 자동적인 Proxy 객체 설정 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
아주 중요
component - scan 파일 위해 설정 또는 상단 위에 설정을 해야 된다.
root-context.xml 에 설정에 해도 안되면 servlet-context.xml 에도 설정을 해라
AOP 마크가 표시 되면 설정이 된 것이다.
4. AOP 기능을 지원할 Advice 클래스 작성
import java.util.Arrays;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
//aspectjweaver(1.6.11)와 aspectjrt(1.6.8) 을 mavenrepository 에서 검색해서 pom.xl 넣는다.
//******************* 중요
/* <!-- aop의 설정을 통한 자동적인 Proxy 객체 설정 --> -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<context:component-scan base-package="com.example.wbe04.*" />
//<aop:config> 추가 - 네임스페이스 aop 체크
//component 스켄 전에 붙여야 한다. 안되면 root-context.xml 과 servlet-context.xml 양쪽 모두 맨 상단위에 추가
*
* */
//종단 관심 - 핵심적인 비즈니스 로직
//횡단 관심(Aspect) -공통적인 로직
//Advice - 횡단관심을 모든 코드에서 처리하지 않고 공통적으로 지원할수 있도록
//처리하는 코드
//@Controller 컨트롤빈
//@Service 서비스빈
//@Repository dao빈
//@Component 기타빈
@Component //스프링에서 관리하는 빈
@Aspect //스프링에서 관리하는 aop bean
public class LogAdvice {
//포인트 컷(실행시점) -Before-실행 전, After -실행 후 , Around -실행 전후
//컨트롤러의 모든 method 실행 전후에 logPrint method 가 호출됨
// controller.. 점 두개의미는 controller 다음 모든 패키지 -> xxxController 클래스 의 .* 의미는 모든 메소드
@Around(
"execution(* com.example.wbe04.controller..*Controller.*(..))"
+ " or execution( * com.example.wbe04.service..*Impl.*(..))"
+ " or execution( * com.example.wbe04.model..dao.*Impl.*(..))")
public Object logPrint(ProceedingJoinPoint joinpoint) throws Throwable{
//시스템의 현재시각
long startTime =System.currentTimeMillis();
Object result =joinpoint.proceed();
//클래스 이름
String type =joinpoint.getSignature().getDeclaringTypeName();
//method 이름
String method=joinpoint.getSignature().getName();
//매개 변수
String args =Arrays.toString(joinpoint.getArgs());
System.out.println("클래스 :"+ type);
System.out.println("method :"+ method);
System.out.println("매개변수 :" + args);
long endTime =System.currentTimeMillis();
System.out.println("실행시간 : " + (endTime-startTime));
//return joinpoint.proceed();// 컨트롤러의 method가 실행됨 -- 현재는 before로 적용
//만약joinpoint.proceed() 중간에 있으면 Around 적용
System.out.println("=====================구분선========================================");
return result;
}
}
댓글 ( 4)
댓글 남기기