Spring 事务理解

版权声明:本文为博主原创文章,未经博主允许不得转载。http://mp.blog.csdn.net/configure#i https://blog.csdn.net/wangming520liwei/article/details/86697089

                                                                    Spring 事务理解

先看代码,再debug看看

主要是基于Spring AOP

一、事务的基本原理

Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供事务功能的。对于纯JDBC操作数据库,想要用到事务,可以按照以下步骤进行:

    获取连接 Connection con = DriverManager.getConnection()
    开启事务con.setAutoCommit(true/false);
    执行CRUD
    提交事务/回滚事务 con.commit() / con.rollback();
    关闭连接 conn.close();

使用Spring的事务管理功能后,我们可以不再写步骤 2 和 4 的代码,而是由Spirng 自动完成。
那么Spring是如何在我们书写的 CRUD 之前和之后开启事务和关闭事务的呢?解决这个问题,也就可以从整体上理解Spring的事务管理实现原理了。下面简单地介绍下,注解方式为例子

    配置文件开启注解驱动,在相关的类和方法上通过注解@Transactional标识。
    spring 在启动的时候会去解析生成相关的bean,这时候会查看拥有相关注解的类和方法,并且为这些类和方法生成代理,并根据@Transaction的相关参数进行相关配置注入,这样就在代理中为我们把相关的事务处理掉了(开启正常提交事务,异常回滚事务)。
    真正的数据库层的事务提交和回滚是通过binlog或者redo log实现的。

二、Spring 事务的传播属性

所谓spring事务的传播属性,就是定义在存在多个事务同时存在的时候,spring应该如何处理这些事务的行为。这些属性在TransactionDefinition中定义,具体常量的解释见下表:
常量名称     常量解释
PROPAGATION_REQUIRED     支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择,也是 Spring 默认的事务的传播。
PROPAGATION_REQUIRES_NEW     新建事务,如果当前存在事务,把当前事务挂起。新建的事务将和被挂起的事务没有任何关系,是两个独立的事务,外层事务失败回滚之后,不能回滚内层事务执行的结果,内层事务失败抛出异常,外层事务捕获,也可以不处理回滚操作
PROPAGATION_SUPPORTS     支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY     支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_NOT_SUPPORTED     以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER     以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED     

如果一个活动的事务存在,则运行在一个嵌套的事务中。如果没有活动事务,则按REQUIRED属性执行。它使用了一个单独的事务,这个事务拥有多个可以回滚的保存点。内部事务的回滚不会对外部事务造成影响。它只对DataSourceTransactionManager事务管理器起效。
三、数据库隔离级别
隔离级别     隔离级别的值     导致的问题
Read-Uncommitted     0     导致脏读
Read-Committed     1     避免脏读,允许不可重复读和幻读
Repeatable-Read     2     避免脏读,不可重复读,允许幻读
Serializable     3     串行化读,事务只能一个一个执行,避免了脏读、不可重复读、幻读。执行效率慢,使用时慎重

脏读:一事务对数据进行了增删改,但未提交,另一事务可以读取到未提交的数据。如果第一个事务这时候回滚了,那么第二个事务就读到了脏数据。

不可重复读:一个事务中发生了两次读操作,第一次读操作和第二次操作之间,另外一个事务对数据进行了修改,这时候两次读取的数据是不一致的。

幻读:第一个事务对一定范围的数据进行批量修改,第二个事务在这个范围增加一条数据,这时候第一个事务就会丢失对新增数据的修改。

总结:

隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。

大多数的数据库默认隔离级别为 Read Commited,比如 SqlServer、Oracle

少数数据库默认隔离级别为:Repeatable Read 比如: MySQL InnoDB
四、Spring中的隔离级别
常量     解释
ISOLATION_DEFAULT     这是个 PlatfromTransactionManager 默认的隔离级别,使用数据库默认的事务隔离级别。另外四个与 JDBC 的隔离级别相对应。
ISOLATION_READ_UNCOMMITTED     这是事务最低的隔离级别,它充许另外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。
ISOLATION_READ_COMMITTED     保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。
ISOLATION_REPEATABLE_READ     这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。
ISOLATION_SERIALIZABLE     这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。
五、事务的嵌套

