아무거나

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

Java & Kotlin/Spring

[spring] AOP(Aspect Oriented Programming) - 2

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

[spring] AOP(Aspect Oriented Programming) - 2

 

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

 

작업순서

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

[pom.xml]

        .........

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

 

(2) @Aspect 어노테이션을 이용한 Aspect클래스 제작

    [LogAop.java]

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

// LogAop 클래스가 Aspect역할을하는 기능이라고 명시
@Aspect
public class LogAop {
    // 핵심코드의 com.javalec.ex아래의 모든범위를 공통기능을 적용하겠다.
    @Pointcut("within(com.javalec.ex.*)")
    private void pointcutMethod() {}

    // loggerAop가 @Around("pointcutMethod()")로 인하여 @Pointcut("within(com.javalec.ex.*)") 메소드를 찾아가서 지정하는 범주까지 loggerAop가 적용됨
    @Around("pointcutMethod()")
    public Object loggerAop(ProceedingJoinPoint joinpoint) throws Throwable {
        String signatureStr = joinpoint.getSignature().toShortString();
        System.out.println( signatureStr + " is start.");
        long st = System.currentTimeMillis();

        try {
            Object obj = joinpoint.proceed();
            return obj;
        } finally {
            long et = System.currentTimeMillis();
            System.out.println( signatureStr + " is finished.");
            System.out.println( signatureStr + " 경과시간 : " + (et - st));
        }
    }

    // @Before실행시점은 핵심기능이 실행되기전에 beforAdvice()가 실행되는걸 확인할 수 있다.
    // 아래 메소드 즉, @Before 어노테이션을 이용하면 @Pointcut 어노테이션을 사용한 메소드를 선언하지 않아도 된다. 
    @Before("within(com.javalec.ex.*)")
        public void beforAdvice() {
        System.out.println("beforAdvice()");
    }
}

 

(3) XML파일에 <aop:aspectj-autoproxy /> 설정

    [applicationCTX.xml]

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

<!-- 설정필요 -->
<aop:aspectj-autoproxy /> <!-- @Aspect 어노테이션을 찾아가서 해당 어노테이션을 붙은 녀석을 aspect로 만들어줘서 사용할 수 있다. -->
<bean id="logAop" class="com.javalec.ex.LogAop" />
<bean id="student" class="com.javalec.ex.Student" >
    <property name="name" value="홍길동" />
    <property name="age" value="10" />
    <property name="gradeNum" value="3" />
    <property name="classNum" value="5" />
</bean>
<bean id="worker" class="com.javalec.ex.Worker" >
    <property name="name" value="홍길순" />
    <property name="age" value="35" />
    <property name="job" value="개발자" />
</bean>
</beans>

 

(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();
    }
}

 

2. AspectJ Pointcut 표현식

   * Pointcut을 지정할 때 사용하는 표현식으로 AspectJ 문법을 사용 한다.

     - * : 모든

     - . : 현재

     - .. : 0개 이상

 

 

   * 주로 bean만 많이 쓰인다.

     [Execution]

     @Pointcut("execution(public void get*(..))") // public void인 모든 get 메소드

     @Pointcut("execution(* com.javalec.ex.*.*())") // com.javalec.ex 패키지에 파라미터가 없는 모든 메소드

     @Pointcut("execution(* com.javalec.ex..*.*())") // com.javalec.ex 패키지 & com.javalec.ex 하위 패키지에 파라미터가 없는 모든 메소드

     @Pointcut("execution(* com.javalec.ex.Worker.*())") // com.javalec.ex.Worker 안의 모든 메소드

 

     [within]

     @Pointcut("within(com.javalec.ex.*)") // com.javalec.ex 패키지 안에 있는 모든ㄴ 메소드

     @Pointcut("within(com.javalec.ex..*)") // com.javalec.ex 패키지 및 하위 패키지 안에 있는 모든 메소드

     @Pointcut("within(com.javalec.ex.Worker)") // com.javalec.ex.Worker 모든 메소드

 

     [bean]

     @Pointcut("bean(student)") // student 빈에만 적용

     @Pointcut("bean(*ker)") // ~key로 끝나는 빈에만 적용

 

    * 예제소스

    [LogAop.java]

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

@Aspect
public class LogAop {
    // @Pointcut("execution(public void get*(..))") // public void인 모든 get메소드
    // @Pointcut("execution(* com.javalec.ex.*.*())") // com.javalec.ex 패키지에 파라미터가 없는 모든 메소드
    // @Pointcut("execution(* com.javalec.ex..*.*())") // com.javalec.ex 패키지 & com.javalec.ex 하위 패키지에 파라미터가 없는 모든 메소드
    // @Pointcut("execution(* com.javalec.ex.Worker.*())") // com.javalec.ex.Worker 안의 모든 메소드
    // @Pointcut("within(com.javalec.ex.*)") //com.javalec.ex 패키지 안에 있는 모든 메소드
    // @Pointcut("within(com.javalec.ex..*)")  //com.javalec.ex 패키지 및 하위 패키지 안에 있는 모든 메소드
    // @Pointcut("within(com.javalec.ex.Worker)") //com.javalec.ex.Worker 모든 메소드
    // @Pointcut("bean(student)") //student 빈에만 적용
    @Pointcut("bean(*ker)") //~ker로 끝나는 빈에만 적용

    private void pointcutMethod() {}

    @Around("pointcutMethod()")
    public Object loggerAop(ProceedingJoinPoint joinpoint) throws Throwable {
        String signatureStr = joinpoint.getSignature().toShortString();
        System.out.println( signatureStr + " is start.");
        long st = System.currentTimeMillis();

        try {
            Object obj = joinpoint.proceed();
            return obj;
        } finally {
            long et = System.currentTimeMillis();
            System.out.println( signatureStr + " is finished.");
            System.out.println( signatureStr + " 경과시간 : " + (et - st));
    	}
    }

    @Before("pointcutMethod()")
    public void beforAdvice() {
    	System.out.println("beforAdvice()");
    }
}

 

 

참고: 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