'AOP'에 해당되는 글 1건

  1. 2012.05.14 Spring 3.0 AOP

Spring 3.0 AOP

2012. 5. 14. 19:10


05. 스프링 AOP




AOP(Aspect Oriented Programming)
 - 문제를 바라보는 관점을 기준으로 프로그래밍하는 기법
 - 문제를 해결하기 위한 핵심 관심 사항과 전체에 적용되는 공통 관심 사항을 기준으로 프로그래밍 함으로써 공통 모듈을 여러 코드에 쉽게 적용

공통관심사항 (cross-cutting concern)
어플리케이션에서 로깅과 같은 기본적인 기능에서부터 트랙잭션이나 보안과 같은 기능에 이르기까지 어플리케이션 전반에걸쳐 적용되는 공통기능이

핵심로직을 핵심 관심 사항(core concern) 이라고 표현.




* AOP용어 *



Advice    : 언제 공통 관심 기능을 핵심 로직에 적용할지를 정의
Joinpoint : Advice를 적용 가능한 지점을 의미 (메서드호출, 필드값 변경 등)
Pointcut  :  Joinpoint의 부분집합(그룹화)  실제로 Advice가 Joinpoint  적용된 스프링 정규표현식이나 AspectJ의 문법을 이용하여 Pointcut을 정의 할 수있다.
Weaving  : Advice를 핵심 로직 코드에 적용하는것
Aspect   :  공통관심사항


세가지 Weaving 방식

 - 컴파일 시에  Weaving 하기
 - 클래스 로딩시에 Weaving 하기
 - 런타임 시에 Weaving 하기


스프링에서의 AOP
스프링은 자체적으로 프록시 기반의 AOP를 지원한다 따라서 스프링 AOP는 메서드호출 Joinpoint만을 지원하고 필드값변경같은 Joinpoint를 사용하기 위해서는 AspectJ와 같이 풍부한 기능을 지원하느 AOP 도구를 사용

스프링은 세가지 방식으로 AOP구현
 - XML 스키마 기반의 POJO클래스를 이용한 AOP 구현
 - AspectJ 5/6에서 정의한 @Aspect 어노테이션 기반의 AOP구현
 - 스프링 API를 이용한 AOP 구현 (많이사용하지는 않음)


Advice    : 언제 공통 관심 기능을 핵심 로직에 적용할지를 정의

Advice 정의 관련태그
<aop:before>            : 메서드 실행전에 적용되는 Advice를 정의
<aop:after-returning> : 메서드가 정상적으로 실행된 후에 적용되는 Advice를 정의
<aop:throwing>         : 예외를 발생시킬 때 적용되는 Advice를 정의 (catch와 비슷)
<aop:after>              : 예외 여부와 상관없는 Advice를 정의한다 (finally 블록봐 비슷)
<aop:around>           : 메서드 호출 이전, 이후, 예외 발생 등 모든 시점에서 적용 가능한 Advice를 정의한다.

public class ProfilingAdvice {
    public Object trace(ProceedingJoinPoint joinPoint) throws Throwable{

전처리
        String signatureString = joinPoint.getSignature().toShortString();
        System.out.println(signatureString + "시작");
        long start = System.currentTimeMillis();

       
        try{
            Object result = joinPoint.proceed();
            return result;
        }finally{

후처리
            long finish = System.currentTimeMillis();
            System.out.println(signatureString + "종료");
            System.out.println(signatureString + "실행 시간 : " + (finish - start) + "ms");

        }
    }
}

XML스키마를 이용한 AOP 설정

<aop:config> : AOP 설정 정보임을 나타낸다.
<aop:aspect> : Aspect를 설정한다.
<aop:pointcut> : Pointcut을 설정 한다.
<aop:around> : Around Advice를 설정한다. 이외에도 다양한 Advice를 설정




Aspect   :  공통관심사항
@Aspect 어노테이션을 이용해서 Aspect 클래스를 구현한다 .이때 Aspect 클래스는 Advice를 구현한 메서드와 Pointcut을 포함한다.








Pointcut  :  Joinpoint의 부분집합(그룹화)  실제로 Advice가 Joinpoint  적용된 스프링 정규표현식이나 AspectJ의 문법을 이용하여 Pointcut을 정의 할 수있다.



Joinpoint : Advice를 적용 가능한 지점을 의미 (메서드호출, 필드값 변경 등)
Weaving  : Advice를 핵심 로직 코드에 적용하는것


AspectJ의 Pointcut 표현식 P181




===============================프로젝트===================================
예제.
src/
madvirus.spring.chap05.aop.annot
      ProfilingAspect (어노테이션)

madvirus.spring.chap05.aop.pojo
      Main (POJO)
      ProfilingAdvice (POJO)

madvirus.spring.chap05.board
      Article ()

madvirus.spring.chap05.board.dao
      ArticleDao (interface)
      MySQLArticleDao ()

madvirus.spring.chap05.board.service
      WriteArticleService (interface)
      WriteArticleServiceImpl ()

