아무거나

[spring] AOP(Aspect Oriented Programming) - 1 본문

Java & Kotlin/Spring

[spring] AOP(Aspect Oriented Programming) - 1

전봉근 2019. 12. 25. 23:42
반응형

[spring] AOP(Aspect Oriented Programming) - 1

개발시에 공통적인 기능이 많이 발생한단. 이러한 것들을 모든 모듈에 적용하기 위한 방법으로 상속을 통한 방법이 있다.

하지만 상속에는 몇가지 문제가 있다. JAVA에는 다중 상속이 불가하며 다양한 모듈에 상속기법을 통한 공통 기능 부여는 한계가 있다.

그리고, 기능 구현부분에 핵심 기능 코드와 공통 기능 코드가 섞여 있어 효율성이 떨어진다. ( 즉, 코드가 core기능이나 필요기능등. 다 짬뽕되어서 코드의 양이 많아지고 유지보수가 어려워진다. )

 

그래서 AOP가 등장했다. AOP는 핵심 기능과 공통 기능을 분리 시켜놓고, 공통 기능을 필요로 하는 핵심 기능들에서 사용하는 방식이다.

 

[ex - 밥만들기]

물을 받고 -> 쌀을 씻고 -> 깨끗한 물을 적당히 넣고 -> 눈으로 판단(물의 양) -> 전자밥솥에 내솥을 넣고 -> 취사버튼

 

# 공통기능 : 물을 받고, 눈으로 판단(물의 양)

# 핵심기능 : 쌀을 씻고, 깨끗한 물을 적당히 넣고, 전자밥솥에 내솥을 넣고, 취사버튼

 

1. AOP란

   * 먼저 용어에 익숙해지자

     - Aspect : 공통 기능 ( ex - log기능 )

     - Advice : Aspect의 기능 자체 ( ex : aspect의 주요 내용 즉, 핵심기능이다. )

     - Joinpoint : Advice를 적용해야 되는 부분( ex, 필드, 메소드 ) ( 스프링에서는 메소드만 해당 ) -> 즉, 핵심기능들 하나 하나가 Joinpoint르 보면 된다.

     - Pointcut : Jointpoint의 부분으로 실제로 Advice가 적용된 부분 ( ex: 핵심기능(advice)안에 공통되는 부분을 넣는것 거기에 advice를 적용한다. )

     - Weaving : Advice를 핵심 기능에 적용하는 행위 ( 위에 pointcut을 advice를 적용하는 행위 )

 

   스프링에서 AOP 구현 방법 : proxy를 이용한다.

   * 호출부(client) -> Proxy(대행) -> Target(핵심기능)

   ex) 요청 -> 프록시에서 공통기능 수행 -> 수행한 프록시가 핵심기능쪽으로 이동하여 핵심기능 로직 수행 -> 다시 프록시로와서 나머지 공통기능 수행 -> 종료

 

   스프링에서 AOP 구현 방식

   - XML 스키마 기반의 AOP구현

   - @Aspect 어노테이션 기반의 AOP구현

 

2. XML 기반의 AOP 구현

   [advice 종류]

   - <acp:before> : 메소드 실행 전에 advice 실행

   - <acp:after-returning> : 정상적으로 메소드 실행 후에 advice 실행

   - <acp:after-throwing> : 메소드 실행중 exception 발생시 advice 실행

   - <acp:after> : 메소드 실행중 exception 이 발생하여도 advice 실행

   - <acp:around> : 메소드 실행 전/후 및 exception 발생시 advice 실행

 

   [작업순서]

   (1) 의존 설정(pom.xml) 

       - aop를 구현하겠다는 의존설정을 직접해야한다.

         [pom.xml]

        .........

        <!-- AOP -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.7.4</version>
        </dependency>
    </dependencies>
</project>

 

   (2) 공통 기능의 클래스 제작 (Advice 역할 클래스)

       [LogAop.java]

import org.aspectj.lang.ProceedingJoinPoint;

public class LogAop {
    // ProceedingJoinPoint의 joinpoint를 가져옴
    public Object loggerAop(ProceedingJoinPoint joinpoint) throws Throwable {
        String signatureStr = joinpoint.getSignature().toShortString(); // 어떤 메소드인지 이름을 변수에 담음
        System.out.println( signatureStr + " is start."); // 출력
        long st = System.currentTimeMillis(); // 공통기능( signatureStr 메서드가 시작 )

        try {
            Object obj = joinpoint.proceed(); // 핵심기능(joinpoint) 코드를 실행
            return obj;
        } finally {
            long et = System.currentTimeMillis(); // 위에 try에 핵심기능(joinpoint)이 실행된후에 시간을 구해온것이다.
            System.out.println( signatureStr + " is finished.");
            System.out.println( signatureStr + " 경과시간 : " + (et - st));
        }
    }
}

 

 

   (3) XML설정 파일에 Aspect 설정( (2)번에 클래스를 만든것으로 XML에 설정 )

       [applicationCTX.xml]

// namespace에 aop설정
xmlns:aop="http://www.springframework.org/schema/aop"
....

<bean id="logAop" class="com.javalec.ex.LogAop" />

<!-- AOP설정 -->
<aop:config>
    <aop:aspect id="logger" ref="logAop"> <!-- logAop Bean을 참조 -->
        <!-- 핵심코드 id를 publicM으로 지정 그리고 com.javalec.ex의 모든 메소드에 전부 적용하겠다. -->
        <aop:pointcut id="publicM" expression="within(com.javalec.ex.*)"  />
        <!-- loggerAop라는 기능을 publicM이라는 pointcut에 주겠다. -->
        <aop:around pointcut-ref="publicM" method="loggerAop" />
    </aop:aspect>
</aop:config>

 

(4) MainClass 작성

    [MainClass.java]

public class MainClass {
    public static void main(String[] args) {
        AbstractApplicationContext ctx = new GenericXmlApplicationContext("classpath:applicationCTX.xml");
        Student student = ctx.getBean("student", Student.class);
        student.getStudentInfo();

        Worker worker = ctx.getBean("worker", Worker.class);
        worker.getWorkerInfo();

        ctx.close();
    }
}

 

 

참고: https://www.inflearn.com/course/%EC%9E%90%EB%B0%94-%EC%8A%A4%ED%94%84%EB%A7%81-%EA%B0%95%EC%A2%8C/dashboard

반응형
Comments