通过上面的理论知识的铺垫,我们大致知道了数据库事务和spring事务的一些属性和特点,接下来我们通过分析一些嵌套事务的场景,来深入理解spring事务传播的机制。

假设外层事务 Service A 的 Method A() 调用 内层Service B 的 Method B()

PROPAGATION_REQUIRED(spring 默认)

如果ServiceB.methodB() 的事务级别定义为 PROPAGATION_REQUIRED,那么执行 ServiceA.methodA() 的时候spring已经起了事务,这时调用 ServiceB.methodB(),ServiceB.methodB() 看到自己已经运行在 ServiceA.methodA() 的事务内部,就不再起新的事务。

假如 ServiceB.methodB() 运行的时候发现自己没有在事务中,他就会为自己分配一个事务。

这样,在 ServiceA.methodA() 或者在 ServiceB.methodB() 内的任何地方出现异常,事务都会被回滚。

PROPAGATION_REQUIRES_NEW

比如我们设计 ServiceA.methodA() 的事务级别为 PROPAGATION_REQUIRED,ServiceB.methodB() 的事务级别为 PROPAGATION_REQUIRES_NEW。

那么当执行到 ServiceB.methodB() 的时候,ServiceA.methodA() 所在的事务就会挂起,ServiceB.methodB() 会起一个新的事务,等待 ServiceB.methodB() 的事务完成以后,它才继续执行。

他与 PROPAGATION_REQUIRED 的事务区别在于事务的回滚程度了。因为 ServiceB.methodB() 是新起一个事务,那么就是存在两个不同的事务。如果 ServiceB.methodB() 已经提交,那么 ServiceA.methodA() 失败回滚,ServiceB.methodB() 是不会回滚的。如果 ServiceB.methodB() 失败回滚,如果他抛出的异常被 ServiceA.methodA() 捕获,ServiceA.methodA() 事务仍然可能提交(主要看B抛出的异常是不是A会回滚的异常)。

PROPAGATION_SUPPORTS

假设ServiceB.methodB() 的事务级别为 PROPAGATION_SUPPORTS,那么当执行到ServiceB.methodB()时,如果发现ServiceA.methodA()已经开启了一个事务,则加入当前的事务,如果发现ServiceA.methodA()没有开启事务,则自己也不开启事务。这种时候,内部方法的事务性完全依赖于最外层的事务。

PROPAGATION_NESTED

现在的情况就变得比较复杂了, ServiceB.methodB() 的事务属性被配置为 PROPAGATION_NESTED, 此时两者之间又将如何协作呢? 
ServiceB#methodB 如果 rollback, 那么内部事务(即 ServiceB#methodB) 将回滚到它执行前的 SavePoint 而外部事务(即 ServiceA#methodA) 可以有以下两种处理方式:

a、捕获异常,执行异常分支逻辑

void methodA() { 

        try { 

            ServiceB.methodB(); 

        } catch (SomeException) { 

            // 执行其他业务, 如 ServiceC.methodC(); 

        } 

    }

这种方式也是嵌套事务最有价值的地方, 它起到了分支执行的效果, 如果 ServiceB.methodB 失败, 那么执行 ServiceC.methodC(), 而 ServiceB.methodB 已经回滚到它执行之前的 SavePoint, 所以不会产生脏数据(相当于此方法从未执行过), 这种特性可以用在某些特殊的业务中, 而 PROPAGATION_REQUIRED 和 PROPAGATION_REQUIRES_NEW 都没有办法做到这一点。

