AOP 웹공학

개념
-핵심 관심사(Core Concerns)에 대한 관점과 횡단 관심사(Cross-cutting Concerns)에 대한 관점들로 프로그램을 분해해 Weaving 을 통해 프로그램을 구현하는 기법.

1. OOP를 OOP답게 사용하는 새로운 패러다임 AOP의 개요

  가. 관점지향 프로그래밍(AOP: Aspect Oriented Programming)의 정의

-핵심 관심사(Core Concerns)에 대한 관점과 횡단 관심사(Cross-cutting Concerns)에 대한 관점들로 프로그램을 분해해 Weaving 을 통해 프로그램을 구현하는 기법.

  나. AOP의 특징

구분

내용

모듈화

- 횡단 관심사를 포괄적이고 체계적으로 모듈화

캡슐화

- 횡단 관심사는 Aspect라는 새로운 단위로 캡슐화하여 모듈화가 이루어짐

단순화

- 핵심 모듈은 더 이상 횡단 관심사의 모듈을 직접 포함하지 않으며 횡단 관심사의 모든 복잡성은 Aspect로 분리

 

2. AOP의 구성도 와 구성요소

  가. AOP의 구성도

  나. AOP의 구성요소

구성요소

내용

핵심관심

- 시스템의 핵심 가치와 목적이 그대로 드러난 관심 영역

횡단관심

- 쉽게 분리된 모듈로 작성하기 힘든 요구사항, 공토모듈

Joint Point

- 횡단 관심의 기능이 삽입되어 실행될 수 있는 특정 위치

Point-Cut

- 어느 Joint Point를 사용할 것인지를 결정하는 선택 기능

Advice

- Joint Point에 삽입되어 동작되는 모듈

Aspect

- Point-cut 과 Advice를 합쳐 놓은 코드

Weaving

- Joint Point 에 해당하는 Advice를 삽입하는 과정

 

3. AOP의 실행절차도 및 절차

  가. AOP의 실행절차도

 

  나. AOP의 절차

순서

내용

1

- 클라이언트는 직접 타겟 객체를 참조하지 않고 프락시를 통해서 호출

2

- 프락시는 클라이언트의 호출을 받으면 3번 처럼 Aspect 모듈을 호출

3

- Cross Concerns에서는 타겟 객체의 메소드를 호출전에 advice의 내용을 수행

4

- 타겟 객체의 전에 Aspect 모듈을 호출해서 마무리 작업을 할 수 있고 그 후 최종적으로 클라이언트에 반환값을 넘겨준다

 

4. AOP와 OOP의 비교

  가. AOP와 OOP의 일반비교

구분

AOP

OOP

소스

코드

구성

- 핵심관심과 횡단관심의 분리

 

 

- 핵심관심과 횡단관심이 산재함

목적

- 부문별 조립으로 생산성 제고

- 상속 및 재사용 통한 효율 제고

관심사

- 공통로직

- 업무로직

장점

- 환경 독립성, 횡단관심 공통 적용

- 객체 재사용

단점

- 구현과 이해에 시간이 소요

- 객체별 독립성 유지 어려움

 

  나. AOP와 OOP의 소스비교

-계정 관리를 기능의 AccountManager 인터페이스가 있고 요구사항은 AccountManager 내에서 Exception이 발생할 때마다 담당자에게 메일을 발송하는 것.

구분

Source

Description

OOP

import org.springframework.dao.DataAccessException;

public interface AccountManager {

    public Account getAccount(String accountId) 

throws AccountNotFoundException, DataAccessException;

   

    public void createAccount(Account account)

 throws DataAccessException;

}

인터페이스

public class AccountManagerImpl implements AccountManager {

 private MailSender mailSender;

 private SimpleMailMessage message;

 private AccountDao accountDao;

 

 public void setAccountDao(AccountDao accountDao) {

   this.accountDao = accountDao;

 } 

 public void setMailSender(MailSender mailSender) {

     this.mailSender = mailSender;

 } 

 public void setMessage(SimpleMailMessage message) {

     this.message = message;

 }

 private void sendMail(Exception ex) {

SimpleMailMessage msg =

new SimpleMailMessage(this.message);

    msg.setText("Encountered exception " + ex.getMessage());

    this.mailSender.send(msg);

 }  

 public Account getAccount(String accountId)

  throws AccountNotFoundException, DataAccessException {

  try {

       return this.accountDao.findAccount(accountId);

 } catch( AccountNotFoundException ex) {

            sendMail(ex);  throw ex;

} catch (DataAccessException ex) {

            sendMail(ex);  throw ex;

        }

    }

 

public void createAccount(Account account) throws DataAccessException {

try {

     if( isInvalid(account)) {

       throw new InvalidAccountException(account);

      }

     this.accountDao.saveAccount(account);

   } catch (IOException ex) {

      sendMail(ex);  throw ex;

} catch (DataAccessException ex) {

     sendMail(ex);  throw ex;

  }

}

}

- AccountManagerImpl 클래스를 보면 Exception이 발생할 때마다 Mail을 보내는 코드가 추가

 

- try/catch block과 메일을 보내기 위한 중복코드가 발생

AOP

public class EmailNotificationThrowsAdvice implements ThrowsAdvice {

 private MailSender mailSender;

 private SimpleMailMessage message;

 

 public void setMailSender(MailSender mailSender) {

     this.mailSender = mailSender;

 }

  

public void setMessage(SimpleMailMessage message) {

    this.message = message;

 }   

 public void afterThrow(Excepton ex) throws Throwable {

     SimpleMailMessage msg =

new SimpleMailMessage(this.message);

        msg.setText

("Encountered exception " + ex.getMessage());

        this.mailSender.send(msg);

 }

}

- Exception이 발생했을 때 메일을 보내는 작업을 실행하는 하나의 Advice

<bean id="emailNotificationThrowsAdvice"

class="com.mycompany.EmailNotificationThrowsAdvice">

<property name="mailSender">

<ref bean="mailSender"/></property>

<property name="message"><ref bean="mailMessage"/>

</property>

</bean>

 

<bean id="accountManagerBeanNameProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">

<property name="beanNames">

<value>accountManagerTarget</value>

</property>

<property name="interceptorNames">

<list>

          <value>emailNotificationThrowsAdvice</value>

</list>

</property>

</bean>          

- 생성된 Advice는 Spring AOP config 정의

 

- EmailNotificationThrowsAdvice를 accountManagerTarget의 메써드가 호출될 때 적용

 

public class AccountManagerImpl implements AccountManager {

 private AccountDao accountDao;

 

 public void setAccountDao(AccountDao accountDao) {

  this.accountDao = accountDao;

 }

 

 public Account getAccount(String accountId)

 throws AccountNotFoundException, DataAccessException {

  return this.accountDao.findAccount(accountId);

 }

 

 public void createAccount(Account account)

 throws DataAccessException {

 this.accountDao.saveAccount(account);

 }

}

- Spring AOP를 적용 후의 AccoungManagerImpl 클래스로서 단지 계정 관리를 위한 비지니스 로직만 있음

댓글