AOP 실습

Spring Framework 2016. 3. 31. 14:17


Spring AOP 용어
Aspect Oriented Programming
Aspect : 여러 객체에서 공통으로 적용되는 공통 관심 사항 (ex:트랜잭션, 로깅, 보안)
JoinPoint : Aspect적용 될 수 있는 곳 (ex:메소드, 필드)
Pointcut : JoinPoint 중 공통 관심 사항이 적용된 곳. (정규표현식이나 AspectJ 문법으로 정의함)
Advice : 언제(ex: 메소드 수행 전/후, 예외발생 후 등) 어떤 공통 관심 기능(Aspect)을 적용할 지 정의한 것.
Weaving : 공통 코드를 핵심 로직 코드에 삽입하는 것. (advisor: pointcut + advice) = 적용되는 동작.

1) 각각의 코드를 어드바이스로 뽑아온다.
2) 여러가지 경우의 수(조인 포인트)를 제공. 이 조인포인트를 어떻게 포인트 컷으로 전환하여 동작을 제공하는가?
3) 여러가지 경우의 수 중 포인트 컷으로 이 메소드가 호출될 때 인터셉트 해줘 라고 개발자가 요청.
4) 인터셉트 하면 로깅이란 이름으로 클래스를 정의해줘서 어드바이스를 적용. (대상인 빈 객체를 알려줌)
5) 스프링에서는 어드바이스와 포인트컷을 합쳐서 빈 객체 이름을 어드바이저라고 붙여줌.
6) 동작을 위빙시켜라 하는 것이 스프링 AOP. 이 주체가 프록시. 프록시에게 어드바이저 정보를 알려줌.
이것들을 적용하는 것을 위빙이라고 함.


AOP를 구현하는 3가지 방법


1) POJO Class를 이용한 AOP구현 (전통적인 방식)

2) 스프링 API를 이용한 AOP구현 (<aop> 엘리먼트 이용)

3) 어노테이션을 이용한 AOP 구현 (@Aspect으로 직접 구현)



1) 설정 파일


<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


<bean id="msgBean" class="spring.aop.ch01.MessageBeanImpl" >

<property name="name" value="Spring AOP" />

</bean>

<bean id="logging" class="spring.aop.ch01.Logging"></bean>

<!-- proxy : 스프링 AOP에서 메서드 호출을 가로채기한다. -->

<!-- target 속성 : 위빙될 대상 클래스 -->

<bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">

<property name="target" ref="msgBean"/><!-- 인터셉트할 대상을 지정, name은 target 메서드, 타겟 클래스 ID는 ref에 -->

<property name="interceptorNames"><!-- setter 메서드인 interceptorNames는 입력값은 리스트 타입.  -->

<list>

<value>advisor</value>

</list>

</property>

</bean>

<!-- advisor : pointcut + advice -->

<bean id="advisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">

<property name="advice"  ref="logging"/>

<property name="pointcut">

<bean class="org.springframework.aop.support.JdkRegexpMethodPointcut">

<property name="pattern">

<value>.*helloApp.*</value>

</property>

</bean>

</property>

</bean>

</beans>





2) 메시지빈 인터페이스


package spring.aop.ch01;

public interface MessageBean {

public void helloApp();

}





3) 메시지빈 클래스


package spring.aop.ch01;


public class MessageBeanImpl implements MessageBean {


private String name;


public void setName(String name) {

this.name = name;

}


@Override

public void helloApp() {

try {

Thread.sleep(5000); // 시간 지연을 위한 스레드 sleep 메소드 사용

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("Hello, " + name + "!");

}

}





4) Logging 클래스


메서드 호출되는 시점과 종료하는 시점에 인터셉트 하겠다는 MethodInterceptor 인터페이스를 구현. = 어드바이스


package spring.aop.ch01;


import org.aopalliance.intercept.MethodInterceptor;

import org.aopalliance.intercept.MethodInvocation;

import org.springframework.util.StopWatch;


public class Logging implements MethodInterceptor {

// 스프링이 AOP 인터셉트 기능을 수행하게 하는 메서드인터셉터 인터페이스를 구현

@Override 

public Object invoke(MethodInvocation arg0) throws Throwable {

// 인터셉트 한 것을 알려주는 메서드

String methodName = arg0.getMethod().getName();

// 현재 인터셉트한 메서드의 이름을 가져옴

StopWatch sw = new StopWatch(); // 스프링에서 제공하는 타이머 기능의 클래스

sw.start();

System.out.println("[메서드 추적 로그 정보]: "+methodName+" 메서드를 호출합니다.");

Object rtnObj = arg0.proceed(); // proceed는 인터셉트를 수행하러 가라는 오브젝트 타입의 메서드

sw.stop(); // 위 메서드가 끝나면 StopWatch도 끝내기

System.out.println("[메서드 추적 로그 정보]: "+methodName+" 메서드를 호출을 완료합니다.");

System.out.println("[메서드 실행 시간]: "+sw.getTotalTimeMillis()/1000+"초");

return null;

}

}




5) 실행 클래스


package spring.aop.ch01;


import org.springframework.context.support.AbstractApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;


public class HelloApp {


public static void main(String[] args) {

AbstractApplicationContext context = new ClassPathXmlApplicationContext("applicationContext1.xml");

context.registerShutdownHook();

MessageBean msgBean = context.getBean("proxy", MessageBean.class);

msgBean.helloApp();

context.close();

}

}




실행 후 5초 후에 뜬다.


[메서드 추적 로그 정보] : helloApp 메서드를 호출합니다.

Hello, Spring AOP!

[메서드 추적 로그 정보] : helloApp 메서드 호출을 완료합니다.

[메서드 실행 시간] : 5초






Posted by netyhobby
,