Java/Spring

[Spring] 12 -1 AOP 적용하기 ( Namespace - aop)

담크 2021. 7. 4. 23:51

저번 포스팅에 이어서 이번에는 AOP를 적용하는 방법중에 namespace를 이용하는 방법을 사용해보겠습니다.

바로 패키지 만들러 가볼까요~

Student.java(interface)

package com.test03;

public interface Student {
	
	void classWork();

}

StudentA.java

package com.test03;

public class StudentA implements Student {

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

	}
}

StudentB.java

package com.test03;

public class StudentB implements Student {

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

	}
}

MyAspect.java

package com.test03;

public class MyAspect {
	
	public void before() {
		System.out.println("출석한다.");
	}
	
	public void after() {
		System.out.println("집에간다");
	}

}

MTest.java

package com.test03;

public class MyAspect {
	
	public void before() {
		System.out.println("출석한다.");
	}
	
	public void after() {
		System.out.println("집에간다");
	}

}

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"
	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/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

	<bean id="studentA" class="com.test03.StudentA" />
	<bean id="studentB" class="com.test03.StudentB" />
	<bean id="myAspect" class="com.test03.MyAspect" />
	
	<aop:config>
		<aop:aspect ref="myAspect">
			<aop:before method="before" pointcut="execution(public * *(..))"/>
			<aop:after method="after" pointcut="execution(public * *(..))"/>
		</aop:aspect>
	</aop:config>
</beans>

코드 실행결과

이번엔 appicationContext를 만들고 namespace에서 aop를 눌러 추가해줍니다.

여기서는 studentA, b는 각각 CC를 가지고 있고, CCC는 aspect의 before, after로 만들어 빼줬습니다.

applicationContext의 aop는 before, after를 나누어 pointcut의 위치를 지정해 줄 수 있는데요

이는 before, after를 각각 누구한테? 어떤 타이밍에? 연결할것인지 지정해 주는것 입니다.

 

그렇다면 execution(public * *(..))는 무슨 의미일까요?

첫번째 별의 위치는 리턴타입을 가집니다. (이 때 *이 의미하는 것은 뭐든지 상관없이 다 연결해준다 입니다.)

 

두번째 별의 위치는 메소드이름을 적어주는 칸 입니다.

 

세번째 ( . . )은 파라미터의 개수가 몇개든 상관없다는 의미를 가집니다.

 

따라서 코드를 실행했을 때 MTest에서 호출하는 그대로 before, after가 전부 출력이 잘 되는것을 볼 수 있습니다.

무슨의미인지 아직 잘 모르겠다면

pointcut="execution(public void com.test03.StudentA.classWork())"/> 이렇게 바꿔보면 어떻게 바뀔까요?

이렇게 바꾸면 코드 실행결과는

이렇게 바뀝니다.

이유는 com.test03.StudentA.classWork가 호출될 때만 before를 연결해달라 라는 의미를 가지기 때문에

B가 호출될 때는 출력되지 않는것 입니다.

 

이걸 좀더 자세히 알아보고싶다면

MyAspcet로 잠시 가보겠습니다.

여기서 JoinPoint를 만들어주고 (aspectj.lang에 임포트 해주셔야합니다!!)

join.getTarget().getClass()  -  호출하는 타겟의 클래스

join.getSignature().getName()  -  어떤 메소드를 실행했는지

알아보면

이렇게 확인이 가능합니다.