Spring transaction notification, 2.0

Source: Internet
Author: User
Tags throwable

Spring 1. in spring declarative transaction management, you can use the preinterceptors and postinterceptors attributes of transacationproxyfactorybean to set "before" or "after" notifications to provide additional interception behaviors, you can set any number of "before" and "after" notifications. Their types can be advisor, methodinterceptor, or notification types supported by the current spring configuration, such as beforeadvice and afterreturningadvice.

There are some doubts here. In the transaction declaration, if a transaction proxy is set to a notification for the preinterceptors attribute, according to the understanding in the spring document, this notification will be notified before the transaction method starts, and vice versa. But what if I set a notification for preinterceptors that implements the afterreturningadvice interface? What will happen to the execution result? Will the notification be sent before or after the method is executed? To solve this problem, I wrote a small example to simulate how the notifications in the transaction operate. Spring version 1.2.6.

First, a simple service and implementation

Myservice. Java

package com.ccb.tra;public interface MyService {public void getAll();}

 

Package com. CCB. TRA; public interface myservice {public void getall ();}

Myserviceimpl. Java

package com.ccb.tra;public class MyServiceImpl implements MyService{public void getAll() {try {System.out.println("getAll Method........");} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}}

 

Package COM. CCB. tra; import Java. lang. reflect. method; import Org. springframework. AOP. methodbeforeadvice; public class mybeforeadvice implements methodbeforeadvice {public void before (method, object [] object, object object0) throws throwable {system. out. println ("methodbeforeadvice ............. ");}}

Myinterceptor. Java

package com.ccb.tra;import org.aopalliance.intercept.MethodInterceptor;import org.aopalliance.intercept.MethodInvocation;public class MyInterceptor implements MethodInterceptor{public Object invoke(MethodInvocation invocation) throws Throwable {System.out.println("MethodInterceptor.................");return invocation.proceed();}}
Package COM. CCB. tra; import Org. aopalliance. intercept. methodinterceptor; import Org. aopalliance. intercept. methodinvocation; public class myinterceptor implements methodinterceptor {public object invoke (methodinvocation Invocation) throws throwable {system. out. println ("methodinterceptor ................. "); Return invocation. proceed ();}}

Myafteradvice. Java

package com.ccb.tra;import java.lang.reflect.Method;import org.springframework.aop.AfterReturningAdvice;public class MyAfterAdvice implements AfterReturningAdvice {public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {System.out.println("AfterReturningAdvice.............");}}

You can see that when each notification is used, a message is printed on the console. The functions of the interfaces implemented by the three notifications are not described too much. For usage instructions, see the spring development documentation.

Then, write the spring configuration file.

<? XML version = "1.0" encoding = "UTF-8"?> <! Doctype beans public "-// spring // DTD bean // en" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id = "datasource" class = "org. apache. commons. DBCP. basicdatasource "Destroy-method =" close "> <property name =" driverclassname "value =" oracle. JDBC. driver. oracledriver "/> <property name =" url "value =" JDBC: oracle: thin: @ 192.168.1.110: 1521: xmldb "/> <property name =" username "value =" neohkdev1 "/> <proper Ty name = "password" value = "XML"/> <property name = "initialsize" value = "5"/> <property name = "maxactive" value = "5 "/> </bean> <! -- Service target --> <bean id = "myservicetarget" class = "com. CCB. TRA. myserviceimpl"/> <! -- Before --> <bean id = "mybeforeadvice" class = "com. CCB. TRA. mybeforeadvice"/> <! -- Interceptor --> <bean id = "myinterceptor" class = "com. CCB. TRA. myinterceptor"/> <! -- Myafteradvice --> <bean id = "myafteradvice" class = "com. CCB. tra. myafteradvice "/> <bean id =" tramanager "class =" org. springframework. JDBC. datasource. datasourcetransactionmanager "> <property name =" datasource "> <ref local =" datasource "/> </property> </bean> <bean id =" myservice "class =" org. springframework. transaction. interceptor. transactionproxyfactorybean "> <property name =" transactionmanager "> <ref bean =" tramana GER "/> </property> <property name =" target "> <ref bean =" myservicetarget "/> </property> <! -- Preinterceptors attributes, contains three notifications --> <property name = "preinterceptors"> <list> <ref bean = "mybeforeadvice"/> <ref bean = "myinterceptor"/> <ref bean =" myafteradvice "/> </List> </property> <property name =" transactionattributes "> <props> <prop key =" get * "> propagation_required </prop> </props> </property> </bean> </beans>

