본문 바로가기
Java . Spring . Web . SQL

[AOP] AOP 용어 및 기본 설정

by heidish 2020. 10. 14.
반응형

 

 

 

 

 

 

AOP를 제대로 사용하려면 AOP 관련 용어를 잘 알아야하니

다 외우자!

 

(각각에 대한 자세한 전체 코드는 수업 게시판에 있음)

heidish.tistory.com/68?category=887330

 

AOP 용어 및 기본 설정 - 예제

교재 P157- Joinpoint & Pointcut 기존의 applicationContext.xml 에서 코드 추가 * applicationContext.xml * BoardServiceClient.java 메인클래스 실행 실행 결과 INFO..

heidish.tistory.com

 

 

 


 

 

AOP 엘리먼트

 


 

<aop:config>

AOP 설정에서의 루트엘리먼트.

즉, 모든 AOP 전체설정을 감싸는 태그!

 

스프링 설정 파일 내에서 <aop:config> 태그는 여러번 사용이 가능하며

자식태그로는  <aop:pointcut> & <aop:aspect>  엘리먼트가 있다.

 

 

 

<aop:pointcut>

포인트컷을 지정할때 사용하는 엘리먼트,

여러개 정의할 수 있음!

 

유일한 id를 할당해서 애스팩트를 설정할 때 포인트컷을 참조하는 용도로 사용할 수 있다.

 

<aop:config>나 <aop:aspect>의 자식 엘리먼트로 사용할 수 있음

 

<aop:config>의 자식태그로 사용할 때  =>  다른 모든 aspect 에서 사용 가능

<aop:aspect>의 자식태그로 사용할 때  =>  해당 aspect 에서만 사용 가능

 

 

 

<aop:aspect>

애스팩트를 설정하는 엘리먼트

 

핵심 관심에 해당하는 포인트컷 메소드와, 횡단 관심에 해당하는 어드바이스 메소드를 결합시키는 역할!

 

애스팩트 설정에 따라 위빙 결과가 달라지기 때문에 AOP 에서 가장 중요한 설정이다..!

 

 

 

 

<aop:advisor>

<aop:aspect>와 동일한 역할로,

포인트컷 & 어드바이스 를 결합시켜준다.

 

단, 트랜잭션 설정같은 몇몇 특수한 경우에만 <aop:advisor>를 사용한다!

 

 

 



 

Joinpoint  (조인포인트)

 

-  클라이언트가 호출하는 '모든' '비즈니스 로직을 갖고있는' '비즈니스 메소드'

 

-  조인포인트는 '포인트컷 대상' 또는 '포인트컷 후보' 라고도 부르는데,

    조인포인트중에서 포인트컷이 선택되기 때문이다.

 

예를 들면 BoardServiceImpl 이나 UserServiceImpl 클래스의 모든 메소드가 조인포인트이다.

 

 

 


 

Pointcut  (포인트컷)

 

<aop:pointcut>

 

-  포인트컷이란 필터링된 조인포인트!

 

-  조인포인트가 모든 메소드를 의미한다면, 포인트컷은 선택된(필터링된) 메소드이다.

 

예를들어, 트랜잭션을 처리하는 공통 기능을 만들었다고 가정하자.

이때 횡단관심 기능은 등록, 수정, 삭제 기능을 하는 비즈니스 메소드들에 대해서는 당연히 작동해야 하지만,

검색 기능을 하는 비즈니스 메소드에 대해서는 트랜잭션과 무관하기 때문에 동작할 필요가 없다.

 

이렇게 많은 비즈니스 메소드 중, 우리가 원하는 특정 메소드에 대해서만 횡단관심에 해당하는 공통 기능을 수행하도록 만들기 위해서 필요한게 포인트컷이다.

포인트컷을 이용하면 메소드가 포함된 클래스, 패키지는 물론이고 메소드 시그니처까지 정확히 지정할 수 있다.

 

포인트컷은 <aop:pointcut> 엘리먼트로 지정하고,

id 속성으로 포인트컷을 식별하기 위한 유일한 문자열을 선언한다.

이 id 값이 나중에 포인트컷을 참조할 때 사용된다!

 

 

ex )

<?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.heidi.biz"></context:component-scan>
	
	<bean id="log" class="com.heidi.biz.board.common.LogAdvice"></bean>
	
	<aop:config>
		<aop:pointcut expression="execution(* com.heidi.biz..*Impl.*(..))" id="allPointcut"/>
		<aop:pointcut expression="execution(* com.heidi.biz..*Impl.get*(..))" id="getPointcut"/>
		<aop:aspect ref="log">
			<aop:before method="printLog" pointcut-ref="allPointcut" />
		</aop:aspect>
	</aop:config>

</beans>

applicationContext.xml 문서에 위와 같이 지정할 수 있다.

 

포인트컷 부분만 좀 더 자세히 살펴보면,

<context:component-scan base-package="com.heidi.biz"></context:component-scan>
	
<bean id="log" class="com.heidi.biz.board.common.LogAdvice"></bean>
	
<aop:config>
	<aop:pointcut expression="execution(* com.heidi.biz..*Impl.*(..))" id="allPointcut"/>
	<aop:pointcut expression="execution(* com.heidi.biz..*Impl.get*(..))" id="getPointcut"/>
	<aop:aspect ref="log">
		<aop:before method="printLog" pointcut-ref="allPointcut" />
	</aop:aspect>
</aop:config>

<aop:pointcut expression="표현식(필터링할 메소드)" id="포인트컷이름">

 

 

이런식으로 써줄 수 있다.

 

expression 속성이 가장 중요한데, 이 값을 어떻게 설정하느냐에 따라서 필터링되는 메소드가 달라진다 !

표현식을 좀 더 자세히 뜯어보면 아래와 같다.

 