b、 外部事务回滚/提交 代码不做任何修改, 那么如果内部事务(ServiceB#methodB) rollback, 那么首先 ServiceB.methodB 回滚到它执行之前的 SavePoint(在任何情况下都会如此), 外部事务(即 ServiceA#methodA) 将根据具体的配置决定自己是 commit 还是 rollback

另外三种事务传播属性基本用不到,在此不做分析。
六、总结

对于项目中需要使用到事务的地方,我建议开发者还是使用spring的TransactionCallback接口来实现事务,不要盲目使用spring事务注解,如果一定要使用注解,那么一定要对spring事务的传播机制和隔离级别有个详细的了解,否则很可能发生意想不到的效果。

spring.xml中事务的配置

    <bean id="genOneTransactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
        abstract="false" lazy-init="default" autowire="default">
        <property name="dataSource">
            <ref bean="genOneDataSource" />
        </property>
    </bean>
    <tx:annotation-driven transaction-manager="genOneTransactionManager" />

NameSpace 解析tx标签

public class TxNamespaceHandler extends NamespaceHandlerSupport {

	static final String TRANSACTION_MANAGER_ATTRIBUTE = "transaction-manager";

	static final String DEFAULT_TRANSACTION_MANAGER_BEAN_NAME = "transactionManager";


	static String getTransactionManagerName(Element element) {
		return (element.hasAttribute(TRANSACTION_MANAGER_ATTRIBUTE) ?
				element.getAttribute(TRANSACTION_MANAGER_ATTRIBUTE) : DEFAULT_TRANSACTION_MANAGER_BEAN_NAME);
	}


	@Override
	public void init() {
		registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());
		registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
		registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());
	}

}

数据库事务的配置 采用注解方式

 @Transactional(value = "genOneTransactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void deleteCostVO(String costIntervalSystemNo, String costInfoSystemNo) throws Exception {
        String sqlForInterval = "DELETE FROM CB_CostInterval WHERE SystemNo = ?";
        String sqlForBasicCost = "DELETE FROM CB_BasicCost WHERE CostIntervalSystemNo = ?";
        String sqlForDiscountCost = "DELETE FROM CB_BasicCost WHERE CostIntervalSystemNo = ?";
        String sqlForCostInfo = "DELETE FROM CB_CostInfo WHERE SystemNo = ?";
        String sqlForItemCostRel = "DELETE FROM CB_ChannelProItemCostRel WHERE CostInfoSystemNo = ?";
        smartDAO.update(FinanceModuleConstants.FINANCE_NAME, sqlForInterval, new Object[] { costIntervalSystemNo });
        smartDAO.update(FinanceModuleConstants.FINANCE_NAME, sqlForBasicCost, new Object[] { costIntervalSystemNo });
        smartDAO.update(FinanceModuleConstants.FINANCE_NAME, sqlForDiscountCost, new Object[] { costIntervalSystemNo });
        List<CbCostInterval> intervals = cbCostIntervalQuery.getListByCostInfoSystemNo(costInfoSystemNo);
        if (intervals.isEmpty()) {
            smartDAO.update(FinanceModuleConstants.FINANCE_NAME, sqlForCostInfo, new Object[] { costInfoSystemNo });
            smartDAO.update(FinanceModuleConstants.FINANCE_NAME, sqlForItemCostRel, new Object[] { costInfoSystemNo });
        }
    }

关注AnnotationDrivenBeanDefinitionParser 类 的parse方法

	@Override
	public BeanDefinition parse(Element element, ParserContext parserContext) {
		registerTransactionalEventListenerFactory(parserContext);
		String mode = element.getAttribute("mode");
		if ("aspectj".equals(mode)) {
			// mode="aspectj"
			registerTransactionAspect(element, parserContext);
		}
		else {
			// mode="proxy"
			AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
		}
		return null;
	}

	private static class AopAutoProxyConfigurer {

		public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {
			AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);

			String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;
			if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {
				Object eleSource = parserContext.extractSource(element);

				// Create the TransactionAttributeSource definition.
                //创建 TransactionAttributeSource 的bean
				RootBeanDefinition sourceDef = new RootBeanDefinition(
						"org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");
				sourceDef.setSource(eleSource);
				sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
                //注册bean 并使用Springbean中的定义规则生成beanName
				String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);

				// Create the TransactionInterceptor definition.
                // 创建TransactionInterceptor 的bean
				RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);
				interceptorDef.setSource(eleSource);
				interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
                // 将 interceptorName的bean注入到advisorDef的advicebean中
				registerTransactionManager(element, interceptorDef);
				interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
               // 注册 bean 并使用spring中的规则生成beanName
				String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);

				// Create the TransactionAttributeSourceAdvisor definition.
				RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);
				advisorDef.setSource(eleSource);
				advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
				advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
				advisorDef.getPropertyValues().add("adviceBeanName", interceptorName);
				if (element.hasAttribute("order")) {
					advisorDef.getPropertyValues().add("order", element.getAttribute("order"));
				}
				parserContext.getRegistry().registerBeanDefinition(txAdvisorBeanName, advisorDef);    
                // 构建CompositeComponentDefinition
				CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);
				compositeDef.addNestedComponent(new BeanComponentDefinition(sourceDef, sourceName));
				compositeDef.addNestedComponent(new BeanComponentDefinition(interceptorDef, interceptorName));
				compositeDef.addNestedComponent(new BeanComponentDefinition(advisorDef, txAdvisorBeanName));
				parserContext.registerComponent(compositeDef);
			}
		}
	}

