spring事務管理 TransactionProxyFactoryBean源碼分析
J2EE,當然離不開事務,事務又當然少不了Spring聲明式事務。spring聲明式事務,很多碼農門,應該和筆者一樣,停留在使用上,及僅僅了解點原理。如:Spring事務管理原理“代理+AOP”,再深入了解就不太清楚了。一直對聲明式事務實現特別感興趣,今天抽時間,剖析一下下。
1.準備
BeanFactory,及對象生成周期
AOP代理對象生成過程
1.1.BeanFactory 及生命周期
Factory class name | 作用 |
ListableBeanFactory | 枚舉所有的bean實例 |
HierarchicalBeanFactory | 維護工廠父子關系 |
ConfigurableBeanFactory | 配置BeanFactory |
AutowireCapableBeanFactory | 維護ean屬性註入和依賴關系維護 |
ConfigurableListableBeanFactory | BeanFacotry配置清單,指定忽略接口 |
SingletonBeanRegistry | 維護單例關系 |
FactoryBeanRegistrySupport | 針對FactoryBean,維護單例關系 |
AbstractBeanFactory | ConfigurableBeanFactory SPI. |
AbstractAutowireCapableBeanFactory | 提供create bean默認實現 |
DefaultListableBeanFactory | 一個基於bean定義對象的完整的bean工廠;默認 |
總之,spring容器中涉及的對象,都是通過上面的BeanFactory樹結構中創建而來。生成的代理對象也是如此。
1.2 周期lifecycle
1. BeanNameAware‘s setBeanName
2. BeanClassLoaderAware‘s setBeanClassLoader
3. BeanFactoryAware‘s setBeanFactory
4. ResourceLoaderAware‘s setResourceLoader (only applicable when running in an application context)
5. ApplicationEventPublisherAware‘s setApplicationEventPublisher (only applicable when running in an application context)
6. MessageSourceAware‘s setMessageSource (only applicable when running in an application context)
7. ApplicationContextAware‘s setApplicationContext (only applicable when running in an application context)
8. ServletContextAware‘s setServletContext (only applicable when running in a web application context)
9. postProcessBeforeInitialization methods of BeanPostProcessors
10. InitializingBean‘s afterPropertiesSet
11. a custom init-method definition
12. postProcessAfterInitialization methods of BeanPostProcessors
beanfactory shutdown
1. DisposableBean‘s destroy
2. a custom destroy-method definition
其中生成代理對象,僅僅是上面(1-12)步驟中的一步而已。
1.2 AOP 代理對象生成
1.2.1 TargetClassAware
用於將目標類暴露在代理後面的最小界面。
1.2.2 Advised
AOP代理配置接口
public interface Advised extends TargetClassAware { /**是否凍結了“Advised”配置,在這種情況下,無法進行任何建議更改。*/ boolean isFrozen(); /** 代理完整的目標類而不是指定的接口?*/ boolean isProxyTargetClass(); /**返回由AOP代理代理的接口 */ Class<?>[] getProxiedInterfaces(); /**確定給定的接口是否被代理。 */ boolean isInterfaceProxied(Class<?> intf); /** 更改此Advised對象使用的TargetSource。 */ void setTargetSource(TargetSource targetSource); TargetSource getTargetSource(); /**是否可以被AOP框架作為ThreadLocal暴露,通過AopContext。 */ void setExposeProxy(boolean exposeProxy); boolean isExposeProxy(); /**設置此代理配置是否經過預篩選,以便它僅包含適用的advisors (與此代理的目標類匹配)。 */ void setPreFiltered(boolean preFiltered); boolean isPreFiltered(); /**返回適用於此代理的Advisor。*/ Advisor[] getAdvisors(); void addAdvisor(Advisor advisor) throws AopConfigException; void addAdvisor(int pos, Advisor advisor) throws AopConfigException; boolean removeAdvisor(Advisor advisor); void removeAdvisor(int index) throws AopConfigException; int indexOf(Advisor advisor); boolean replaceAdvisor(Advisor a, Advisor b) throws AopConfigException; /**將給定的AOP advice 添加到advice(interceptor)鏈的尾部。這將包含在一個DefaultPointcutAdvisor中,該切點總是適用,*/ void addAdvice(Advice advice) throws AopConfigException; void addAdvice(int pos, Advice advice) throws AopConfigException; boolean removeAdvice(Advice advice); int indexOf(Advice advice); String toProxyConfigString(); }
1.2.3 AdvisedSupport
AOP代理配置管理器的基類
public class AdvisedSupport extends ProxyConfig implements Advised { /** Package-protected to allow direct access for efficiency */ TargetSource targetSource = EMPTY_TARGET_SOURCE; /** Advisors是否已針對特定目標類過濾 */ private boolean preFiltered = false; /** The AdvisorChainFactory to use */ AdvisorChainFactory advisorChainFactory = new DefaultAdvisorChainFactory(); /** Cache with Method as key and advisor chain List as value */ private transient Map<MethodCacheKey, List<Object>> methodCache; /** * 接口由代理實現。 在List中保存註冊順序,創建具有指定順序接口的JDK代理。 */ private List<Class> interfaces = new ArrayList<Class>(); /**Advisor名單 如果添加了一個Advise,它將被包裝在一個Advisor中,然後被添加到此列表中。 */ private List<Advisor> advisors = new LinkedList<Advisor>(); /** * Array updated on changes to the advisors list, which is easier * to manipulate internally. */ private Advisor[] advisorArray = new Advisor[0]; } }
1.2.4 ProxyCreatorSupport
proxy factory的基類
public class ProxyCreatorSupport extends AdvisedSupport { //允許在不改變核心框架的情況下選擇不同的策略。 private AopProxyFactory aopProxyFactory; private List<AdvisedSupportListener> listeners = new LinkedList<AdvisedSupportListener>(); /** Set to true when the first AOP proxy has been created */ private boolean active = false; }
1.2.5 生成序列圖
需要關註:
1.生成代理時機:在afterPropertiesSet中,(對應10. InitializingBean‘s afterPropertiesSet)
2.委派給AopProxy具體實現類生成代理對象。
1.3 AOP 攔截器實現(具體發生在每次函數調用過程中)
Advisor規則應用過程,發生在具體方法調用過程中,此時代理對象已經生成了。
主要工作:
維護Advisor鏈
匹配過程,主要通過Pointcut中的ClassFiter,和MethodMatcher完成。
2.TransactionProxyFactoryBean 對象剖析
2.1 類圖
2.1.1 ProxyConfig
方便的用於創建代理的超類配置,以確保所有代理創建者具有一致的屬性。
public class ProxyConfig implements Serializable { /** * 設置是否直接代理目標類,而不是僅代理特定的接口。 默認值為“false”。 * 將其設置為“true”以強制對TargetSource的暴露目標類進行代理。 * 如果該目標類是接口,將為給定的接口創建一個JDK代理。 * 如果該目標類是任何其他類,將為給定的類創建一個CGLIB代理。 */ private boolean proxyTargetClass = false; /** *設置代理是否應該執行積極的優化。 “aggressive optimizations”的確切含義在代理之間有所不同,但通常有一些權衡。 默認值為“false”。 *例如,優化通常意味著建議更改在代理創建後不會生效。 *因此,默認情況下禁用優化。 如果其他設置排除優化,則可以忽略“true”的優化值:例如,如果“publicProxy”設置為“true”,並且與優化不兼容。 */ private boolean optimize = false; /** *設置是否應該阻止通過此配置創建的代理被轉換為Advised,以查詢代理狀態。 *默認為“false”,這意味著任何AOP代理可以轉換為Advised。 */ boolean opaque = false; /** 是否可以被AOP框架作為ThreadLocal暴露,通過AopContext。默認false,以避免不必要的額外攔截 */ boolean exposeProxy = false; /** * 設置此配置是否應該被凍結。當配置被凍結時,不會改變任何advice。 這對於優化是有用的, */ private boolean frozen = false; }
2.1.2 AbstractSingletonProxyFactoryBean
方便的FactoryBean類型的超類,產生單例範圍的代理對象。
public abstract class AbstractSingletonProxyFactoryBean extends ProxyConfig implements FactoryBean<Object>, BeanClassLoaderAware, InitializingBean { //目標對象 private Object target; //被代理的一組接口 private Class<?>[] proxyInterfaces; //在隱式”事務“攔截器之前設置要應用的interceptors (or advisors) private Object[] preInterceptors; //在隱式”事務“攔截器後設置要應用的interceptors (or advisors) private Object[] postInterceptors; //Specify the AdvisorAdapterRegistry to use. Default is the global AdvisorAdapterRegistry. private AdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.getInstance(); //生成代理的ClassLoader private transient ClassLoader proxyClassLoader; private Object proxy; }
2.1.3 TransactionProxyFactoryBean
代理工廠bean,用於簡化的聲明性事務處理。
public class TransactionProxyFactoryBean extends AbstractSingletonProxyFactoryBean implements BeanFactoryAware { //設置事務管理器。 這將執行實際的事務管理:這個類只是一種調用它的方式。 private final TransactionInterceptor transactionInterceptor = new TransactionInterceptor(); ////設置一個pointcut,即根據傳遞的方法和屬性可以導致TransactionInterceptor的條件調用的bean。 註意:總是調用其他攔截器。 private Pointcut pointcut; //將方法名稱的屬性設置為鍵和事務屬性描述符(通過TransactionAttributeEditor解析) public void setTransactionAttributes(Properties transactionAttributes) { this.transactionInterceptor.setTransactionAttributes(transactionAttributes); } //設置用於查找事務屬性的事務屬性源。 如果指定一個String屬性值,PropertyEditor將從該值創建一個MethodMapTransactionAttributeSource。 public void setTransactionAttributeSource(TransactionAttributeSource transactionAttributeSource) { this.transactionInterceptor.setTransactionAttributeSource(transactionAttributeSource); } }
2.1.4 使用配置
<bean id="baseTransactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true"> <property name="transactionManager" ref="transactionManager"/> <property name="transactionAttributes"> <props> <prop key="insert*">PROPAGATION_REQUIRED</prop> <prop key="update*">PROPAGATION_REQUIRED</prop> <prop key="*">PROPAGATION_REQUIRED,readOnly</prop> </props> </property> </bean> <bean id="myProxy" parent="baseTransactionProxy"> <property name="target" ref="myTarget"/> </bean> <bean id="yourProxy" parent="baseTransactionProxy"> <property name="target" ref="yourTarget"/> </bean>
2.2 TransactionProxyFactoryBean分析
2.2.1類圖
2.2.2 序列圖
事務模板入口
org.springframework.transaction.interceptor.TransactionInterceptor
public Object invoke(@NotNull MethodInvocation invocation)
public Object invoke(final MethodInvocation invocation) throws Throwable { // Work out the target class: may be [email protected] null}. // The TransactionAttributeSource should be passed the target class // as well as the method, which may be from an interface. Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null); // Adapt to TransactionAspectSupport‘s invokeWithinTransaction... return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() { public Object proceedWithInvocation() throws Throwable { return invocation.proceed(); } }); }
事務管理模板
protected Object invokeWithinTransaction(Method method, Class targetClass, final InvocationCallback invocation) throws Throwable { // If the transaction attribute is null, the method is non-transactional. final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass); final PlatformTransactionManager tm = determineTransactionManager(txAttr); final String joinpointIdentification = methodIdentification(method, targetClass); if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) { // Standard transaction demarcation with getTransaction and commit/rollback calls. TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification); Object retVal = null; try { // This is an around advice: Invoke the next interceptor in the chain. // This will normally result in a target object being invoked. retVal = invocation.proceedWithInvocation();//調用實際業務 } catch (Throwable ex) { // target invocation exception completeTransactionAfterThrowing(txInfo, ex); throw ex; } finally { cleanupTransactionInfo(txInfo); } commitTransactionAfterReturning(txInfo); return retVal; } else { // It‘s a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in. try { Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr, new TransactionCallback<Object>() { public Object doInTransaction(TransactionStatus status) { TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status); try { return invocation.proceedWithInvocation(); } catch (Throwable ex) { if (txAttr.rollbackOn(ex)) { // A RuntimeException: will lead to a rollback. if (ex instanceof RuntimeException) { throw (RuntimeException) ex; } else { throw new ThrowableHolderException(ex); } } else { // A normal return value: will lead to a commit. return new ThrowableHolder(ex); } } finally { cleanupTransactionInfo(txInfo); } } }); // Check result: It might indicate a Throwable to rethrow. if (result instanceof ThrowableHolder) { throw ((ThrowableHolder) result).getThrowable(); } else { return result; } } catch (ThrowableHolderException ex) { throw ex.getCause(); } } }
本文出自 “簡單” 博客,請務必保留此出處http://dba10g.blog.51cto.com/764602/1927762
spring事務管理 TransactionProxyFactoryBean源碼分析