001/* 002 * Copyright 2002-2014 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.transaction.interceptor; 018 019import java.io.IOException; 020import java.io.ObjectInputStream; 021import java.io.ObjectOutputStream; 022import java.io.Serializable; 023import java.util.Properties; 024 025import org.aopalliance.intercept.MethodInterceptor; 026import org.aopalliance.intercept.MethodInvocation; 027 028import org.springframework.aop.support.AopUtils; 029import org.springframework.beans.factory.BeanFactory; 030import org.springframework.transaction.PlatformTransactionManager; 031 032/** 033 * AOP Alliance MethodInterceptor for declarative transaction 034 * management using the common Spring transaction infrastructure 035 * ({@link org.springframework.transaction.PlatformTransactionManager}). 036 * 037 * <p>Derives from the {@link TransactionAspectSupport} class which 038 * contains the integration with Spring's underlying transaction API. 039 * TransactionInterceptor simply calls the relevant superclass methods 040 * such as {@link #invokeWithinTransaction} in the correct order. 041 * 042 * <p>TransactionInterceptors are thread-safe. 043 * 044 * @author Rod Johnson 045 * @author Juergen Hoeller 046 * @see TransactionProxyFactoryBean 047 * @see org.springframework.aop.framework.ProxyFactoryBean 048 * @see org.springframework.aop.framework.ProxyFactory 049 */ 050@SuppressWarnings("serial") 051public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable { 052 053 /** 054 * Create a new TransactionInterceptor. 055 * <p>Transaction manager and transaction attributes still need to be set. 056 * @see #setTransactionManager 057 * @see #setTransactionAttributes(java.util.Properties) 058 * @see #setTransactionAttributeSource(TransactionAttributeSource) 059 */ 060 public TransactionInterceptor() { 061 } 062 063 /** 064 * Create a new TransactionInterceptor. 065 * @param ptm the default transaction manager to perform the actual transaction management 066 * @param attributes the transaction attributes in properties format 067 * @see #setTransactionManager 068 * @see #setTransactionAttributes(java.util.Properties) 069 */ 070 public TransactionInterceptor(PlatformTransactionManager ptm, Properties attributes) { 071 setTransactionManager(ptm); 072 setTransactionAttributes(attributes); 073 } 074 075 /** 076 * Create a new TransactionInterceptor. 077 * @param ptm the default transaction manager to perform the actual transaction management 078 * @param tas the attribute source to be used to find transaction attributes 079 * @see #setTransactionManager 080 * @see #setTransactionAttributeSource(TransactionAttributeSource) 081 */ 082 public TransactionInterceptor(PlatformTransactionManager ptm, TransactionAttributeSource tas) { 083 setTransactionManager(ptm); 084 setTransactionAttributeSource(tas); 085 } 086 087 088 @Override 089 public Object invoke(final MethodInvocation invocation) throws Throwable { 090 // Work out the target class: may be {@code null}. 091 // The TransactionAttributeSource should be passed the target class 092 // as well as the method, which may be from an interface. 093 Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null); 094 095 // Adapt to TransactionAspectSupport's invokeWithinTransaction... 096 return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() { 097 @Override 098 public Object proceedWithInvocation() throws Throwable { 099 return invocation.proceed(); 100 } 101 }); 102 } 103 104 105 //--------------------------------------------------------------------- 106 // Serialization support 107 //--------------------------------------------------------------------- 108 109 private void writeObject(ObjectOutputStream oos) throws IOException { 110 // Rely on default serialization, although this class itself doesn't carry state anyway... 111 oos.defaultWriteObject(); 112 113 // Deserialize superclass fields. 114 oos.writeObject(getTransactionManagerBeanName()); 115 oos.writeObject(getTransactionManager()); 116 oos.writeObject(getTransactionAttributeSource()); 117 oos.writeObject(getBeanFactory()); 118 } 119 120 private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { 121 // Rely on default serialization, although this class itself doesn't carry state anyway... 122 ois.defaultReadObject(); 123 124 // Serialize all relevant superclass fields. 125 // Superclass can't implement Serializable because it also serves as base class 126 // for AspectJ aspects (which are not allowed to implement Serializable)! 127 setTransactionManagerBeanName((String) ois.readObject()); 128 setTransactionManager((PlatformTransactionManager) ois.readObject()); 129 setTransactionAttributeSource((TransactionAttributeSource) ois.readObject()); 130 setBeanFactory((BeanFactory) ois.readObject()); 131 } 132 133}