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.