In the configuration file, you can see that a simple transaction is defined for the service, and three notifications are defined, and these notifications are injected into the preinterceptors attribute of transactionproxyfactorybean, according to spring's description of the preinterceptors attribute, all three notifications will be executed before the service method is executed.

Write a simple test class to test their execution results
Main. Java

package com.ccb.tra;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class Main {public static void main(String[] args) {ApplicationContext ctx = new ClassPathXmlApplicationContext("tra.xml");MyService myService = (MyService)ctx.getBean("myService");myService.getAll();}}

Run main. Java to check the execution result.

MethodBeforeAdvice.............MethodInterceptor.................getAll Method........AfterReturningAdvice.............

It seems that the result is incorrect. The afterreturningadvice notification is executed only after the service method is executed. It is weird. It does not match the preinterceptors attribute described by spring, but it is consistent with the notification interface described in AOP, view the source code of transactionproxyfactorybean and find the operation method defined for these two attributes,

Public void afterpropertiesset () {This. transactioninterceptor. afterpropertiesset (); If (this.tar get = NULL) {Throw new illegalargumentexception ("'target' is required");} If (this.tar get instanceof string) {Throw new illegalargumentexception ("'target' needs to be a bean reference, not a bean name as value");} proxyfactory = new proxyfactory (); // preinterceptors attributes if (this. preinterceptors! = NULL) {for (INT I = 0; I <this. preinterceptors. length; I ++) {// note the code proxyfactory. addadvisor (this. advisoradapterregistry. wrap (this. preinterceptors [I]) ;}} if (this. pointcut! = NULL) {advisor advice = new defaultpointcutadvisor (this. pointcut, this. transactioninterceptor); proxyfactory. addadvisor (advice);} else {// rely on default pointcut. proxyfactory. addadvisor (New transactionattributesourceadvisor (this. transactioninterceptor); // cocould just do the following, but it's usually less efficient because of AOP advice chain caching. // proxyfactory. addadvice (transactionintercep Tor);} // postinterceptors attributes if (this. postinterceptors! = NULL) {for (INT I = 0; I <this. postinterceptors. length; I ++) {// note the code proxyfactory. addadvisor (this. advisoradapterregistry. wrap (this. postinterceptors [I]);} proxyfactory. copyfrom (this); targetsource = createtargetsource(this.tar get); proxyfactory. settargetsource (targetsource); If (this. proxyinterfaces! = NULL) {proxyfactory. setinterfaces (this. proxyinterfaces);} else if (! Isproxytargetclass () {// rely on AOP infrastructure to tell us what interfaces to proxy. proxyfactory. setinterfaces (classutils. getallinterfacesforclass (targetsource. gettargetclass ();} This. proxy = getproxy (proxyfactory );}

The role of the above Code is to inject the notifications contained in preinterceptors and postinterceptors into proxyfactory.

After a notification is injected into proxyfactory, proxyfactory is responsible for managing the notification. I want to manage the notification in the same way as that of common AOP, and determine the call sequence of the notification based on the interface implemented by the notification, transactionproxyfactorybean will give these notifications to proxyfactory and then let them go, and there is no difference in processing the notifications included in preinterceptors and postinterceptors.
Processing preinterceptors

 

if (this.preInterceptors != null) {for (int i = 0; i < this.preInterceptors.length; i++) {proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(this.preInterceptors[i]));}}

 

If (this. preinterceptors! = NULL) {for (INT I = 0; I <this. preinterceptors. length; I ++) {proxyfactory. addadvisor (this. advisoradapterregistry. wrap (this. preinterceptors [I]);}

Process postinterceptors

if (this.postInterceptors != null) {for (int i = 0; i < this.postInterceptors.length; i++) {proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(this.postInterceptors[i]));}}

In fact, the execution sequence of the notification is not determined by defining the notification in preinterceptors or postinterceptors, but by the notification implementation and which notification interface.

Spring 2.0 seems to have improved this. The <TX: Advice> label can be different, but there is no change in transactionproxyfactorybean. just inherit some methods from abstractsingletonproxyfactorybean? I'm studying. If you have any opinions, let's discuss them together.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.