configureAutoProxyCreator 方法注册了三个bean ,interceptorDef、advisorDef、compositeDef

这三个bean支持了整个事务的功能

在看一个很重要的一行, 事务上面的注解配置是怎么加载进来的呢?

看这一行

AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);

点进去,看

public abstract class AopNamespaceUtils {

	/**
	 * The {@code proxy-target-class} attribute as found on AOP-related XML tags.
	 */
	public static final String PROXY_TARGET_CLASS_ATTRIBUTE = "proxy-target-class";

	/**
	 * The {@code expose-proxy} attribute as found on AOP-related XML tags.
	 */
	private static final String EXPOSE_PROXY_ATTRIBUTE = "expose-proxy";


	public static void registerAutoProxyCreatorIfNecessary(
			ParserContext parserContext, Element sourceElement) {

		BeanDefinition beanDefinition = AopConfigUtils.registerAutoProxyCreatorIfNecessary(
				parserContext.getRegistry(), parserContext.extractSource(sourceElement));
		useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
		registerComponentIfNecessary(beanDefinition, parserContext);
	}

	public static void registerAspectJAutoProxyCreatorIfNecessary(
			ParserContext parserContext, Element sourceElement) {

		BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAutoProxyCreatorIfNecessary(
				parserContext.getRegistry(), parserContext.extractSource(sourceElement));
		useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
		registerComponentIfNecessary(beanDefinition, parserContext);
	}
}

主要关注这一行,怎么拿到beanDefinition的呢?

最终是把 beanDefinition放到parserContext 中的

public abstract class AopConfigUtils {
      public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
		return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
	}


private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
		if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
			BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
			if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
				int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
				int requiredPriority = findPriorityForClass(cls);
				if (currentPriority < requiredPriority) {
					apcDefinition.setBeanClassName(cls.getName());
				}
			}
			return null;
		}
		RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
		beanDefinition.setSource(source);
		beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
		beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
		registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
		return beanDefinition;
	}

}

registerAutoProxyCreatorIfNecessary 主要是返回 beanDefinition的,主要需要看下InfrastructureAdvisorAutoProxyCreator.class这个类

return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);

看这个类,主要关注的是bean的实例化之后干了啥postProcessAfterInitialization类

看继承关系InfrastructureAdvisorAutoProxyCreator 继承AbstractAdvisorAutoProxyCreator 继承AbstractAutoProxyCreator实现SmartInstantiationAwareBeanPostProcessor

@SuppressWarnings("serial")
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
		implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (!this.earlyProxyReferences.contains(cacheKey)) {
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}


   /**
	 * Wrap the given bean if necessary, i.e. if it is eligible for being proxied.
	 * @param bean the raw bean instance
	 * @param beanName the name of the bean
	 * @param cacheKey the cache key for metadata access
	 * @return a proxy wrapping the bean, or the raw bean instance as-is
	 */
	protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

		// Create proxy if we have advice.
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		if (specificInterceptors != DO_NOT_PROXY) {
			this.advisedBeans.put(cacheKey, Boolean.TRUE);
			Object proxy = createProxy(
					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}

}

postProcessAfterInitialization 主要是对InfrastructureAdvisorAutoProxyCreator进行封装,封装的工作都交给 wrapIfNecessary(bean, beanName, cacheKey); 方法

