Java/Spring

[Spring] 12. AOP - 기본 개념 ( CC, CCC, Joinpoint, ...)

담크 2021. 7. 3. 23:07

오늘은 스프링의 AOP에 대해서 공부해보겠습니다.

 

AOP ( Aspect Oriented Programing) - 관점지향 프로그래밍이라고 합니다.

AOP에 사용되는 용어들을 간단히 정리해보자면

CC (Core Concern) : 주 관심사항

 

CCC (Cross Cutting Concern) : 공통 관심사항

 

Joinpoint : 인스턴스의 생성시점과 메소드를 실행하는 시점, Exception이 발생하는 시점같이 애플리케이션이 실행될 때 특정 작업이 실행되는 시점

 

Pointcut : 어떠한 Joinpoint에 적용되어야 하는지 정의

 

Advice : Pointcut에서 지정한 Joinpoint에서 실행(삽입) 되어야 하는 코드로 Aspect의 실제 구현체

 

Aspect : Advice + pointcut 으로 AOP의 중심단위

 

Weaving : Aspect를 대상으로 객체에 적용하여 새로운 Proxy객체를 생성하는 과정

 

Proxy : AOP에서 타겟인척 하며 신호를 대신 받아주고 응답

 

이렇게 나오는데요 용어만 보면 무슨 말인지 이해하기 쉽지 않죠... ㅎㅎ 바로 코딩하러 가봅시다.

패키지부터 만들어주세요

Student.java(interface)

package com.test02;

public interface Student {
	
	void classWork();

}

StudentA.java (Student.java 상속)

package com.test02;

public class StudentA implements Student {

	@Override
	public void classWork() {
		System.out.println("컴퓨터를 켜서 뉴스를 본다.");

	}

}

StudentB.java (Student.java 상속)

package com.test02;

public class StudentB implements Student {

	@Override
	public void classWork() {
		System.out.println("컴퓨터를 켜서 주식을 본다.");

	}

}

MyAspect.java (MethodInterceptor 잘 보고 상속받아주세요)

package com.test02;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class MyAspect implements MethodInterceptor {

	@Override
	public Object invoke(MethodInvocation invocation) throws Throwable {
		Object target = null;
		
		System.out.println("출석한다.");
		
		try {
			target = invocation.proceed();
		} catch(Exception e) {
			System.out.println("쉬는날이었다.");
		} finally {
			System.out.println("집에간다.");
		}
		
		return target;
	}

}

MTest.java

package com.test02;

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

public class MTest {
	
	public static void main(String[] args) {
		ApplicationContext factory = new ClassPathXmlApplicationContext("com/test02/applicationContext.xml");
		
		Student a = factory.getBean("studentA", Student.class);
		Student b = (Student) factory.getBean("studentB");
		
		System.out.println("A 입장");
		a.classWork();
		System.out.println("--------------");
		System.out.println("B 입장");
		b.classWork();
	}

}

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	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.xsd">

	<bean id="studentA" class="com.test02.StudentA" />
	<bean id="studentB" class="com.test02.StudentB" />
	<bean id="myAdvice" class="com.test02.MyAspect" />
	
	<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" />
	
	<bean id="myAdvisor" class="org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor">
		<property name="advice" ref="myAdvice"/>
		<property name="expression" value="execution(public * *(..))" />
	</bean>
</beans>

코드 실행결과

실행 결과를 보게 되면 '출석한다.' 와 '집에간다.' 가 공통된 관심사항(CCC)이고

A에서는 '컴퓨터를 켜서 뉴스를 본다.', B에서는 '컴퓨터를 켜서 주식을 본다.' 가 주 관심사항(CC)이 됩니다.

좀 더 자세히 살펴보자면

MTest에서 보면 그냥 a호출, b호출이지만 Aspect가 Proxy가 돼서 대신 가져와 주는 부분을 보여줍니다.

 

가지고 올 수 있는 부분들을 Joinpoint, 실제 Proxy와 연결되어야 하는 부분이 Pointcut입니다.

Proxy가 신호를 인터셉터할 거라서 MyAspect에서 interceptor를 상속받았죠

그다음 타겟의 앞뒤에 CCC를 붙여줍니다. (이때 프록시 객체가 붙여줍니다.)

그걸 원래의 Target에서 신호를 받아와서 다시 MTest에 보내줍니다.

여기서 PointcutAdvice를 합쳐서 Advisor(Aspect)라고 부르고

이러한 과정 전체를 묶어서 작동하도록 해주는 것을 Weaving이라고 합니다.

 

이러한 느낌의 작업이 이루어지고 있습니다.

 

그렇다면 이걸 왜 사용해야 할까요?

스프링 AOP는 관점지향 프로그래밍이라고 설명했는데 이는 이런 로직을 기준으로 뭐가 핵심인지 아닌지 관점을 나누고 그 관점에 따라 각각 나누어서 모듈화 시키는 것입니다.

이 말은 반복해서 사용하는 부분을 분리해서 모듈화하고 해당 기능을 프로그램 코드에서 직접 명시하지 않고 선언으로 처리해서 핵심 로직에 영향을 미치지 않고 공통 모듈을 효과적으로 적용시키기 위한 것입니다.