240 likes | 387 Views
Chapter 3. 스프링 AOP. 작성자 : 장은호 소속팀 : 네이버메인스포츠서비스개발팀 작성 일 : 2009/07/24. ⓒ 2009 NHN CORPORATION. 목차. 1. AOP. 1.1 AOP 용어 1.2 세 가지 Weaving 방식. 2. 스프링에서의 AOP. 2.1 프록시를 이용한 AOP 구현. 3. 스프링 API 를 이용한 AOP. 3.1 Advice 작성 3.2 Pointcut 및 Advisor 설정
E N D
Chapter 3. 스프링 AOP 작성자 : 장은호 소속팀 : 네이버메인스포츠서비스개발팀 작성일 : 2009/07/24 ⓒ 2009 NHN CORPORATION
목차 1. AOP 1.1 AOP 용어 1.2 세 가지 Weaving 방식 2. 스프링에서의 AOP 2.1 프록시를 이용한 AOP 구현 3. 스프링 API를 이용한 AOP 3.1 Advice 작성 3.2 Pointcut및 Advisor 설정 3.3 ProxyFactoryBean을 이용한 Advice 적용 3.4 DefaultAdvisorAutoProxyCreator를 이용한 자동 프록시 생성 4. POJO 클래스를 이용한 AOP 4.1 XML 스키마를 이용한 AOP 설정 4.2 POJO 기반의 Advice 작성 4.3 스프링 API를 이용한 Advice 설정 5. @Aspect 어노테이션을 이용한 AOP 6. AspectJ의 Pointcut표현식 6.1 프록시구현 방식에 따른 execution 적용 차이
1.1 AOP 용어 Advice - 언제 공통 관심 기능을 핵심 로직에 적용할지에 대한 정의 (예 : 메서드 호출 전에 시작한다) Joinpoint - Advice를 적용 가능한 지점 (예 : 메서드 호출지점, 필드) Pointcut proxybean - 실제 Advice가 적용되는 지점(Jointpoint의 부분집합) Advisor - Advice + Pointcut Weaving - Advice를 핵심 로직에 적용하는 것 Aspect - 여러 객체에 공통으로 적용되는 공통 관심사항 (보안, 로그 등)
1.2 세 가지 Weaving 방식 컴파일 시에 Weaving하기 : 핵심 로직 부분을 컴파일할 때, 컴파일러가 공통코드를 삽입 = AOP가 적용된 클래스 파일 생성 클래스 로딩 시에 Weaving하기 : JVM 레벨에서 바이트코드 조작 런타임 시에 Weaving하기 : 조작 없이 순수한 자바언어+API (프록시기반) = 스프링에서 사용하는 방식
2.1 프록시를 이용한 AOP 구현 스프링 API를 이용한 AOP 구현 : Ch. 3.3 POJO 클래스를 이용한 AOP 구현 : Ch. 3.4 AspectJ 5에서 정의한 @Aspect 어노테이션 기반의 AOP 구현 : Ch. 3.5 스프링 내부에서의 처리는 같으므로 메서드 호출에 대한 AOP만 구현됨
3.1 Advice 작성 MethodBeforeAdvice : 대상 객체의 메서드 실행 전 • public class MethodBeforeLogAdvice implements MethodBeforeAdvice { • private Log log = LogFactory.getLog(getClass()); • @Override • public void before(Method method, Object[] args, Object target) throws Throwable { • if (log.isTraceEnabled()) • log.trace(method.toString()); • } • } AfterReturningAdvice : 대상 객체의 메서드 실행 후 • public class AfterReturningLogAdvice implements AfterReturningAdvice { • private Log log = LogFactory.getLog(getClass()); • @Override • public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { • if (log.isTraceEnabled()) • log.trace(method.getName() + " on " + target + " called, return value is " + returnValue); • } • } ThrowsAdvice : 대상 객체의 메서드에서 예외가 발생했을 때 void afterThrowing([Method method, Object[] args, Object target], ExceptionType)
3.1 Advice 작성 MethodInterceptor : All in one • public class MethodInterceptorLogAdvice implements MethodInterceptor { • private Log log = LogFactory.getLog(getClass()); • @Override • public Object invoke(MethodInvocation invocation) throws Throwable { • if (log.isTraceEnabled()) • log.trace(invocation.getMethod().getName() + "calling"); • try { • Object returnValue = invocation.proceed(); • if (log.isTraceEnabled()) • log.trace(invocation.getMethod().getName() + " called, return value is " + returnValue); • } catch (Throwable e) { • if (log.isTraceEnabled()) • log.error(invocation.getMethod().getName()); • throw e; • } finally { • if (log.isTraceEnabled()) • log.trace(invocation.getMethod().getName() + "completed."); • } • }
3.2 Pointcut및 Advisor 설정 JdkRegexpMethodPointCut(Perl5RegexpMethodPointcut) <bean id="writePointcut" class="org.springframework.aop.support.JdkRegexpMethodPointCut"> <property name="pattern" value=".*write.*" /> </bean> <bead id="readPointcut" class="org.springframework.aop.support.JdkRegexpMethodPointCut"> <property name="paterns"> <list> <value>.*readArticle.*</value> <value>.*readComment.*</value> </list> </property> </bean> <bean id="beforeLogAdvice" class="MethodBeforeLogAdvice" /> <bean id="writeAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor"> <property name="advice" ref="beforeLogAdvice" /> <property name="pointcut" ref="writePointcut" /> </bean>
3.2 Pointcut및 Advisor 설정 AspectJExpressionPointcut <bean id=“getPointcut" class="org.springframework.aop.aspectj.AspectJExpressionPointcut"> <property name=“expression" value=“execution(public !void get*(..))” /> </bean> <bean id=“getAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor"> <property name="advice" ref=“cacheAdvice" /> <property name="pointcut" ref=“getPointcut" /> </bean>
3.3 ProxyFactoryBean을 이용한 Advice 적용 ProxyFactoryBean : AOP를 적용할 객체에 프록시를 적용시켜 줌 <bean id="writeArticleServiceTarget" class=“...WriteArticleServiceImpl" /> <bean id="writeAdvisor" class="...RegexpMethodPointcutAdvisor"> ... </bean> <bean id="writeArticleService" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target" ref="writeArticleServiceTarget" /> <property name="interceptorNames"> <list> <value>writeAdvisor</value> <value>afterLogAdvice</value> </list> </property> <property name=“proxyInterfaces”> <list> <value>WriteArticleService</value> </list> </property> </bean>
3.3 ProxyFactoryBean을 이용한 Advice 적용 ProxyFactoryBean : AOP를 적용할 객체에 프록시를 적용시켜 줌 String[] configs = {“contextApi.xml”}; ApplicationContext context = new ClassPathXmlApplicationContext(configs); ReadArticleService readArticleService1 = (ReadArticleService) context.getBean(“readArticleService”); // It’s Proxybean ReadArticleService readArticleService2 = (ReadArticleService) context.getBean(“readArticleServiceTarget”); // Just bean
3.4 DefaultAdvisorAutoProxyCreator를 이용한 자동 프록시 생성 ProxyFactoryBean클래스를 사용하지 않아도 자동으로 Advisor 적용 <bean class=“org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator” /> <bead id=“writeArticleService” class=“…” /> <bean id=“beforeLogAdvice” class=…” /> <bean id=“beforeLogAdvisor” class=“org.springframwrodk.aop.aspectj.AspectJExpressionPointcutAdvisor”> <property name=“advice” ref=“beforeLogAdvice” /> <property name=“expression” value=:execution(public * *(..))” /> </bean>
4.1 XML 스키마를 이용한 AOP 설정 AOP 설정 정보임을 나타내는 태그 : <aop:config> Aspect 설정 : <aop:aspect> Pointcut설정 :<aop:pointcut> Advice 설정 : <aop:around> 메서드 실행 전 : <aop:before> 메서드가 정상적으로 실행된 후 : <aop:after-returning> 메서드가 예외를 발생시킬 때 : <aop:atfer-throwing> 메서드가(예외 발생에 상관없이) 종료된 경우 : <aop:after> 모든 시점에 적용 가능 : <aop:around> <bean id="logging" class="LoggingAspect" /> <aop:config> <aop:aspect id="loggingAspect" ref="logging"> <aop:pointcut id="publicMethod" expression="execution(public * (..))" /> <aop:aroundpointcut-ref="publicMethod" method="logging" /> </aop:aspect> </aop:config> <bean id="readArticleService" class="ReadArticleServiceImpl" /> </beans>
4.2 POJO 기반의 Advice 작성 1) Before Advice <aop:config> <aop:aspect id="loggingAspect" ref="logging"> <aop:beforepointcut-ref="publicMethod" method=“beforeLogging" /> </aop:aspect> </aop:config> 2) After Returning Advice <aop:config> <aop:aspect id="loggingAspect" ref="logging"> <aop:after-returningpointcut-ref="publicMethod" method=“returninigLogging" returning=“ret” /> </aop:aspect> </aop:config> 3) After Throwing Advice <aop:config> <aop:aspect id="loggingAspect" ref="logging"> <aop:after-throwingpointcut-ref="publicMethod" method=“throwingLogging" throwing=“ex” /> </aop:aspect> </aop:config>
4.2 POJO 기반의 Advice 작성 4) After Advice <aop:config> <aop:aspect id="loggingAspect" ref="logging"> <aop:afterpointcut-ref="publicMethod" method=“afterLogging" /> </aop:aspect> </aop:config> 5) Around Advice <aop:config> <aop:aspect id="loggingAspect" ref="logging"> <aop:aroundpointcut-ref="publicMethod" method=“returninigLogging“ /> </aop:aspect> </aop:config>
4.3 스프링 API를 이용한 Advice 설정 <bead id="afterReturnAdvice" class="AfterReturningLogAdvice" /> <aop:config> <aop:pointcut id="publicMethod" expression="execution(public *(..))" /> <aop:advisor advice-ref="afterReturnAdvice" pointcut-ref="publicMethod" /> </aop:config>
5.1 @Aspect Annotaion // 설정 파일에 : <aop:aspectj=autoproxy /> // 적용할 Aspect 안에 @Aspect public class AnnoLoggingAspect { private Log log = LogFactory.getLog(getClass()); // Advice와 Pointcut을 기술 @Before("execution(public * *(..))") public String beforeLogging(JoinPointjoinPoint) { String methodName = joinPoint.getSignature().getName(); if (log.isTraceEnabled()) log.trace("calling: " + methodName); return methodName; } }