看看wrapIfNecessary 怎么封装的

wrapIfNecessary  主要做了什么事情?

1. 找到指定bean对应的增强器

2.根据找到的增强器创建代理

wrapIfNecessary  怎么找到增强的?看方法getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);

getAdvicesAndAdvisorsForBean方法 不仅要找到增强,还需要判断增强器是否满足要求

@SuppressWarnings("serial")
public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator {
   	@Override
	protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
		List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
		if (advisors.isEmpty()) {
			return DO_NOT_PROXY;
		}
		return advisors.toArray();
	}

	/**
	 * Find all eligible Advisors for auto-proxying this class.
	 * @param beanClass the clazz to find advisors for
	 * @param beanName the name of the currently proxied bean
	 * @return the empty List, not {@code null},
	 * if there are no pointcuts or interceptors
	 * @see #findCandidateAdvisors
	 * @see #sortAdvisors
	 * @see #extendAdvisors
	 */
	protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
		extendAdvisors(eligibleAdvisors);
		if (!eligibleAdvisors.isEmpty()) {
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}
		return eligibleAdvisors;
	}

	/**
	 * Find all candidate Advisors to use in auto-proxying.
	 * @return the List of candidate Advisors
	 */
	protected List<Advisor> findCandidateAdvisors() {
		return this.advisorRetrievalHelper.findAdvisorBeans();
	}

	protected List<Advisor> findAdvisorsThatCanApply(
			List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {

		ProxyCreationContext.setCurrentProxiedBeanName(beanName);
		try {
			return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
		}
		finally {
			ProxyCreationContext.setCurrentProxiedBeanName(null);
		}
	}


}

使用 findCandidateAdvisors 去找增强器,然后使用findAdvisorsThatCanApply 方法从候选增强器中找到匹配项目

public abstract class AopUtils {
      	public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
		if (candidateAdvisors.isEmpty()) {
			return candidateAdvisors;
		}
		List<Advisor> eligibleAdvisors = new LinkedList<Advisor>();
		for (Advisor candidate : candidateAdvisors) {
			if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
				eligibleAdvisors.add(candidate);
			}
		}
		boolean hasIntroductions = !eligibleAdvisors.isEmpty();
		for (Advisor candidate : candidateAdvisors) {
			if (candidate instanceof IntroductionAdvisor) {
				// already processed
				continue;
			}
			if (canApply(candidate, clazz, hasIntroductions)) {
				eligibleAdvisors.add(candidate);
			}
		}
		return eligibleAdvisors;
	}

public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
		if (advisor instanceof IntroductionAdvisor) {
			return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
		}
		else if (advisor instanceof PointcutAdvisor) {
			PointcutAdvisor pca = (PointcutAdvisor) advisor;
			return canApply(pca.getPointcut(), targetClass, hasIntroductions);
		}
		else {
			// It doesn't have a pointcut so we assume it applies.
			return true;
		}
	}


  	public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
		Assert.notNull(pc, "Pointcut must not be null");
		if (!pc.getClassFilter().matches(targetClass)) {
			return false;
		}

		MethodMatcher methodMatcher = pc.getMethodMatcher();
		if (methodMatcher == MethodMatcher.TRUE) {
			// No need to iterate the methods if we're matching any method anyway...
			return true;
		}

		IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
		if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
			introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
		}

		Set<Class<?>> classes = new LinkedHashSet<Class<?>>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
		classes.add(targetClass);
		for (Class<?> clazz : classes) {
			Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
			for (Method method : methods) {
				if ((introductionAwareMethodMatcher != null &&
						introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
						methodMatcher.matches(method, targetClass)) {
					return true;
				}
			}
		}

		return false;
	}

}

看methodMatcher.matchers(methmod,targetClass) 怎么匹配的

@SuppressWarnings("serial")
abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {

	@Override
	public boolean matches(Method method, Class<?> targetClass) {
		if (targetClass != null && TransactionalProxy.class.isAssignableFrom(targetClass)) {
			return false;
		}
		TransactionAttributeSource tas = getTransactionAttributeSource();
		return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
	}

}

getTransactionAttributeSource()获取切点的套路是一样的 使用TransactionAttributeSource的getTransactionAttribute获取

