일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- django
- Problems occurred while performing provisioning operation
- apache pythonpath
- The requested operation has failed!
- django 프로젝트 시작
- django httpd error
- 공유기 원격 설정
- django apache deploy error
- 18233 java
- 2661 좋은 수열
- 원격 연결 포트 포워딩
- 14711 java
- 2961 java
- django settings.py
- 18233 러버덕
- APPEND_SLASH = FALSE
- 1188 음식 평론가
- 14711 타일 뒤집기
- django The requested operation has failed!
- 18233 비트마스킹
- windows 원격 연결 설정
- 2661 java
- django windows 배포 에러
- 1188 java
- 2961 도영이가 만든 맛있는 음식
- windows apache wsgi 에러
- java di
- 2643 java
- 2643 색종이 올려 놓기
- django 웹 페이지
라이브러리는 도서관 아닌가요
Spring xml 설정으로 proxy를 사용해 AOP 적용 본문
메서드 invoke에서 다뤄지는 proxy 구현 대신,
xml 설정 파일을 이용해서 AOP를 적용할 수 있다.
(이전 invoke 관련 : https://verycrazy.tistory.com/31?category=1027221)
AOP를,
단순하게,
xml과 proxy만을 사용해서 설정할 때는,
setting.xml 파일에
타겟(클래스)과 핸들러만 설정해주면 된다.
<!-- 속성을 초기화해주는 Namespace p를 사용하기 위해 선언해주어야 함 -->
<bean id="target" class="패키지경로.myClass" p:x="1" p:y="2"></bean>
<!-- MethodInterceptor 인터페이스 구현 + invocation 객체 생성 후 .proceed()메서드 호출 + Exception 처리 -->
<bean id="logAroundPrint" class="패키지경로.LogPrint"/> <!-- Around 방식 -->
<!-- MethodBeforeAdvice 인터페이스 구현 + before 메서드 구현 -->
<bean id="logBeforePrint" class="패키지경로.LogPrint"/> <!-- Before 방식 -->
<!-- AfterReturningAdvice 인터페이스 구현 + afterReturning 메서드 구현 + returnValue 사용 가능 -->
<bean id="logAfterReturningPrint" class="패키지경로.LogPrint"/> <!-- After Returning 방식 -->
<!-- ThrowAdvice 인터페이스 구현 + 특정 메서드 구현 없음 ! (위의 메서드와 달리 고정된 인자가 없다.) -->
<!-- 대신 특정 Exception을 인자로 받아 처리를 수행한다. -->
<bean id="logAfterThrowingPrint" class="패키지경로.LogPrint"/> <!-- After 방식 -->
<!-- id의 proxy는 실제 그 proxy 역할을 하는 녀석 -->
<bean id="proxy" class="org.springframework.aop.framework.proxyFactoryBean">
<!-- ref가 가리키는 target 메서드가 호출된다. -->
<!-- property의 name은 setter명이다. 암묵적으로 앞에 set이 붙고 첫 글자 대문자로 변경 -->
<property name="target" ref="target">
<property name="interceptorNames"> <!-- 참고: 인터셉터는 복수로 들어간다, 아래처럼. -->
<list>
<value>logAroundPrint</value> <!-- Around -->
<value>logBeforePrint</value> <!-- Before -->
<value>logAfterReturningPrint</value> <!-- logAfter -->
<value>logAfterThrowingPrint</value> <!-- AfterThrowing -->
</list>
</property>
</bean>
설정을 변경함으로써 proxy를 이용해
추가적인 비즈니스 로직을 빼거나 꽂을 수 있다.
java 코드에서 berfore 메서드 따위를 이용해 훨씬 간결하게 구현할 수도 있다.
위는 proxy로 날 것(?)을 구현한 것이고, 아래부터는 스프링의 weaving 방식을 이용해 advisor를 도입해보자.
잊지 말아야 할 기본 핵심: Proxy를 이용해서 별도로 수행하는 작업을 주입한다.
* 포인트컷(pointcut, 잘라내는(?) 지점)
: Proxy 내부에서 실행될 주 업무 이외의 로직이 자리할 위치. before나 after 등에 주 업무 외의 업무가 수행된다.
* 조인포인트(joinPoint, 합류 지점)
: 주 업무 로직인 모든 타겟 메서드들이 조인포인트가 될 수 있다.
* 위빙(weaving, 뜨개질)
: 필요한 업무 메서드(조인포인트)를 포인트컷(Proxy 내부에서 실행될 주 업무 로직이 들어갈 위치)에 주입
즉 여기서 구현할 핵심적인 내용은 특정한 메서드만이 weaving이 되도록 joinpoint를 지정하는 것이다.
<!-- 속성을 초기화해주는 Namespace p를 사용하기 위해 선언해주어야 함 -->
<bean id="target" class="패키지경로.myClass" p:x="1" p:y="2"></bean>
<!-- MethodInterceptor 인터페이스 구현 + invocation 객체 생성 후 .proceed()메서드 호출 + Exception 처리 -->
<bean id="logAroundPrint" class="패키지경로.LogPrint"/> <!-- Around 방식 -->
<!-- MethodBeforeAdvice 인터페이스 구현 + before 메서드 구현 -->
<bean id="logBeforePrint" class="패키지경로.LogPrint"/> <!-- Before 방식 -->
<!-- AfterReturningAdvice 인터페이스 구현 + afterReturning 메서드 구현 + returnValue 사용 가능 -->
<bean id="logAfterReturningPrint" class="패키지경로.LogPrint"/> <!-- After Returning 방식 -->
<!-- ThrowAdvice 인터페이스 구현 + 특정 메서드 구현 없음 ! (위의 메서드와 달리 고정된 인자가 없다.) -->
<!-- 대신 특정 Exception을 인자로 받아 처리를 수행한다. -->
<bean id="logAfterThrowingPrint" class="패키지경로.LogPrint"/> <!-- After 방식 -->
<bean id="proxy" class="org.springframework.aop.framework.proxyFactoryBean">
<!-- property의 name은 setter명이다. 암묵적으로 앞에 set이 붙고 첫 글자 대문자로 변경 -->
<!-- value 또는 ref를 사용하는데 target은 현재 클래스이므로 참조 변수(ref)를 사용한다. -->
<property name="target" ref="target">
<property name="interceptorNames"> <!-- 참고: 인터셉터는 복수로 들어간다. 아래처럼. -->
<list>
<value>logAroundPrint</value> <!-- Around -->
<value>logBeforePrint</value> <!-- Before -->
<value>logAfterReturningPrint</value> <!-- logAfter -->
<value>logAfterThrowingPrint</value> <!-- AfterThrowing -->
</list>
</property>
</bean>
<!-- 특정 메서드를 기준으로 발생하는 포인트 컷 생성 -->
<bean id="myPointCut" class="org.springframework.aop.support.NameMatchMethodPointcut">
<property name="mappedName" value="특정_메서드명"></property>
</bean>
<!-- advice와 pointcut을 연결한 advisor 설정: 윗쪽에 미리 생성해놓은 Before advice를 가져온다. -->
<bean id="logBeforePrint" class="org.springframework.aop.support.DefaultPointcutAdvisor>
<property name="advice" ref=""></property>
<property name="pointcut" ref=""></property>
</bean>
<!-- advice와 pointcut을 연결한 advisor 설정: 윗쪽에 미리 생성해놓은 After advice를 가져온다. -->
<bean id="logAfterReturningPrint" class="org.springframework.aop.support.DefaultPointcutAdvisor>
<property name="advice" ref=""></property>
<property name="pointcut" ref=""></property>
</bean>
위에서 지정한 특정_메서드의 전후로 실행되는 pointcut 2개가 존재한다.
문제점: 딱 보인다. 코드의 중복. pointcut(혹은 advice) 하나당 advisor를 만들어야 하는 귀찮음이 존재한다.
Advisor 생성이 귀찮으니 뭔가 하나로 묶어서 사용할 수 있는 Advisor는 없을까?
있다 NameMatchMethodPointcutAdvisor
기존의 NameMatchMethodPointcut에서 Advisor를 결합한 녀석이다.
위에서 사용했던 코드 중 Pointcut과 하나의 Before Advisor를 생성하는 부분을 합쳐보자.
<!-- 특정 메서드를 기준으로 발생하는 포인트 컷 생성 -->
<bean id="myPointCut" class="org.springframework.aop.support.NameMatchMethodPointcut">
<property name="mappedName" value="특정_메서드명"></property>
</bean>
<!-- advice와 pointcut을 연결한 advisor 설정: 윗쪽에 미리 생성해놓은 Before advice를 가져온다. -->
<bean id="logBeforePrint" class="org.springframework.aop.support.DefaultPointcutAdvisor>
<property name="advice" ref=""></property>
<property name="pointcut" ref=""></property>
</bean>
...를 아래와 같이 변경한다.
<bean id="myPointCut" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<property name="advice" ref="logBeforePrint">
<property name="mappedName" value="특정_메서드명"></property>
</bean>
훨씬 간결해진다.
다음과 같이 메서드를 더 추가해줄 수도 있다.
<bean id="myPointCut" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<property name="advice" ref="logBeforePrint"></property>
<property name="mappedName">
<list>
<value>특정_메서드명1</value>
<value>특정_메서드명2</value>
<value>특정_메서드명3</value>
...
</list>
</property>
</bean>
위와 같이 메서드가 갈수록 많아질 수 있다. 이럴 때에는 정규식을 이용해 보다 편하게 등록할 수 있다.
RegexpMethodPointcutAdvisor를 적용해보자.
<bean id="myPointCut" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice" ref="logBeforePrint"></property>
<property name="mappedName">
<list>
<value>hello.*</value>
<value>.*my.*</value>
</list>
</property>
</bean>
뭔가 알록달록하게 되었다.