Loading...
Spring Framework Reference Documentation 7.0.2의 Advising Transactional Operations의 한국어 번역본입니다.
아래의 경우에 피드백에서 신고해주신다면 반영하겠습니다.
감사합니다 :)
가령 transactional operation과 몇 가지 기본적인 profiling advice를 둘 다 실행하고 싶다고 가정해 보겠습니다.
<tx:annotation-driven/>의 context에서 이것을 어떻게 구현할 수 있을까요?
updateFoo(Foo) 메서드를 호출할 때, 다음과 같은 action이 발생하기를 원합니다:
이 chapter는 (transaction에 적용되는 부분을 제외하고는) AOP를 자세히 설명하는 데 관심이 없습니다. AOP 설정과 일반적인 AOP에 대한 자세한 내용은 AOP를 참조하세요.
다음 코드는 앞에서 설명한 simple profiling aspect를 보여 줍니다:
1package x.y; 2 3import org.aspectj.lang.ProceedingJoinPoint; 4import org.springframework.util.StopWatch; 5import org.springframework.core.Ordered; 6 7public class SimpleProfiler implements Ordered { 8 9 private int order; 10 11 // allows us to control the ordering of advice 12 public int getOrder() { 13 return this.order; 14 } 15 16 public void setOrder(int order) { 17 this.order = order; 18 } 19 20 // this method is the around advice 21 public Object profile(ProceedingJoinPoint call) throws Throwable { 22 Object returnValue; 23 StopWatch clock = new StopWatch(getClass().getName()); 24 try { 25 clock.start(call.toShortString()); 26 returnValue = call.proceed(); 27 } finally { 28 clock.stop(); 29 System.out.println(clock.prettyPrint()); 30 } 31 return returnValue; 32 } 33}
1package x.y 2 3import org.aspectj.lang.ProceedingJoinPoint 4import org.springframework.util.StopWatch 5import org.springframework.core.Ordered 6 7class SimpleProfiler : Ordered { 8 9 private var order: Int = 0 10 11 // allows us to control the ordering of advice 12 override fun getOrder(): Int { 13 return this.order 14 } 15 16 fun setOrder(order: Int) { 17 this.order = order 18 } 19 20 // this method is the around advice 21 fun profile(call: ProceedingJoinPoint): Any { 22 var returnValue: Any 23 val clock = StopWatch(javaClass.name) 24 try { 25 clock.start(call.toShortString()) 26 returnValue = call.proceed() 27 } finally { 28 clock.stop() 29 println(clock.prettyPrint()) 30 } 31 return returnValue 32 } 33}
advice의 ordering은 Ordered 인터페이스를 통해 제어됩니다.
advice ordering에 대한 전체 내용은
Advice ordering을 참조하세요.
다음 설정은 profiling과 transactional aspect가 원하는 순서로 적용된 fooService 빈을 생성합니다:
1<?xml version="1.0" encoding="UTF-8"?> 2<beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:aop="http://www.springframework.org/schema/aop" 5 xmlns:tx="http://www.springframework.org/schema/tx" 6 xsi:schemaLocation=" 7 http://www.springframework.org/schema/beans 8 https://www.springframework.org/schema/beans/spring-beans.xsd 9 http://www.springframework.org/schema/tx 10 https://www.springframework.org/schema/tx/spring-tx.xsd 11 http://www.springframework.org/schema/aop 12 https://www.springframework.org/schema/aop/spring-aop.xsd"> 13 14 <bean id="fooService" class="x.y.service.DefaultFooService"/> 15 16 <!-- this is the aspect --> 17 <bean id="profiler" class="x.y.SimpleProfiler"> 18 <!-- run before the transactional advice (hence the lower order number) --> 19 <property name="order" value="1"/> 20 </bean> 21 22 <tx:annotation-driven transaction-manager="txManager" order="200"/> 23 24 <aop:config> 25 <!-- this advice runs around the transactional advice --> 26 <aop:aspect id="profilingAspect" ref="profiler"> 27 <aop:pointcut id="serviceMethodWithReturnValue" 28 expression="execution(!void x.y..*Service.*(..))"/> 29 <aop:around method="profile" pointcut-ref="serviceMethodWithReturnValue"/> 30 </aop:aspect> 31 </aop:config> 32 33 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> 34 <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/> 35 <property name="url" value="jdbc:oracle:thin:@rj-t42:1521:elvis"/> 36 <property name="username" value="scott"/> 37 <property name="password" value="tiger"/> 38 </bean> 39 40 <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 41 <property name="dataSource" ref="dataSource"/> 42 </bean> 43 44</beans>
유사한 방식으로 원하는 만큼의 추가 aspect를 설정할 수 있습니다.
다음 example은 앞의 두 example과 동일한 setup을 생성하지만 순수하게 XML 선언적 approach를 사용합니다:
1<?xml version="1.0" encoding="UTF-8"?> 2<beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:aop="http://www.springframework.org/schema/aop" 5 xmlns:tx="http://www.springframework.org/schema/tx" 6 xsi:schemaLocation=" 7 http://www.springframework.org/schema/beans 8 https://www.springframework.org/schema/beans/spring-beans.xsd 9 http://www.springframework.org/schema/tx 10 https://www.springframework.org/schema/tx/spring-tx.xsd 11 http://www.springframework.org/schema/aop 12 https://www.springframework.org/schema/aop/spring-aop.xsd"> 13 14 <bean id="fooService" class="x.y.service.DefaultFooService"/> 15 16 <!-- the profiling advice --> 17 <bean id="profiler" class="x.y.SimpleProfiler"> 18 <!-- run before the transactional advice (hence the lower order number) --> 19 <property name="order" value="1"/> 20 </bean> 21 22 <aop:config> 23 <aop:pointcut id="entryPointMethod" expression="execution(* x.y..*Service.*(..))"/> 24 <!-- runs after the profiling advice (cf. the order attribute) --> 25 26 <aop:advisor advice-ref="txAdvice" pointcut-ref="entryPointMethod" order="2"/> 27 <!-- order value is higher than the profiling aspect --> 28 29 <aop:aspect id="profilingAspect" ref="profiler"> 30 <aop:pointcut id="serviceMethodWithReturnValue" 31 expression="execution(!void x.y..*Service.*(..))"/> 32 <aop:around method="profile" pointcut-ref="serviceMethodWithReturnValue"/> 33 </aop:aspect> 34 35 </aop:config> 36 37 <tx:advice id="txAdvice" transaction-manager="txManager"> 38 <tx:attributes> 39 <tx:method name="get*" read-only="true"/> 40 <tx:method name="*"/> 41 </tx:attributes> 42 </tx:advice> 43 44 <!-- other <bean/> definitions such as a DataSource and a TransactionManager here --> 45 46</beans>
앞선 설정의 결과는 profiling과 transactional aspect가 그 순서로 적용된 fooService 빈입니다.
profiling advice가 들어가는 시점에는 transactional advice 다음에, 나오는 시점에는 transactional advice 전에 실행되도록 하려면,
profiling aspect 빈의 order 프로퍼티 값을 transactional advice의 order 값보다 더 높게 바꾸면 됩니다.
추가 aspect는 유사한 방식으로 설정할 수 있습니다.
Transaction Propagation
Using @Transactional with AspectJ