getTransactionAttribute还是先从缓存中加载,加载不到 使用computeTransactionAttribute 去提取

class TransactionalRepositoryProxyPostProcessor implements RepositoryProxyPostProcessor {
public TransactionAttribute getTransactionAttribute(Method method, Class<?> targetClass) {
			// First, see if we have a cached value.
			Object cacheKey = getCacheKey(method, targetClass);
			Object cached = this.attributeCache.get(cacheKey);
			if (cached != null) {
				// Value will either be canonical value indicating there is no transaction attribute,
				// or an actual transaction attribute.
				if (cached == NULL_TRANSACTION_ATTRIBUTE) {
					return null;
				} else {
					return (TransactionAttribute) cached;
				}
			} else {
				// We need to work it out.
				TransactionAttribute txAtt = computeTransactionAttribute(method, targetClass);
				// Put it in the cache.
				if (txAtt == null) {
					this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
				} else {
					if (logger.isDebugEnabled()) {
						logger.debug("Adding transactional method '" + method.getName() + "' with attribute: " + txAtt);
					}
					this.attributeCache.put(cacheKey, txAtt);
				}
				return txAtt;
			}
		}


		public TransactionAttribute getTransactionAttribute(Method method, Class<?> targetClass) {
			// First, see if we have a cached value.
			Object cacheKey = getCacheKey(method, targetClass);
			Object cached = this.attributeCache.get(cacheKey);
			if (cached != null) {
				// Value will either be canonical value indicating there is no transaction attribute,
				// or an actual transaction attribute.
				if (cached == NULL_TRANSACTION_ATTRIBUTE) {
					return null;
				} else {
					return (TransactionAttribute) cached;
				}
			} else {
				// We need to work it out.
				TransactionAttribute txAtt = computeTransactionAttribute(method, targetClass);
				// Put it in the cache.
				if (txAtt == null) {
					this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
				} else {
					if (logger.isDebugEnabled()) {
						logger.debug("Adding transactional method '" + method.getName() + "' with attribute: " + txAtt);
					}
					this.attributeCache.put(cacheKey, txAtt);
				}
				return txAtt;
			}
		}


       private TransactionAttribute computeTransactionAttribute(Method method, Class<?> targetClass) {
			// Don't allow no-public methods as required.
			if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
				return null;
			}

			// Ignore CGLIB subclasses - introspect the actual user class.
			Class<?> userClass = ClassUtils.getUserClass(targetClass);
			// The method may be on an interface, but we need attributes from the target class.      // methmod 代表接口中的方法 specificMethod 代表实现类的方法
			// If the target class is null, the method will be unchanged.
			Method specificMethod = ClassUtils.getMostSpecificMethod(method, userClass);
			// If we are dealing with method with generic parameters, find the original method.
			specificMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);

			TransactionAttribute txAtt = null;

			if (specificMethod != method) {
				// Fallback is to look at the original method.
                // 查看方法方法释放声明事务
				txAtt = findTransactionAttribute(method);
               
				if (txAtt != null) {
					return txAtt;
				}
				// Last fallback is the class of the original method.
                // 如果存在,从接口中去寻找
				txAtt = findTransactionAttribute(method.getDeclaringClass());
                    
				if (txAtt != null || !enableDefaultTransactions) {
					return txAtt;
				}
			}

			// Start: Implementation class check block

			// First try is the method in the target class.
			txAtt = findTransactionAttribute(specificMethod);
			if (txAtt != null) {
				return txAtt;
			}

			// Second try is the transaction attribute on the target class.
			txAtt = findTransactionAttribute(specificMethod.getDeclaringClass());
			if (txAtt != null) {
				return txAtt;
			}

			if (!enableDefaultTransactions) {
				return null;
			}

			// Fallback to implementation class transaction settings of nothing found
			// return findTransactionAttribute(method);
			Method targetClassMethod = repositoryInformation.getTargetClassMethod(method);

			if (targetClassMethod.equals(method)) {
				return null;
			}

			txAtt = findTransactionAttribute(targetClassMethod);
			if (txAtt != null) {
				return txAtt;
			}

			txAtt = findTransactionAttribute(targetClassMethod.getDeclaringClass());
			if (txAtt != null) {
				return txAtt;
			}

			return null;
			// End: Implementation class check block
		}
}

