001/* 002 * Copyright 2002-2020 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.lang.Nullable; 031import org.springframework.transaction.PlatformTransactionManager; 032import org.springframework.transaction.TransactionManager; 033 034/** 035 * AOP Alliance MethodInterceptor for declarative transaction 036 * management using the common Spring transaction infrastructure 037 * ({@link org.springframework.transaction.PlatformTransactionManager}/ 038 * {@link org.springframework.transaction.ReactiveTransactionManager}). 039 * 040 * <p>Derives from the {@link TransactionAspectSupport} class which 041 * contains the integration with Spring's underlying transaction API. 042 * TransactionInterceptor simply calls the relevant superclass methods 043 * such as {@link #invokeWithinTransaction} in the correct order. 044 * 045 * <p>TransactionInterceptors are thread-safe. 046 * 047 * @author Rod Johnson 048 * @author Juergen Hoeller 049 * @see TransactionProxyFactoryBean 050 * @see org.springframework.aop.framework.ProxyFactoryBean 051 * @see org.springframework.aop.framework.ProxyFactory 052 */ 053@SuppressWarnings("serial") 054public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable { 055 056 /** 057 * Create a new TransactionInterceptor. 058 * <p>Transaction manager and transaction attributes still need to be set. 059 * @see #setTransactionManager 060 * @see #setTransactionAttributes(java.util.Properties) 061 * @see #setTransactionAttributeSource(TransactionAttributeSource) 062 */ 063 public TransactionInterceptor() { 064 } 065 066 /** 067 * Create a new TransactionInterceptor. 068 * @param ptm the default transaction manager to perform the actual transaction management 069 * @param tas the attribute source to be used to find transaction attributes 070 * @since 5.2.5 071 * @see #setTransactionManager 072 * @see #setTransactionAttributeSource 073 */ 074 public TransactionInterceptor(TransactionManager ptm, TransactionAttributeSource tas) { 075 setTransactionManager(ptm); 076 setTransactionAttributeSource(tas); 077 } 078 079 /** 080 * Create a new TransactionInterceptor. 081 * @param ptm the default transaction manager to perform the actual transaction management 082 * @param tas the attribute source to be used to find transaction attributes 083 * @see #setTransactionManager 084 * @see #setTransactionAttributeSource 085 * @deprecated as of 5.2.5, in favor of 086 * {@link #TransactionInterceptor(TransactionManager, TransactionAttributeSource)} 087 */ 088 @Deprecated 089 public TransactionInterceptor(PlatformTransactionManager ptm, TransactionAttributeSource tas) { 090 setTransactionManager(ptm); 091 setTransactionAttributeSource(tas); 092 } 093 094 /** 095 * Create a new TransactionInterceptor. 096 * @param ptm the default transaction manager to perform the actual transaction management 097 * @param attributes the transaction attributes in properties format 098 * @see #setTransactionManager 099 * @see #setTransactionAttributes(java.util.Properties) 100 * @deprecated as of 5.2.5, in favor of {@link #setTransactionAttributes(Properties)} 101 */ 102 @Deprecated 103 public TransactionInterceptor(PlatformTransactionManager ptm, Properties attributes) { 104 setTransactionManager(ptm); 105 setTransactionAttributes(attributes); 106 } 107 108 109 @Override 110 @Nullable 111 public Object invoke(MethodInvocation invocation) throws Throwable { 112 // Work out the target class: may be {@code null}. 113 // The TransactionAttributeSource should be passed the target class 114 // as well as the method, which may be from an interface. 115 Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null); 116 117 // Adapt to TransactionAspectSupport's invokeWithinTransaction... 118 return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed); 119 } 120 121 122 //--------------------------------------------------------------------- 123 // Serialization support 124 //--------------------------------------------------------------------- 125 126 private void writeObject(ObjectOutputStream oos) throws IOException { 127 // Rely on default serialization, although this class itself doesn't carry state anyway... 128 oos.defaultWriteObject(); 129 130 // Deserialize superclass fields. 131 oos.writeObject(getTransactionManagerBeanName()); 132 oos.writeObject(getTransactionManager()); 133 oos.writeObject(getTransactionAttributeSource()); 134 oos.writeObject(getBeanFactory()); 135 } 136 137 private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { 138 // Rely on default serialization, although this class itself doesn't carry state anyway... 139 ois.defaultReadObject(); 140 141 // Serialize all relevant superclass fields. 142 // Superclass can't implement Serializable because it also serves as base class 143 // for AspectJ aspects (which are not allowed to implement Serializable)! 144 setTransactionManagerBeanName((String) ois.readObject()); 145 setTransactionManager((PlatformTransactionManager) ois.readObject()); 146 setTransactionAttributeSource((TransactionAttributeSource) ois.readObject()); 147 setBeanFactory((BeanFactory) ois.readObject()); 148 } 149 150}