리턴타입을 모든 타입으로 지정

com.heidi.biz..  패키지 경로를 com.heidi.biz 로 시작하는 모든 패키지로 지정

*Impl  클래스명은 Impl로 끝나는 클래스로 지정

*(..)  메소드명은 모든 메소드명으로, 매개변수도 모든 타입으로 지정

(  get*(..)  의 경우, 메소드명이 get 으로 시작하는 모든 메소드, 매개변수는 모든 타입으로 지정한것  )

 

 

 


 

Advice  (어드바이스)

 

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

 

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

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

 

 

 

ex )

<?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.heidi.biz"></context:component-scan>
	
	<bean id="log" class="com.heidi.biz.board.common.LogAdvice"></bean>
	
	<aop:config>
		<aop:pointcut expression="execution(* com.heidi.biz..*Impl.*(..))" id="allPointcut"/>
		<aop:pointcut expression="execution(* com.heidi.biz..*Impl.get*(..))" id="getPointcut"/>
		<aop:aspect ref="log">
			<aop:after method="printLog" pointcut-ref="getPointcut" />
		</aop:aspect>
	</aop:config>

</beans>

기존에 작성했던 applicationContext.xml 파일에서,

<aop:config> 태그 내의 <aop:aspect> 태그의, <aop:before ~> 태그를 <aop:after ~> 로 수정했다.

또 pointcut-ref 속성을 allPointcut=>getPointcut 으로 수정했다.

 

 

실행해보면 아래와 같이 결과가 콘솔창에 나온다.

INFO : org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [applicationContext.xml]
INFO : org.springframework.context.support.GenericXmlApplicationContext - Refreshing org.springframework.context.support.GenericXmlApplicationContext@7dc5e7b4: startup date [Wed Oct 14 12:38:25 KST 2020]; root of context hierarchy
INFO : org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor - JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
==> JDBC로 insertBoard() 기능 처리
==> JDBC로 getBoardList() 기능 처리
[공통로그] 비즈니스 로직 수행 전 동작
==> BoardVO [seq=6, title=임시 제목, writer=전소현, content=임시내용, regDate=2020-10-14, cnt=0]
==> BoardVO [seq=5, title=임시 제목, writer=전소현, content=임시내용, regDate=2020-10-14, cnt=0]
==> BoardVO [seq=4, title=임시 제목, writer=전소현, content=임시내용, regDate=2020-10-14, cnt=0]
==> BoardVO [seq=3, title=임시 제목, writer=전소현, content=임시내용, regDate=2020-10-14, cnt=0]
==> BoardVO [seq=2, title=임시 제목, writer=전소현, content=임시내용, regDate=2020-10-13, cnt=0]
==> BoardVO [seq=1, title=test, writer=test, content=test, regDate=2020-10-13, cnt=0]
INFO : org.springframework.context.support.GenericXmlApplicationContext - Closing org.springframework.context.support.GenericXmlApplicationContext@7dc5e7b4: startup date [Wed Oct 14 12:38:25 KST 2020]; root of context hierarchy

get~ 으로 시작하는 메서드의 경우에만 printLog 메서드가 동작하도록 설정해주었고,

동작 시점을 <aop:after> 태그를 이용해, 메소드가 실행된 후로 지정했기 때문에

getBoardList() 메소드가 실행된 후에 로그가 찍힌 것이다.

 

 

 

 

어드바이스 동작 시점에 관한 자세한 내용과 예시는 다음 포스트에 있으니 참고하기!

 

 

 


 

Weaving  (위빙)

 

-  포인트컷으로 지정한 핵심 관심 메소드가 호출될 때, 어드바이스에 해당하는 횡단 관심 메소드가 삽입되는 과정.

 

위빙을 통해서 비즈니스 메소드를 수정하지 않고도

횡단 관심에 해당하는 기능을 추가하거나 변경할 수 있다.

 

위빙을 처리하는 방식은 크게 Compiletime(컴파일타임)위빙, Loadingtime(로딩타임)위빙, Runtime(런타임)위빙 이 있는데, 스프링에서는 런타임 위빙 방식만 지원하고 있다.

 

 

 


 

 

Aspect  (애스팩트)  &  Advisor  (어드바이저)

 

<aop:aspect>

 

-  포인트컷과 어드바이스를 결합시키는 역할

 

-  AOP의 핵심!

 

어떤 포인트컷 메소드에 대해서 어떤 어드바이스 메소드를 실행할지 결정해준다.

애스팩트 설정에 따라서 AOP의 동작 방식이 결정되기 때문에 AOP 용어 중 가장 중요하다고 볼 수 있다.

 

원래 애스팩트를 설정할 땐 <aop:aspect> 태그를 사용하지만,

트랜잭션 설정과 같은 특수한 상황에서는 <aop:advisor> 태그를 사용한다!

애스팩트와 어드바이저는 같은 의미의 용어라는걸 알아두자.

 

(트랜잭션 설정에 관한 글은 트랜잭션 포스트를 참고하자!)

 

 

 

ex )

<?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.heidi.biz"></context:component-scan>
	
	<bean id="log" class="com.heidi.biz.board.common.LogAdvice"></bean>
	
	<aop:config>
		<aop:pointcut expression="execution(* com.heidi.biz..*Impl.*(..))" id="allPointcut"/>
		<aop:pointcut expression="execution(* com.heidi.biz..*Impl.get*(..))" id="getPointcut"/>
		<aop:aspect ref="log">
			<aop:after method="printLog" pointcut-ref="getPointcut" />
		</aop:aspect>
	</aop:config>

</beans>

<aop:aspect> 태그에 의해서 만들어놓은 포인트컷인 getPointcut과 LogAdvice의 객체인 log 를 결합시킨 것임!

 

 

 

 

반응형

댓글