Spring

[Spring] AOP 관점 지향 프로그래밍, Advice 동작시점

코딩 수달 2022. 9. 16. 11:26
반응형

AOP (Aspect Oriented Programming) - 관점 지향 프로그래밍 

관점 지향은 쉽게 말하면 어떤 로직을 기준으로 핵심적인 관점, 부가적인 관점으로 나누어서 보고

그 관점을 기준으로 각각 모듈화 하겠다는 것 

 

장점 : 중복코드 제거, 효율적인 유지보수, 높은 생산성, 재활용성 극대화, 변화 수용 용이 

 

AOP 언제 쓰는데? 
핵심로직(비즈니스 메서드, CRUD)에는 공통적으로 들어가는 로직이 존재함! 
== 공통로직(횡단관심) 
ex) 로깅, 예외처리, 트랜잭션, 보안(인증, 인가, 허가)...


어떤 횡단관심들을 
어떤 핵심로직에 연결할지 "설정" 
=> AOP설정 


< AOP 용어 정리 >

Aspect

"결합" 
횡단관심+포인트컷(핵심로직)

위에서 설명한 흩어진 관심사를 모듈화 한 것. 주로 부가기능을 모듈화함.

 

Target

Aspect를 적용하는 곳 (클래스, 메서드 .. )

 

Advice

횡단관심 (트랜잭션, 로그, 보안, 인증 등) 

실질적으로 어떤 일을 해야할 지에 대한 것, 실질적인 부가기능을 담은 구현체

 

JointPoint

Advice가 적용될 위치, 끼어들 수 있는 지점.

메서드 진입 지점, 생성자 호출 시점, 필드에서 값을 꺼내올 때 등 다양한 시점에 적용가능

 

PointCut

회단관심을 적용할 핵심 로직을 의미 

JointPoint의 상세한 스펙을 정의한 것.

'A란 메서드의 진입 시점에 호출할 것'과 같이 더욱 구체적으로 Advice가 실행될 지점을 정할 수 있음


Advice 동작시점

before, after, after-returning, after-throwing, around  5가지의 동작 시점이 존재

 

어드바이스는 횡단 관심에 해당하는 공통 기능의 코드를 의미하며, 독립된 클래스의 메소드로 작성

그리고 어드바이스로 구현된 메소드가 언제 동작할지를 스프링설정파일을 통해 지정할 수 있음 

 

Before

-   비즈니스 메소드 실행 전 동작

 

After Returning

-   비즈니스 메소드가 성공적으로 리턴되면 동작

     (단, 메소드 내부에 리턴값이 존재하는 경우)

 

After Throwing

-   비즈니스 메소드 실행 중, 예외가 발생하면 동작

     (예를들면 try~catch 블록의 catch 부분에 해당!)

 

After

-   비즈니스 메소드가 실행된 후,  !무조건!  실행

     (예를들면 try~catch 블록에서 finally 부분에 해당!)

 

Around

-   메소드 호출 자체를 가로채서 비즈니스 메소드 실행 전&후 모두에 처리할 로직을 삽입할 수 있음


AOP 라이브러리 추가

 

AOP를 적용하기 위해서 poem.xml 파일에 라이브러리 추가

	<!-- AOP -->
      <dependency>
         <groupId>org.aspectj</groupId>
         <artifactId>aspectjrt</artifactId>
         <version>${org.aspectj-version}</version>
      </dependency>
      <dependency>
         <groupId>org.aspectj</groupId>
         <artifactId>aspectjweaver</artifactId>
         <version>1.8.8</version>
      </dependency>

저장 후 "Maven Dependencies" 에 설정한대로 라이브러리가 변경되었는지 확인 

 


aop 네임스페이스를 추가

 

스프링 설정파일 (applicationContext.xml)에서 AOP태그를 사용하려면 

aop 네임스페이스를 추가 해야함 


LogAdvice.java

package com.kim.biz.common;

	public class LogAdvice {
		public void printLog() {
			System.out.println(">>> 공통로직 <<<     핵심로직 수행전에 호출");
		}
}

※ 포인트컷 표현식

execution() : 가장 대표적이고 강력한 지시자로, 접근제어자, 리턴 타입, 타입 패턴, 메서드, 파라미터 타입, 예외 타입 등을 조합해서 메서드까지 선택가능한 가장 정교한 포인트컷을 만들수 있다.
execution([수식어] 리턴타입 [클래스이름].이름(파라미터)

execution(public Integer com.edu.aop.*.*(*))
 - com.edu.aop 패키지에 속해있고, 파라미터가 1개인 모든 메서드

execution(* com.edu..*.get*(..))
 - com.edu 패키지 및 하위 패키지에 속해있고, 이름이 get으로 시작하는 파라미터가 0개 이상인 모든 메서드 

execution(* com.edu.aop..*Service.*(..))
 - com.edu.aop 패키지 및 하위 패키지에 속해있고, 이름이 Service르 끝나는 인터페이스의 파라미터가 0개 이상인 모든 메서드

execution(* com.edu.aop.BoardService.*(..))
 - com.edu.aop.BoardService 인터페이스에 속한 파마리터가 0개 이상인 모든 메서드

execution(* some*(*, *))
 - 메서드 이름이 some으로 시작하고 파라미터가 2개인 모든 메서드

설정파일

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">

<context:component-scan base-package="com.kim.biz" />



<bean id="LogAdvice" class="com.kim.biz.common.LogAdvice" />

<aop:config>
	<aop:pointcut expression="execution(* com.kim.biz..*Impl.*(..))" id="aPointcut"/>
	<aop:aspect ref="LogAdvice">
		<aop:before method="printLog" pointcut-ref="aPointcut"/>
	</aop:aspect>
</aop:config>

</beans>

실행화면

 


실습

 

select류를 수행하면 "데이터를 탐색합니다..."라는 로그를 남길 수 있게 aspect 처리하라.

(applicationContext.xml(스프링설정파일)에 aop설정하라는 뜻)

 

LogSelectAdvice

package com.kim.biz.common;

public class LogSelectAdvice {
	public void printLogSelect() {
		System.out.println("데이터를 탐색합니다....");
	}
}

표현식 부분 수정

execution(* com.kim.biz..*Impl.select*(..))

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">

<context:component-scan base-package="com.kim.biz"/>

<bean id="LogSelectAdvice" class="com.kim.biz.common.LogSelectAdvice"/>

<aop:config>
	<aop:pointcut expression="execution(* com.kim.biz..*Impl.*(..))" id="aPointcut"/>
    <aop:pointcut expression="execution(* com.kim.biz..*Impl.select*(..))" id="bPointcut"/>

	<aop:aspect ref="LogSelectAdvice">
		<aop:before method="printLogSelect" pointcut-ref="bPointcut"/>
	</aop:aspect>
	
</aop:config>
</beans>

 

 

 

반응형