AOP 개요 (A)spect (O)riented (P)rogramming : 관점 지향 프로그래밍 가장 기초가 되는 개념은 관심의 분리(Separation of Concern) AOP는 OOP를 수정하는 것이라 보면 된다. 가장 기초가 되는 개념은 관심의 분리(Separation of Concern) 1.핵심관심 : 시스템의 핵심 가치와 목적이 그대로 드러난 관심영역
2.횡단관심: 핵심관심 전반에 걸쳐 반복적으로 나오게 되는 로깅, 트랜잭션, 보안, 인증, 리소스 풀링, 에러체크 등의 관심영역
3.관심의 분리: 여러 핵심관심에 걸쳐 등장하는 횡단관심을 분리하여 독립적인 모듈로 만들고 핵심관심이 실행되는 동안 횡단관심을 호출하는 코드를 직접 명시하지 않고 선언적으로 처리
4.핵심관심 모듈의 중간중간에서 필요한 횡단관심 모듈을 직접 호출하지 않고 위빙(Weaving)이라 불리는 작업을 이용하여 횡단관심 코드가 삽입되도록 만든다.
5.핵심관심모듈에서는 횡단관심모듈이 무엇인지 조차 인식할 필요가 없음
AOP의 구성요소
JoinPoint(언제)
-횡단관심모듈은 코드의 아무 때나 삽입이 되는 건 아니다. -조인포인트라 불리는 특정 시점에서만 삽입이 가능하다.
PointCut (어디에서)
-어느 조인포인트에 횡단관심모듈을 삽입할지를 결정하는 기능 -횡단관심이 삽입될 특정 클래스의 특정 메소드를 선택하는 방법 정의
Advice(or Interceptor, 무엇을 ) 횡단관심모듈(로깅, 보안, 트랜잭션 등)
Weaving(위빙)
-어드바이스(횡단관심)를 삽입하는 과정 -위빙작업이 일어나는 시간 컴파일 시 - 특별한 컴파일러 필요 클래스 로딩시 - 특별한 클래스로더 필요 런타임시 - 프록시를 이용한 방법(스프링)
####실습 project 생성 - new maven project - 다음 - quick start 다음 - 그룹ID:com.bigdata2017 / 아티클아이디:aoptest
프로젝트 우클릭 - 프로퍼티스- 자바빌드패스 - JRE 수정 프로젝트 우클릭 - 프로퍼티스- project facets - Runtimes탭 - jre 선택 후 어플라이
아래와 같이 수정
pom.xml 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 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > <modelVersion>4.0 .0 </modelVersion> <groupId>com.bigdata2017</groupId> <artifactId>aoptest</artifactId> <version>0.0 .1 -SNAPSHOT</version> <packaging>jar</packaging> <name>aoptest</name> <url>http: <properties> <project.build.sourceEncoding>UTF-8 </project.build.sourceEncoding> <org.springframework-version>4.1 .1 .RELEASE</org.springframework-version> </properties> <dependencies> <!-- spring context --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${org.springframework-version}</version> </dependency> <!-- spring aspect --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>${org.springframework-version}</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8 .1 </version> <scope>test</scope> </dependency> </dependencies> </project>
프로젝트 우클릭- 뉴 - 소스폴더 -src/main/resource 생성된 소스폴더안에 config패키지 추가 패키지 안에 applicationContext.xml
applicationContext.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <?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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd" > <!-- AOP AutoProxy --> <aop:aspectj-autoproxy /> <context:annotation-config /> <context:component-scan base-package ="com.bigdata2017.aoptest" > <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository" /> <context:include-filter type="annotation" expression="org.springframework.stereotype.Service" /> <context:include-filter type="annotation" expression="org.springframework.stereotype.Component" /> </context:component-scan> </beans>
App.java에 입력
App.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package com.bigdata2017.aoptest;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class App { public static void main ( String[] args ) { ApplicationContext ac = new ClassPathXmlApplicationContext ("config/applicationContext.xml" ); ProductService ps = ac.getBean( ProductService.class ); ProductVo vo = ps.find( "camera" ); } }
ProductService.java 생성
pom.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package com.bigdata2017.aoptest;import org.springframework.stereotype.Service;@Service public class ProductService { public ProductVo find ( String keyword ) { System.out.println("finding...." ); return new ProductVo ( keyword ); } }
ProductVo생성
ProductVo.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 package com.bigdata2017.aoptest;public class ProductVo { private String name; public ProductVo ( String name ) { this .name = name; } public String getName () { return name; } public void setName (String name) { this .name = name; } @Override public String toString () { return "ProductVo [name=" + name + "]" ; } }
MyAspect생성
MyAspect.java 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 package com.bigdata2017.aoptest;import org.aspectj.lang.annotation.After;import org.aspectj.lang.annotation.AfterReturning;import org.aspectj.lang.annotation.AfterThrowing;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.springframework.stereotype.Component;@Aspect @Component public class MyAspect { @Before( "execution(public ProductVo com.bigdata2017.aoptest.ProductService.find(..))" ) public void beforeAdvice () { System.out.println( "beforeAdvice() called" ); } @After( "execution(* com.bigdata2017.aoptest.*.find(..))" ) public void afterAdvice () { System.out.println( "afterAdvice() called" ); } @AfterReturning( "execution(* *..ProductService.find(..))" ) public void afterReturning () { System.out.println( "afterReturning() called" ); } @AfterThrowing( value="execution(* *..*.*(..))", throwing="ex" ) public void afterThrowing ( Throwable ex ) { System.out.println( "afterThrowing() called:" + ex ); } }