[spring] AOP 란?
by mini_min[spring] AOP 란?
✔️ AOP
: 관점 지향 프로그래밍
핵심 비즈니스 로직과 공통 모듈을 분리하여 개발자가 좀 더 비즈니스 로직에만 집중해서 처리할 수 있는 방법을 제공한다.
공통 모듈을 적용해서 발생하는 의존 관계의 복잡성과 코드 중복을 해소해주는 프로그래밍 기법이다.
즉, 공통 모듈을 별도로 작성하고 코드 밖에서 비즈니스 로직 사이에 삽입하는 것
📓 용어
- 타겟 : 핵심 기능을 담고 있는 모듈로 타겟은 공통 모듈을 부여할 대상이 된다.
- 어드바이스 : 타겟에 제공할 공통 기능을 담고 있는 모듈이다.
- 조인포인트 : 어드바이스가 적용될 수 있는 위치를 말한다.
타겟 객체가 구현한 인터페이스의 모든 메소드는 Join Point 가 된다.
- 포인트 컷 : 어드바이스를 적용할 타겟의 메소드를 선별하는 정규표현식이다.
- 애스펙트 : AOP 의 기본 모듈이다. (어드바이스+포인트컷)
싱글톤 형태의 객체로 존재한다.
- 어드바이저 : 어드바이스 + 포인트컷
- 위빙 : 위빙은 포인트컷에 의해서 결정된 타겟의 조인 포인트에 어드바이스를 삽입하는 과정을 나타낸다.
📓 특징
- 스프링은 프록시 기반 AOP 를 지원한다.
- 프록시가 호출을 가로챈다.
- 스프링 AOP 는 메소드 조인포인트만 지원한다.
✔️ Advice 종류
- Before 어드바이스
: 타겟의 메소드 호출 전에 적용
- After 어드바이스
: 타겟의 메소드 호출 후에 적용
- After throwing
: 타겟의 예외 발생 후 적용
- After
: 타겟의 메소드 호출 후 예외의 발생에 관계 없이 적용
- Around
: 타겟의 메소드 호출 이전과 이후 모두 적용
✔️ Before 어드바이스
-- Before 예시
✨ JdkRegexpMethodPointcut : 포인트 컷
✨ BeforeLogAdvice : Before 어드바이스 클래스 (공통 부분 가지고 있음)
✨ DefaultPointcutAdvisor : Advice와 Pointcut 을 연결하는 작업
아래 코드에서는 write 메소드가 실행할 때 어떤 공통부분이 실행하는지 묶는 작업이다.
✨ 마지막에 AOP 를 적용한다 (타겟한테)
<!-- Target 클래스 : AOP를 적용할 대상 클래스이다. --> <bean id="testServiceTarget" class="ex01.aop.before.TestServiceImpl"/> <!-- Advice 클래스 : 공통사항을 가지고 있는 클래스 --> <bean id="beforeAdvice" class="ex01.aop.before.BeforeLogAdvice"/> <!-- Pointcut : 실제 Advice 가 적용될 Joinpoint(Advice가 적용될 시점) --> <!-- 하나의 패턴 ,,,, write 라는 말이 들어간거 다 실행--> <!-- --> <!-- pattern : class 안에 있는 필드명이다!!! 이름 틀리면 xx --> <!-- <bean id="myPointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut"> <property name="pattern" value=".*write.*"/> </bean> --> <!-- 다수의 패턴 --> <bean id="myPointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut"> <property name="patterns"> <list> <value>.*save.*</value> <value>.*write.*</value> </list> </property> </bean> <!-- Advisor : Advice와 Pointcut 을 연결하는 작업이다. --> <!-- write 메소드가 실행할 때 어떤 공통부분이 실행하는지 묶는 것 --> <bean id="testAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor"> <property name="advice" ref="beforeAdvice"/> <property name="pointcut" ref="myPointcut"/> </bean> <!-- 마지막 : AOP 적용하기 (타겟한테) --> <!-- 기능이 +++ --> <bean id="testService" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target" ref="testServiceTarget"/> <property name="interceptorNames"> <list> <value>testAdvisor</value> </list> </property> </bean>
✨ MethodBeforeAdvice : 대상 객체의 메소드를 실행하기 전에 공통 기능을 실행할 때 사용하는 Advice
//MethodBeforeAdvice // : 대상 객체의 메소드를 실행하기 전에 공통 기능을 실행할 때 사용하는 Advice public class BeforeLogAdvice implements MethodBeforeAdvice { @Override // 메소드, 매개변수, 타겟 public void before(Method method, Object[] args, Object target) throws Throwable { String s; s = target.getClass() + "클래스의 " + method.getName() + " 메소드 실행전에 실행..."; s += "\n매개변수 : "; if(args != null) { for(int i = 0; i<args.length; i++) { s += args[i] + " "; } } System.out.println(s); } }
public class TestServiceImpl implements TestService { private String value; public TestServiceImpl() { this.value = "AOP 테스트..."; } @Override public void save(String value) { System.out.println("[save 메소드]..."); this.value = value; } @Override public void write() { System.out.println("[wrtie 메소드]..."); System.out.println(value); } }
✔️ After 어드바이스
-- After 예시
<!-- Target 타겟 클래스 --> <bean id="testServiceTarget" class="ex01.aop.after.TestServiceImpl"/> <!-- Advice 클래스 --> <bean id="afterAdvice" class="ex01.aop.after.AfterLogAdvice"></bean> <!-- Advisor : Advice 와 Pointcut 연결하는 작업 --> <bean id="myAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> <property name="advice" ref="afterAdvice"/> <property name="patterns"> <list> <value>.*save.*</value> <value>.*write.*</value> </list> </property> </bean> <!-- AOP 적용 --> <bean id="testService" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target" ref="testServiceTarget"/> <property name="interceptorNames"> <list> <value>myAdvisor</value> </list> </property> </bean>
✨ AfterReturningAdvice : 대상 객체의 메소드 실행 이후에 공통 기능을 실행할 때 사용하는 Advice
예외가 없이 실행된 경우에만 실행
//AfterReturningAdvice // : 대상 객체의 메소드 실행 이후에 공통 기능을 실행할 때 사용하는 Advice // : 예외가 없이 실행된 경우에만 실행 public class AfterLogAdvice implements AfterReturningAdvice { @Override public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { System.out.println(target + "클래스의 " + method.getName() + " 메소드 호출 후... "); System.out.println("리턴 값 : " + returnValue); } }
✔️ MethodInterceptor
: MethodInterceptor 의 경우 세 가지 어드바이스를 묶은 어드바이스이다. (전 후 작업 다 할 수 있다!)
메소드 실행 전, 후 또는 예외 발생 시점에 공통 기능을 실행할 수 있다.
✨ MethodBeforeAdvice, AfterRunningAdvice, ThrowsAdvice 세가지 Advice를 하나로 묶은 Advice
📓 execution 명시자
: 엑시큐선은 어드바이스를 적용할 메소드를 명시할 때 사용한다.
형식 : execution(수식어패턴 리턴타입패턴 클래스이름패턴 이름패턴(파라미터패턴)) 예외패턴
패턴문자 : *(모든 값 표현) .. (0개 이상을 나타냄)
✨ <property name="expression" value="execution(public * *(..))"/>
<!-- Target 클래스 --> <bean id="testService" class="ex03.aop.interceptor.TestServiceImpl"/> <!-- Advice 클래스 --> <bean id="myLogAdvice" class="ex03.aop.interceptor.MyLogAdvice"/> <!-- Advisor : execution 명시자에 표현식 기술 --> <bean id="myAdvisor" class="org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor"> <property name="advice" ref="myLogAdvice"/> <property name="expression" value="execution(public * *(..))"/> </bean> <!-- AOP 적용 : 자동 프록시 생성기 --> <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean>
public class MyLogAdvice implements MethodInterceptor { //MethodInterceptor : 전 후 작업 다 할 수 있음 // : 메소드 실행 전, 후 또는 예외 발생 시점에 공통 기능을 실행할 수 있다. // : MethodBeforeAdvice, AfterRunningAdvice, ThrowsAdvice 세가지 Advice를 // 하나로 묶은 Advice @Override public Object invoke(MethodInvocation invocation) throws Throwable { // 대상 객체 메소드 호출 전 System.out.println(invocation.getMethod().getName()+ " 메소드 호출 전.."); // 대상 객체 메소드 호출 Object returnValue = invocation.proceed(); // 대상 객체 메소드 호출 후 System.out.println(invocation.getMethod().getName()+ " 메소드 호출 후..."); System.out.println("리턴값 : " + returnValue); return returnValue; } }

블로그의 정보
개발자 미니민의 개발로그
mini_min