再看怎么查找事务声明的

class TransactionalRepositoryProxyPostProcessor implements RepositoryProxyPostProcessor {
      @Override
		protected TransactionAttribute findTransactionAttribute(Class<?> clazz) {
			return determineTransactionAttribute(clazz);
		}

//  看到注解获取了

		protected TransactionAttribute determineTransactionAttribute(AnnotatedElement ae) {
			for (TransactionAnnotationParser annotationParser : this.annotationParsers) {
				TransactionAttribute attr = annotationParser.parseTransactionAnnotation(ae);
				if (attr != null) {
					return attr;
				}
			}
			return null;
		}

}

看下Spring 注解解析器是怎么解析 注解声明的

public class SpringTransactionAnnotationParser implements TransactionAnnotationParser, Serializable {

	@Override
	public TransactionAttribute parseTransactionAnnotation(AnnotatedElement ae) {
		AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ae, Transactional.class);
		if (attributes != null) {
			return parseTransactionAnnotation(attributes);
		}
		else {
			return null;
		}
	}


protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
		RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
		Propagation propagation = attributes.getEnum("propagation");
		rbta.setPropagationBehavior(propagation.value());
		Isolation isolation = attributes.getEnum("isolation");
		rbta.setIsolationLevel(isolation.value());
		rbta.setTimeout(attributes.getNumber("timeout").intValue());
		rbta.setReadOnly(attributes.getBoolean("readOnly"));
		rbta.setQualifier(attributes.getString("value"));
		ArrayList<RollbackRuleAttribute> rollBackRules = new ArrayList<RollbackRuleAttribute>();
		Class<?>[] rbf = attributes.getClassArray("rollbackFor");
		for (Class<?> rbRule : rbf) {
			RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);
			rollBackRules.add(rule);
		}
		String[] rbfc = attributes.getStringArray("rollbackForClassName");
		for (String rbRule : rbfc) {
			RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);
			rollBackRules.add(rule);
		}
		Class<?>[] nrbf = attributes.getClassArray("noRollbackFor");
		for (Class<?> rbRule : nrbf) {
			NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);
			rollBackRules.add(rule);
		}
		String[] nrbfc = attributes.getStringArray("noRollbackForClassName");
		for (String rbRule : nrbfc) {
			NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);
			rollBackRules.add(rule);
		}
		rbta.getRollbackRules().addAll(rollBackRules);
		return rbta;
	}

}

解析完了之后事务标签之后,再回到最开始,我们是怎么实现增强的

class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {	
private static class AopAutoProxyConfigurer {

		public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {

// Create the TransactionAttributeSourceAdvisor definition.
				RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);
				advisorDef.setSource(eleSource);
				advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
				advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
				advisorDef.getPropertyValues().add("adviceBeanName", interceptorName);
				if (element.hasAttribute("order")) {
					advisorDef.getPropertyValues().add("order", element.getAttribute("order"));
				}
				parserContext.getRegistry().registerBeanDefinition(txAdvisorBeanName, advisorDef);

 }
}

BeanFactoryTransactionAttributeSourceAdvisor 作为增强的实现类,当代理被调用时会调用这个类的增强方法,也就是Bean的advice,在自定义标签解析时,注入的类成为了整个事务的功能基础。BeanFactoryTransactionAttributeSourceAdvisor 作为Advisor的实现类,自然要遵从Advisor的处理方式,当代理被调用是会调用这个增强方法,也就是此bean的Advise,因为在解析事务标签时,我们把TransactionInterceptor类型的bean注入到了BeanFactory TransactionInterceptor进行增强,同时也就是在TransactionInterceptor类的invoke方法中完成整个事务逻辑

public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean {
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, txAttr);

		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;
		}
}

综合来看

可以理解 spring aop 事务

{org.springframework.transaction.config.internalTransactionAdvisor=false}

猜你喜欢

转载自blog.csdn.net/wangming520liwei/article/details/86697089
今日推荐