관점 지향 (AOP, Aspect-Oriented Programming)
메서드나 객체 안에 주기능과 보조기능으로 분리한 후 선택적으로 적용해서 사용하는 방법
전체 코드에 흩어져있는 보조 기능들을 한 곳에 모아서 처리가능하다
필요시(=주기능이 사용될때마다) 선택적으로 보조기능을 사용할 수 있다.
예시 : 쇼핑몰개발자는 쇼핑몰 정보를 처리만 하고 보안처리는 spring 프레임워크가 하는 것
장점 : 코드가 단순해지면서 가독성 향상, 중복된 코드 제거.
사용처: 로깅, 보안, 트랜젝션처리시 사용
AOP용어
AOP용어
설명
특징
Target
Advice가 적용되는 클래스/메서드
-
Advice
Aspect의 실체, 구현해놓은 클래스
메서드호출기준으로 여러 지점에서 호출 가능
Pointcut
Jointpoint의 부분으로 실제로 Advice가 적용된 대상, JointPoint의 상세한 스펙을 정의한 것
패키지이름/클래스이름/메서드이름을 정규식으로 지정 후 처리함
Jointpoint
Advice가 적용될 위치, 끼어들 수 있는 지점
스프링에서는 method 결합점만 제공
Aspect
공통기능, 구현하고자 하는 보조 기능
-
Weaving(위빙)
Advice를 핵심기능에 적용하는 행위
-
스프링API를 활용한 AOP구현방법
Target 클래스 지정
Advice 클래스 지정
설정파일(스프링프레임워크)에서 Pointcut을 지정
설정파일(스프링프레임워크)에서 Advice와 Pointcut을 결합하는 Advicer 생성
설정파일(스프링프레임워크)에서 ProxyFactoryBean(스프링에서 제공)클래스를 사용해서 Target에 Advice를 적용
getBean()메서드로 해당 bean(객체)접근해서 사용
스프링API에서 제공하는 Advice인터페이스
인터페이스 이름
추상메서드 이름
특징
MethodBeforeAdvice
before()
주 메서드 실행하기 전에 실행. 예를 들면 내 주기능이 로그인이다. 로그인전에 보안처리나 로깅처리를 실행하고자할때 내 주기능 실행전에 실행하는 것
AfterReturningAdvice
afterReturning()
주 메서드 실행 후 실행
ThrowsAdvice
afterThrowing()
주 메서드에서 예외가 발생시 실행
MethodInterceptor
invoke()
주 메서드의 실행 전/후에 실행(예외발생시 실행도 포함)
예시 : 계산기 만들기 간단한 계산기 예제를 통해서 AOP를 알아보자
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class Calculator { public void add (int x, int y) { int result = x + y; System.out.println("add 결과: " +result); } public void sub (int x, int y) { int result = x - y; System.out.println("sub 결과: " +result); } public void mul (int x, int y) { int result = x * y; System.out.println("mul 결과: " +result); } public void div (int x, int y) { int result = x / y; System.out.println("div 결과: " +result); } }
target 객체생성 advice 객체생성 위에서 학습한 순서에 따라 객체 생성해보자. 1번과 2번을 함께 xml파일에 생성
1 2 3 4 5 6 7 8 9 10 11 12 13 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd" > <beans > <bean id ="calcTarget" class ="com.itwill.aop.Calculator" /> <bean id ="logAdvice" class ="com.itwill.aop.LoggingAdvice" /> </beans >
설정파일(스프링프레임워크)에서 Pointcut을 지정 설정파일(스프링프레임워크)에서 Advice와 Pointcut을 결합하는 Advicer 생성 3번 4번을 함께 java파일에 작성하자 스프링API에서 제공하는 Advice인터페이스 중 MethodInterceptor를 구현해보았다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import org.aopalliance.intercept.MethodInterceptor;import org.aopalliance.intercept.MethodInvocation;public class LoggingAdvice implements MethodInterceptor { @Override public Object invoke (MethodInvocation inv) throws Throwable { System.out.println(inv.getMethod()+" 메서드 호출 전" ); Object obj = inv.proceed(); System.out.println(inv.getMethod()+" 메서드 호출 후" ); return obj; } }
설정파일(스프링프레임워크)에서 ProxyFactoryBean(스프링에서 제공)클래스를 사용해서 Target에 Advice를 적용
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 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd" > <beans > <bean id ="calcTarget" class ="com.itwill.aop.Calculator" /> <bean id ="logAdvice" class ="com.itwill.aop.LoggingAdvice" /> <bean id ="proxyCalc" class ="org.springframework.aop.framework.ProxyFactoryBean" > <property name ="target" ref ="calcTarget" /> <property name ="interceptorNames" > <list > <value > logAdvice</value > </list > </property > </bean > </beans >
getBean()메서드로 해당 bean(객체)접근해서 사용
CalcAOPTest.java
생성 후 getBean()사용
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class CalcAOPTest { public static void main (String[] args) { System.out.println(" 계산기 실행 ! " ); ApplicationContext appCtx = new ClassPathXmlApplicationContext("AOPTest.xml" ); System.out.println("-----------target 객체생성" ); Calculator cal2 = (Calculator)appCtx.getBean("calcTarget" ); cal2.add(200 , 200 ); System.out.println("-----------Proxy로 객체생성" ); Calculator cal = (Calculator)appCtx.getBean("proxyCalc" ); cal.sub(100 , 200 ); cal.mul(5 , 2 ); } }
로그를 통해 정상적으로 객체를 생성하고 호출하는 것을 확인할 수 있다.