코딩은 실력보다 시력이지

빅데이터교육과정/Spring

AOP란?

Listeria 2021. 4. 9. 02:19

AOP - Aspect Oriented Programing.

Cross-cutting concern의 분리를 통해 모듈성을 증가시키는 프로그래밍 방법.

기존에 있는 코드를 수정하지 않은 상태에서 Advice를 추가하여 사용한다.

Aspect : 공통기능

Advice : Aspect의 기능 그 자체

Pointcut : Jointpoint의 부분으로 실제로 Advice가 적용된 부분

Weaving : Advice를 핵심 기능에 적용하는 행위

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

AOP 사용을 위해 Spring의 pom.xml에 추가 해줘야 하는 코드

 

 

//메인 클래스 예시
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;



public class MainClass {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		AbstractApplicationContext ctx = new GenericXmlApplicationContext("classpath:test.xml");
		
		Student student = ctx.getBean("student",Student.class);
		student.getStudentInfo();
		
		Worker worker = ctx.getBean("worker", Worker.class);
		worker.getWorkerInfo();
		
		ctx.close();
	}

}

 

Annotation을 사용할때 Context xml의 예시 코드
<!-- annotation 사용할때 -->
<aop:aspectj-autoproxy/>
<bean id="logAop" class="com.sl.ap.LogAop"/>

<bean id="student" class="com.sl.ap.Student">
	<property name="name" value="gildong"/>
	<property name="age" value="10"/>
	<property name="gradeNum" value="3"/>
	<property name="classNum" value="3"/>
</bean>

<bean id="worker" class="com.sl.ap.Worker">
	<property name="name" value="soon"/>
	<property name="age" value="2"/>
	<property name="job" value="nothing"/>

</bean>

Annotation을 사용안할때 Context xml의 예시 코드
<!-- annotation 사용안할때 -->
 <aop:config>
	<aop:aspect id="logger" ref="logAop"> 
		<aop:pointcut expression="within(com.sl.app.*)" id="publicM"/>
		<aop:around method="loggerAop" pointcut-ref="publicM"/>
	</aop:aspect>
	<aop:aspect id="logger" ref="logAop">
		<aop:pointcut expression="within(com.sl.app.*)" id="publicM"/>
		<aop:around method="afterReturningAdvice" pointcut-ref="publicM"/>
	</aop:aspect>
	<aop:aspect id="logger" ref="logAop">
		<aop:pointcut expression="within(com.sl.app.*)" id="publicM"/>
		<aop:around method="beforeAdvice" pointcut-ref="publicM"/>
	</aop:aspect>
	<aop:aspect id="logger" ref="logAop">
		<aop:pointcut expression="within(com.sl.app.*)" id="publicM"/>
		<aop:around method="afterAdvice" pointcut-ref="publicM"/>
	</aop:aspect>
</aop:config> 

 

package com.sl.ap;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;

@Aspect
public class LogAop {	//공통기능

	
//	@Pointcut("bean(*ker)")
//	@Pointcut("bean(student)")	
//	@Pointcut("within(com.sl.app.Worker)")	
//	@Pointcut("execution(public void get*(..))")	//public void인 모든 get 메소드
//	@Pointcut("execution(* com.sl.app.*.*())")		//패키지에 파라미터가 없는 모든 메소드
//	@Pointcut("execution(* com.sl.app..*.*())")		//패키지와 하위 패키지에 파라미터가 없는 모든 메소드
	@Pointcut("execution(* com.sl.ap.Worker.*())")		//com.sl.app.Worker안의 모든 메소드
	private void pointcutMethod() {
		
	}
	
//	@Pointcut("within(com.sl.app.*)")
	@Around("pointcutMethod()")
	public Object loggerAop(ProceedingJoinPoint joinpoint) throws Throwable{
		
		String signatureStr = joinpoint.getSignature().toShortString();
		System.out.println(signatureStr + "start");
		long st =System.currentTimeMillis();
		
		try {
			Object obj=joinpoint.proceed(); //개별기능
			return obj;
		} finally {
			long et = System.currentTimeMillis();
			System.out.println(signatureStr + " finish");
			System.out.println(signatureStr + " time"+(et-st));
		}
	}
	
	@Before("within(com.sl.app.*)")
	public void beforeAdvice(JoinPoint joinPoint) {
		System.out.println("before adv");
	}

	@AfterReturning("within(com.sl.ap.*)")
	public void afterReturningAdvice() {
		System.out.println("after return");
	}
	
	@AfterThrowing("within(com.sl.ap.*)")
	public void afterThrowingAdvice() {
		System.out.println("after throw");
	}
	@After("within(com.sl.ap.*)")
	public void afterAdvice() {
		System.out.println("after adv");
	}
}