死磕Spring之AOP篇 - Spring 事务详解 (4)

BeanFactoryTransactionAttributeSourceAdvisor 切面,这个 PointcutAdvisor 对象关联的 Pointcut 切点用于筛选 @Transactional 注解的方法(标注在类上也可以),在关联的 Advice 中会进行事务的拦截处理

Advice 通知,就是一个 TransactionInterceptor 方法拦截器,关联着一个 AnnotationTransactionAttributeSource 对象

AnnotationTransactionAttributeSource 事务属性资源对象,被 Pointcut 和 Advice 关联,用于解析 @Transactional 注解,在它的构造方法中会添加一个 SpringTransactionAnnotationParser 事务注解解析器,用于解析 @Transactional 注解,如下:

// AnnotationTransactionAttributeSource.java public AnnotationTransactionAttributeSource() { this(true); } public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) { this.publicMethodsOnly = publicMethodsOnly; if (jta12Present || ejb3Present) { this.annotationParsers = new LinkedHashSet<>(4); this.annotationParsers.add(new SpringTransactionAnnotationParser()); if (jta12Present) { this.annotationParsers.add(new JtaTransactionAnnotationParser()); } if (ejb3Present) { this.annotationParsers.add(new Ejb3TransactionAnnotationParser()); } } else { this.annotationParsers = Collections.singleton(new SpringTransactionAnnotationParser()); } }

PointcutAdvisor 事务切面

org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor,Spring 事务切面,如下:

public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor { /** * 事务属性源对象,用于解析 @Transactional 注解 */ @Nullable private TransactionAttributeSource transactionAttributeSource; /** * Pointcut 对象,用于判断 JoinPoint 是否匹配 */ private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() { @Override @Nullable protected TransactionAttributeSource getTransactionAttributeSource() { return transactionAttributeSource; } }; public void setTransactionAttributeSource(TransactionAttributeSource transactionAttributeSource) { this.transactionAttributeSource = transactionAttributeSource; } public void setClassFilter(ClassFilter classFilter) { this.pointcut.setClassFilter(classFilter); } @Override public Pointcut getPointcut() { return this.pointcut; } }

设置的 TransactionAttributeSource 就是上面的 AnnotationTransactionAttributeSource 对象,关联的 Pointcut 切点就是一个 TransactionAttributeSourcePointcut 对象

也就是说通过 Pointcut 事务切点筛选出来的 Bean 会创建一个代理对象,方法的拦截处理则交由 Advice 完成

Pointcut 事务切点

org.springframework.transaction.interceptor.TransactionAttributeSourcePointcut,Spring 事务的 AOP 切点,如下:

abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable { @Override public boolean matches(Method method, Class<?> targetClass) { // <1> 目标类是 Spring 内部的事务相关类,则跳过,不需要创建代理对象 if (TransactionalProxy.class.isAssignableFrom(targetClass) || PlatformTransactionManager.class.isAssignableFrom(targetClass) || PersistenceExceptionTranslator.class.isAssignableFrom(targetClass)) { return false; } // <2 获取 AnnotationTransactionAttributeSource 对象 TransactionAttributeSource tas = getTransactionAttributeSource(); // <3> 解析该方法相应的 @Transactional 注解,并将元信息封装成一个 TransactionAttribute 对象 // 且缓存至 AnnotationTransactionAttributeSource 对象中 // <4> 如果有对应的 TransactionAttribute 对象,则表示匹配,需要进行事务的拦截处理 return (tas == null || tas.getTransactionAttribute(method, targetClass) != null); } }

判断这个方法是否需要被 TransactionInterceptor 事务拦截器进行拦截的过程如下:

目标类是 Spring 内部的事务相关类,则跳过,不需要创建代理对象

获取 AnnotationTransactionAttributeSource 对象

解析该方法相应的 @Transactional 注解,并将元信息封装成一个 TransactionAttribute 对象,且缓存至 AnnotationTransactionAttributeSource 对象中

如果有对应的 TransactionAttribute 对象,则表示匹配,需要进行事务的拦截处理

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zygsff.html