madvirus.spring.chap05.member
      Member ()

madvirus.spring.chap05.member.service
      MemberService (interface)
      MemberServiceImpl ()
      UpdateInfo ()

applicationContext.xml (POJO)
applicationContext02.xml (어노테이션)


==================================코드======================================
예제.
src/
madvirus.spring.chap05.aop.annot
      Main02(어노테이션)
package madvirus.spring.chap05.aop.annot;

import madvirus.spring.chap05.board.Article;
import madvirus.spring.chap05.board.service.WriteArticleService;
import madvirus.spring.chap05.member.Member;
import madvirus.spring.chap05.member.service.MemberService;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main02 {
    public static void main(String[] args){
        String[] configLocations = new String[] {"applicationContext02.xml" };
        ApplicationContext context = new ClassPathXmlApplicationContext(configLocations);
       
        WriteArticleService articaleService = (WriteArticleService)context.getBean("writeArticleService");
       
        articaleService.write(new Article());
    }
}

      ProfilingAspect (어노테이션)
package madvirus.spring.chap05.aop.annot;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class ProfilingAspect {

    @Pointcut("execution(public * madvirus.spring.chap05.board..*(..))")
    private void profileTarget(){}

    @Around("profileTarget()")
    public Object trace(ProceedingJoinPoint joinPoint)throws Throwable{
       
        String signatureString = joinPoint.getSignature().toShortString();
        System.out.println(signatureString + "시작");
        long start = System.currentTimeMillis();
       
        try{
            Object result =joinPoint.proceed();
            return result;
        }finally{
           
            long finish = System.currentTimeMillis();
            System.out.println(signatureString + "종료");
            System.out.println(signatureString + "실행시간 : "+(finish-start)+"ms");               
        }
    }
}


madvirus.spring.chap05.aop.pojo
      Main (POJO)
package madvirus.spring.chap05.aop.pojo;

import madvirus.spring.chap05.board.Article;
import madvirus.spring.chap05.board.service.WriteArticleService;
import madvirus.spring.chap05.member.Member;
import madvirus.spring.chap05.member.service.MemberService;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
    public static void main(String[] args){
        String[] configLocations = new String[] {"applicationContext.xml" };
        ApplicationContext context = new ClassPathXmlApplicationContext(configLocations);
       
        WriteArticleService articaleService = (WriteArticleService)context.getBean("writeArticleService");
       
        articaleService.write(new Article());
       
        MemberService memberService = (MemberService)context.getBean("memberService");
        memberService.regist(new Member());
    }
}

      ProfilingAdvice (POJO)
package madvirus.spring.chap05.aop.pojo;

import org.aspectj.lang.ProceedingJoinPoint;

public class ProfilingAdvice {
    public Object trace(ProceedingJoinPoint joinPoint) throws Throwable{
        String signatureString = joinPoint.getSignature().toShortString();
        System.out.println(signatureString + "시작");
        long start = System.currentTimeMillis();
       
        try{
            Object result = joinPoint.proceed();
            return result;
        }finally{
            long finish = System.currentTimeMillis();
            System.out.println(signatureString + "종료");
            System.out.println(signatureString + "실행 시간 : " + (finish - start) + "ms");
        }
    }
}


madvirus.spring.chap05.board
      Article ()
package madvirus.spring.chap05.board;

import madvirus.spring.chap05.board.dao.ArticleDao;

import org.springframework.beans.factory.annotation.Configurable;

public class Article {

    private int id;
    private ArticleDao articleDao;

    public Article() {
    }

    public Article(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }

    public void increaseReadCount() {
        articleDao.updateReadCount(id, 1);
    }

    public void setArticleDao(ArticleDao articleDao) {
        this.articleDao = articleDao;
    }
}


madvirus.spring.chap05.board.dao
      ArticleDao (interface)
package madvirus.spring.chap05.board.dao;

import madvirus.spring.chap05.board.Article;

public interface ArticleDao {

    void insert(Article article);

    void updateReadCount(int id, int i);
}

      MySQLArticleDao ()
package madvirus.spring.chap05.board.dao;

import madvirus.spring.chap05.board.Article;

public class MySQLArticleDao implements ArticleDao {

    @Override
    public void insert(Article article) {
        System.out.println("MySQLArticleDao.insert() 실행");
    }

    @Override
    public void updateReadCount(int articleId, int inc) {
        System.out.println("MySQLArticleDao.updateReadCount() 실행");
    }
}


madvirus.spring.chap05.board.service
      WriteArticleService (interface)
package madvirus.spring.chap05.board.service;

import madvirus.spring.chap05.board.Article;

public interface WriteArticleService {

    void write(Article article);
}

      WriteArticleServiceImpl ()
package madvirus.spring.chap05.board.service;

import madvirus.spring.chap05.board.Article;
import madvirus.spring.chap05.board.dao.ArticleDao;

public class WriteArticleServiceImpl implements WriteArticleService {

    private ArticleDao articleDao;

    public WriteArticleServiceImpl() {
    }
   
