Transaction註解原理

開啓事務註解EnableTransactionManagement,該註解往容器中導入了導入TransactionManagementConfigurationSelector組件。該組件有個方法,在容器刷新的時候會被調用。(此處不講解爲何會被調用,重點講解Transaction註解)
protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:java

return new String[] {AutoProxyRegistrar.class.getName(),
                ProxyTransactionManagementConfiguration.class.getName()};
    case ASPECTJ:
            return new String[] {

TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME};
 default:
 return null;
 }
 }

EnableTransactionManagement默認是AdviceMode mode() default AdviceMode.PROXY;因此
AutoProxyRegistrar和ProxyTransactionManagementConfiguration會被加載到容器中。

AutoProxyRegistrar功能是往容器中註冊了InfrastructureAdvisorAutoProxyCreator是個BeanPostProcessor後置處理器。
ProxyTransactionManagementConfiguration利用@Bean註解往容器中添加多個bean。(BeanFactoryTransactionAttributeSourceAdvisor是個Advisor和前面Aop中@Before同樣都是通知方法,可是此處的是手動導入的,Aop是本身自動生成的)。

在bean生成完成之後會調用後置處理器初始化。會去查找bean有沒有合適的通知方法。因此重點是在找通知方法,找到了合適的就會生成代理對象。

//簡單的分析一下流程
AbstractAutowireCapableBeanFactory#initializeBean() ->
AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization() ->
AbstractAutoProxyCreator#postProcessAfterInitialization() ->
AbstractAutoProxyCreator#wrapIfNecessary()->
AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean()
/**
 * 尋找可用的通知方法
 */
 protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
 //尋找全部的Advisors,會去容器遍歷全部類型爲Advisor的bean,
 //BeanFactoryTransactionAttributeSourceAdvisor就是咱們手動導入的Advisor
 List<Advisor> candidateAdvisors = findCandidateAdvisors();
 //在全部的Advisors,看是否有beanClass匹配的
 List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
 extendAdvisors(eligibleAdvisors);
 if (!eligibleAdvisors.isEmpty()) {
 eligibleAdvisors = sortAdvisors(eligibleAdvisors);
 }
 return eligibleAdvisors;
 }
//找到全部的Advisors,剩下就是是否有匹配的findAdvisorsThatCanApply()方法//最終走到TransactionAttributeSourcePointcut#matches//->AbstractFallbackTransactionAttributeSource#computeTransactionAttribute

`javaprotected TransactionAttribute computeTransactionAttribute(Method method, Class<?> targetClass) {
 //判斷方法修飾符是否是Public,allowPublicMethodsOnly()默認是true的
 if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
 return null;
 }

 // 這裏面就是判斷方法上有沒有Transactional註解,有進行解析操做並返回。
 TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
 if (txAttr != null) {
 return txAttr;
 }
 //代碼每貼全,爲了少點沒用的東西。。。。
那要是找了合適的通知方法,就生成代理對象,並設置回調函數。設置回調函數是CglibAopProxy.DynamicAdvisedInterceptor的intercept方法,該方法有個getInterceptorsAndDynamicInterceptionAdvice獲取合適的攔截器。(事務的攔截器是TransactionInterceptor)
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
 //獲取目標對象,不是代理對象
 target = getTarget();
 if (target != null) {
 targetClass = target.getClass();
 }
 //獲取方法合適的攔截器
 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
 Object retVal;
 //沒有合適的攔截器而且方法的修飾符是Public
 if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
 Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
 //會調用目標方法
 retVal = methodProxy.invoke(target, argsToUse);
 }
 else {
 /*
 * 1.有合適的攔截器:跟單網www.gendan5.com會去執行攔截器TransactionInterceptor#invoke(),
 * 事務的提交,回滾等一系列操做都在裏面。具體是調去了
 * TransactionAspectSupport#invokeWithinTransaction()方法
 * 2.沒有合適的攔截器而且方法的修飾符不是Public:這裏面也會去調目標方法
 * (這裏簡單能夠走進去看一下)
 */
 retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
 }
 retVal = processReturnType(proxy, target, method, retVal);
 return retVal;
 }
app

相關文章
相關標籤/搜索