    public WriteArticleServiceImpl(ArticleDao articleDao) {
        this.articleDao = articleDao;
    }

    //실제적으로 출력될 메서드
    @Override
    public void write(Article article) {
        System.out.println("WriteArticleServiceImpl.write() 메서드 실행");
        articleDao.insert(article);
    }
}


madvirus.spring.chap05.member
      Member ()
package madvirus.spring.chap05.member;

public class Member {

}


madvirus.spring.chap05.member.service
      MemberService (interface)
package madvirus.spring.chap05.member.service;

import madvirus.spring.chap05.member.Member;

public interface MemberService {
   
    void regist(Member member);
   
    boolean update(String memberId,UpdateInfo info);
}

      MemberServiceImpl ()
package madvirus.spring.chap05.member.service;

import madvirus.spring.chap05.member.Member;

public class MemberServiceImpl implements MemberService {

    @Override
    public void regist(Member member) {
        System.out.println("MemberServiceImpl.regist() 메서드 실행");
    }

    @Override
    public boolean update(String memberId, UpdateInfo info) {
        System.out.println("MemberServiceImpl.update() 메서드 실행");
        return true;
    }
}

      UpdateInfo ()
package madvirus.spring.chap05.member.service;

public class UpdateInfo {

}


applicationContext.xml (POJO)
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    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-3.0.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd">


    <!-- Advice 클래스를 빈으로 등록 -->
    <bean id="preformanceTraceAdvice" class="madvirus.spring.chap05.aop.pojo.ProfilingAdvice"/>
   
    <!-- Aspect 설정 : Advice를 어떤 Pointcut에 적용할 지 설정 -->
    <aop:config>
        <aop:aspect id="traceAspect1" ref="preformanceTraceAdvice">
            <!-- 광범위하게 적용 : madvirus.spring.chap05.board 안에있는  모든 메소드에 적용 -->
            <aop:pointcut id="publicMethod" expression="execution(public * madvirus.spring.chap05.board..*(..))" />
            <aop:around pointcut-ref="publicMethod" method="trace"/>       
        </aop:aspect>   
       
        <aop:aspect id="traceAspect2" ref="preformanceTraceAdvice">
            <!-- 광범위하게 적용 : madvirus.spring.chap05.board 안에있는  모든 메소드에 적용 -->
            <aop:around pointcut="execution(public * madvirus.spring.chap05.member..*(..))" method="trace"/>       
        </aop:aspect>   
    </aop:config>
   
    <bean id="writeArticleService" class="madvirus.spring.chap05.board.service.WriteArticleServiceImpl">
        <constructor-arg>
            <ref bean="articleDao"/>
        </constructor-arg>
    </bean>   
   
    <bean id="articleDao" class="madvirus.spring.chap05.board.dao.MySQLArticleDao" />
   
    <bean id="memberService" class="madvirus.spring.chap05.member.service.MemberServiceImpl"/>
   
</beans>

applicationContext02.xml (어노테이션)
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    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-3.0.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <aop:aspectj-autoproxy/>

    <!-- Advice 클래스를 빈으로 등록 -->
    <bean id="preformanceTraceAspect" class="madvirus.spring.chap05.aop.annot.ProfilingAspect"/>
   
    <bean id="writeArticleService" class="madvirus.spring.chap05.board.service.WriteArticleServiceImpl">
        <constructor-arg>
            <ref bean="articleDao"/>
        </constructor-arg>
    </bean>   
   
    <bean id="articleDao" class="madvirus.spring.chap05.board.dao.MySQLArticleDao" />
   
</beans>


==================================결과값=====================================

1. (POJO)

2. (POJO)

3 (어노테이션)


'스프링3.0' 카테고리의 다른 글

Spring3.0 View error filedown  (0) 2012.05.14
Spring3.0 MVC 웹요청 처리  (0) 2012.05.14
Spring3.0 DI 3  (0) 2012.05.14
스프링 3.0 @ 어노테이션 기반 설정  (0) 2012.05.14
Spring3.0 message&event  (1) 2012.05.14
Posted by 사라링

BLOG main image
.. by 사라링

카테고리

사라링님의 노트 (301)
JSP (31)
J-Query (41)
JAVA (24)
VM-WARE (0)
디자인패턴 (1)
스크랩 (0)
스트러츠 (3)
안드로이드 (11)
오라클 (45)
우분투-오라클 (1)
이클립스메뉴얼 (6)
스프링3.0 (23)
자바스크립트 (10)
HTML5.0 (17)
정보처리기사 (1)
기타(컴퓨터 관련) (1)
문제점 해결 (3)
프로젝트 (2)
AJAX (4)
하이버네이트 (3)
트러스트폼 (11)
Jeus (2)
재무관리(회계) (5)
정규식 (5)
아이바티스 (8)
취미 (2)
소프트웨어 보안 관련모음 (0)
정보보안기사 (6)
C언어 베이직 및 프로그램 (3)
보안 관련 용어 정리 (2)
넥사크로 (6)
Total :
Today : Yesterday :