文章目录
前言
Spring基于AOP完成的事务处理。接下来就是围绕着Spring是如何基于AOP完成的事务处理的学习总结
一、事务处理的核心类
提到AOP,就需要提到三个核心类Advisor、PointCut、Advice。Advisor主要用于封装后两者,PointCut用于匹配待增强的方法,Advice用于增强待增强的方法。以下就是事务中用到的核心类
类名 | 所属类型 | 简介 |
---|---|---|
BeanFactoryTransactionAttributeSourceAdvisor | Advisor | 用于封装Advice和PointCut,便于Spring调用 |
AnnotationTransactionAttributeSource | PointCut | 该类本身不是PointCut的子类,spring使用适配器模式让其成为了一个PointCut |
TransactionInterceptor | Advice | 用于增强需要事务处理的方法,事务处理的逻辑都在该类中 |
二、核心类的加载
Spring原始采用自定义标签的方式加载这三个类,在SpringBoot中使用了自动装配完成加载
2.1、自定义标签加载方式简介
大致过程如下
- 1 这个标签加入spring的配置文件。
<tx:annotation-driven />
- 2 TxNamespaceHandler类中的AnnotationDrivenBeanDefinitionParser类对自定义标签进行解析完成核心类加载
public BeanDefinition parse(Element element, ParserContext parserContext) {
registerTransactionalEventListenerFactory(parserContext);
String mode = element.getAttribute("mode");
//目前不是aspectj模式 这里先不看了
if ("aspectj".equals(mode)) {
。。。
}
//重点看这里
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);
//构建AnnotationTransactionAttributeSource
RootBeanDefinition sourceDef = new RootBeanDefinition(
"org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");
sourceDef.setSource(eleSource);
sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);
//构建TransactionInterceptor
RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);
interceptorDef.setSource(eleSource);
interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registerTransactionManager(element, interceptorDef);
interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);
//构建BeanFactoryTransactionAttributeSourceAdvisor
RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);
advisorDef.setSource(eleSource);
advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
//向BeanFactoryTransactionAttributeSourceAdvisor注入AnnotationTransactionAttributeSource
advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
//向BeanFactoryTransactionAttributeSourceAdvisor注入TransactionInterceptor
advisorDef.getPropertyValues().add("adviceBeanName", interceptorName);
if (element.hasAttribute("order")) {
advisorDef.getPropertyValues().add("order", element.getAttribute("order"));
}
parserContext.getRegistry().registerBeanDefinition(txAdvisorBeanName, advisorDef);
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);
}
}
}
以上就是自定义标签加载核心类的方式。
2.2、自动装配加载方式简介
大致过程如下
- 1 默认自定装配列表【spring.factories】自带事务装配类TransactionAutoConfiguration
- 2 TransactionAutoConfiguration内部会开启@EnableTransactionManagement
@Configuration(proxyBeanMethods = false)
@ConditionalOnBean(TransactionManager.class)
@ConditionalOnMissingBean(AbstractTransactionManagementConfiguration.class)
public static class EnableTransactionManagementConfiguration {
@Configuration(proxyBeanMethods = false)
@EnableTransactionManagement(proxyTargetClass = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false",
matchIfMissing = false)
public static class JdkDynamicAutoProxyConfiguration {
}
@Configuration(proxyBeanMethods = false)
@EnableTransactionManagement(proxyTargetClass = true)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
matchIfMissing = true)
public static class CglibAutoProxyConfiguration {
}
}
- 3 @EnableTransactionManagement注解中带有TransactionManagementConfigurationSelector
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
}
- 3 @TransactionManagementConfigurationSelector选择装配ProxyTransactionManagementConfiguration
@Override
protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:
//最终会进入这个分支
return new String[] {AutoProxyRegistrar.class.getName(),
ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
return new String[] {determineTransactionAspectClass()};
default:
return null;
}
}
- 4 ProxyTransactionManagementConfiguration完成核心类装配
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
//定义BeanFactoryTransactionAttributeSourceAdvisor
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
//设置AnnotationTransactionAttributeSource
advisor.setTransactionAttributeSource(transactionAttributeSource);
//设置TransactionInterceptor
advisor.setAdvice(transactionInterceptor);
if (this.enableTx != null) {
advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
}
return advisor;
}
//定义AnnotationTransactionAttributeSource
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
return new AnnotationTransactionAttributeSource();
}
//定义TransactionInterceptor
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {
TransactionInterceptor interceptor = new TransactionInterceptor();
interceptor.setTransactionAttributeSource(transactionAttributeSource);
if (this.txManager != null) {
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
}
三、结合AOP总结事务核心类的使用时机
这里总结的比较块,需要已经了解AOP的源码。以下基于AOP的源码来看看核心类【BeanFactoryTransactionAttributeSourceAdvisor、AnnotationTransactionAttributeSource、TransactionInterceptor】的使用时机。首先看看AOP的入口方法,该方法在AbstractAutoProxyCreator类中
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
...略
//获得与bean匹配的Advisor集合
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
//如果Advisor集合非空,开始构建代理对象
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;
}
AOP的主流程就在这里。一共两步,
- 其一获取所有与当前bean匹配的Advisor。结合事务来看主要是通过AnnotationTransactionAttributeSource于类进行匹配,如果匹配成功返回的Advisor集合就会包含BeanFactoryTransactionAttributeSourceAdvisor
- 其二如果Advisor集合不为空,通过Advisor集合构建代理对象。结合事务来看最终会将BeanFactoryTransactionAttributeSourceAdvisor中的TransactionInterceptor封装到代理对象中完成事务控制
接下来分别跟着下这两个分支
3.1 AnnotationTransactionAttributeSource的匹配时机和规则
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
//跟这个方法
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
可以看到核心逻辑在findEligibleAdvisors方法中,继续跟进
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
//获取所有Advisor
List<Advisor> candidateAdvisors = findCandidateAdvisors();
//过滤出于bean匹配的Advisor
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
这里主要有两步
- 获取所有的Advisor,这里包括BeanFactoryTransactionAttributeSourceAdvisor
- 过滤出于bean匹配的Advisor
接着重点看过滤bean匹配的Advisor
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
//最终委托AopUtils来进行匹配
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
将匹配工作委托给了AopUtils类,继续跟进findAdvisorsThatCanApply方法
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new ArrayList<>();
//BeanFactoryTransactionAttributeSourceAdvisor不是IntroductionAdvisor的子类 这个分支跳过
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;
}
我们关注的BeanFactoryTransactionAttributeSourceAdvisor不是IntroductionAdvisor的子类,所以IntroductionAdvisor相关的先跳过。重点看
canApply方法。
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;
//这里提取了Pointcut
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
// It doesn't have a pointcut so we assume it applies.
return true;
}
}
BeanFactoryTransactionAttributeSourceAdvisor是PointcutAdvisor的子类,所以可以强转。强制后可以拿到其内部的Pointcut。接着调用了
canApply的重载方法。
继续跟进之前,先了解下这里拿到的Pointcut是谁,和AnnotationTransactionAttributeSource有什么关系
public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {
@Nullable
private TransactionAttributeSource transactionAttributeSource;
private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
@Override
@Nullable
protected TransactionAttributeSource getTransactionAttributeSource() {
return transactionAttributeSource;
}
};
/**
* Set the transaction attribute source which is used to find transaction
* attributes. This should usually be identical to the source reference
* set on the transaction interceptor itself.
* @see TransactionInterceptor#setTransactionAttributeSource
*/
public void setTransactionAttributeSource(TransactionAttributeSource transactionAttributeSource) {
this.transactionAttributeSource = transactionAttributeSource;
}
/**
* Set the {@link ClassFilter} to use for this pointcut.
* Default is {@link ClassFilter#TRUE}.
*/
public void setClassFilter(ClassFilter classFilter) {
this.pointcut.setClassFilter(classFilter);
}
@Override
public Pointcut getPointcut() {
return this.pointcut;
}
}
这里可以看到Pointcut并不是TransactionAttributeSource,而是一个包含了TransactionAttributeSource的TransactionAttributeSourcePointcut。个人理解TransactionAttributeSourcePointcut相当于TransactionAttributeSource的一个适配器,用于支持spring的统一调用。其本质的匹配能力都是由TransactionAttributeSource来完成的。这里先做一个了解,等真正执行匹配时在进一步讨论。继续跟进canApply
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
//这里的pc 目前就是TransactionAttributeSourcePointcut
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;
}
//这里拿到bean的所有父类
Set<Class<?>> classes = new LinkedHashSet<>();
if (!Proxy.isProxyClass(targetClass)) {
classes.add(ClassUtils.getUserClass(targetClass));
}
//将bean和其所有父类封装到classes集合
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
//便利bean及其父类
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;
}
这个方法主要流程就是,从pc中获取方法匹配器MethodMatcher,然后通过MethodMatcher的matches方法和当前类全家的所有方法进行匹配。这里重点就是MethodMatcher是谁,还有其matches方法的逻辑。
TransactionAttributeSourcePointcut的getMethodMatcher方法是由其父类StaticMethodMatcherPointcut实现的。
public final MethodMatcher getMethodMatcher() {
return this;
}
这里返回了this也就是说MethodMatcher本质上就是TransactionAttributeSourcePointcut,所以接下来看看TransactionAttributeSourcePointcut的matches方法
public boolean matches(Method method, Class<?> targetClass) {
//这里拿到了TransactionAttributeSource
TransactionAttributeSource tas = getTransactionAttributeSource();
//最终通过TransactionAttributeSource的getTransactionAttribute方法完成匹配
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}
可以看到真正的匹配是由TransactionAttributeSource的getTransactionAttribute方法实现的,TransactionAttributeSourcePointcut本身只是一个适配器。那么设计之初为什么不把TransactionAttributeSource变成一个Pointcut,这里个人理解是TransactionAttributeSource本质是做@Transactional注解解析的和Pointcut没有一点关系,而Spring想通能否解析到@Transactional注解来做Pointcut的匹配结果,最终引入了TransactionAttributeSourcePointcut适配器继续跟getTransactionAttribute方法
public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
if (method.getDeclaringClass() == Object.class) {
return null;
}
//缓存机制 这个分支先跳过
Object cacheKey = getCacheKey(method, targetClass);
TransactionAttribute 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 cached;
}
}
//重点看下没有缓存的情况
else {
//最终通过txAttr是否为空来确定是否匹配
TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
// Put it in the cache.
if (txAttr == null) {
this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
}
else {
String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass);
if (txAttr instanceof DefaultTransactionAttribute) {
((DefaultTransactionAttribute) txAttr).setDescriptor(methodIdentification);
}
if (logger.isTraceEnabled()) {
logger.trace("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);
}
this.attributeCache.put(cacheKey, txAttr);
}
return txAttr;
}
}
上边分析可以知道,是否匹配是根据txAttr 是否为空来判断的,所以需要看下computeTransactionAttribute方法
protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
// Don't allow no-public methods as required.
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;
}
//获取原始方法,入参方法可能是接口方法。如果是接口方法这里会返回实现类方法
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
//实现类方法中上的@Transactional 解析成TransactionAttribute 不为空直接返回
TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
if (txAttr != null) {
return txAttr;
}
//实现类中上的@Transactional 解析成TransactionAttribute 不为空直接返回
txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
//如果实现类方法和入参方法不一样 说明入参方法可能是个接口
if (specificMethod != method) {
//接口方法上的@Transactional 解析成TransactionAttribute 不为空直接返回
txAttr = findTransactionAttribute(method);
if (txAttr != null) {
return txAttr;
}
//接口上的@Transactional 解析成TransactionAttribute 不为空直接返回
txAttr = findTransactionAttribute(method.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
}
return null;
}
这里主要分了四步
- 如果实现类方法上有@Transactional注解,将其解析成TransactionAttribute返回
- 如果实现类上有@Transactional注解,将其解析成TransactionAttribute返回
- 如果入参方法是接口方法,会继续向下走,否则返回null
- 如果接口类方法上有@Transactional注解,将其解析成TransactionAttribute返回
- 如果接口类上有@Transactional注解,将其解析成TransactionAttribute返回
为什么会提到@Transactional注解呢?需要接着看看findTransactionAttribute的实现
@Override
@Nullable
protected TransactionAttribute findTransactionAttribute(Class<?> clazz) {
return determineTransactionAttribute(clazz);
}
@Override
@Nullable
protected TransactionAttribute findTransactionAttribute(Method method) {
return determineTransactionAttribute(method);
}
这两个处理逻辑差不多,接下来随便选一个。就选入参是method的继续跟踪
//用于保存解析器
private final Set<TransactionAnnotationParser> annotationParsers;
//AnnotationTransactionAttributeSource无参构造器
public AnnotationTransactionAttributeSource() {
this(true);
}
//AnnotationTransactionAttributeSource有参构造器
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());
}
}
//会进入这个分支 解析器集合被初始化并添加SpringTransactionAnnotationParser解析器
else {
this.annotationParsers = Collections.singleton(new SpringTransactionAnnotationParser());
}
}
//接着跟进方法
protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
for (TransactionAnnotationParser parser : this.annotationParsers) {
//通过上边分析 可以知道这里的parser就是SpringTransactionAnnotationParser
TransactionAttribute attr = parser.parseTransactionAnnotation(element);
if (attr != null) {
return attr;
}
}
return null;
}
这里除了determineTransactionAttribute方法,还把和determineTransactionAttribute方法相关的全局变量以及构造器也一起列出来了。AnnotationTransactionAttributeSource在构造时会初始化解析器集合annotationParsers,并添加SpringTransactionAnnotationParser解析器。最终determineTransactionAttribute方法会通过SpringTransactionAnnotationParser的parseTransactionAnnotation方法对元素进行解析
public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
//寻找元素中的@Transactional注解,如果找到返回注解属性
AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
element, Transactional.class, false, false);
if (attributes != null) {
//将AnnotationAttributes解析成TransactionAttribute
return parseTransactionAnnotation(attributes);
}
else {
return null;
}
}
//解析操作
protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
//这里的属性都是@Transactional中定义的,将其封装到TransactionAttribute中
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"));
List<RollbackRuleAttribute> rollbackRules = new ArrayList<>();
for (Class<?> rbRule : attributes.getClassArray("rollbackFor")) {
rollbackRules.add(new RollbackRuleAttribute(rbRule));
}
for (String rbRule : attributes.getStringArray("rollbackForClassName")) {
rollbackRules.add(new RollbackRuleAttribute(rbRule));
}
for (Class<?> rbRule : attributes.getClassArray("noRollbackFor")) {
rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
}
for (String rbRule : attributes.getStringArray("noRollbackForClassName")) {
rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
}
rbta.setRollbackRules(rollbackRules);
return rbta;
}
这里可以看到其本质就是寻找元素上的@Transactional注解。并将@Transactional注解的属性解析后封装到TransactionAttribute对象中。
这里总结下AnnotationTransactionAttributeSource的匹配时机和规则
AnnotationTransactionAttributeSource的匹配时机是下寻找于bean匹配的Advisor时触发的,其匹配规则如下
- 如果实现类方法上有@Transactional注解,将其解析成TransactionAttribute返回
- 如果实现类上有@Transactional注解,将其解析成TransactionAttribute返回
- 如果入参方法是接口方法,会继续向下走,否则返回null
- 如果接口类方法上有@Transactional注解,将其解析成TransactionAttribute返回
- 如果接口类上有@Transactional注解,将其解析成TransactionAttribute返回
最终只要返回的TransactionAttribute非空就算匹配成功,也可以理解为只要类中有@Transactional就会匹配成功
3.2 TransactionInterceptor的增强时机
接着跟下代理类的创建逻辑
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
//拿到Advisor集合 这里包括BeanFactoryTransactionAttributeSourceAdvisor
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
//创建代理类 跟这里
return proxyFactory.getProxy(getProxyClassLoader());
}
这里主要是将Advisor集合传给ProxyFactory,然后委托ProxyFactory 完成代理类创建,继续跟getProxy
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
这里主要两步,第一通过createAopProxy获取是cglib代理工厂还是jdk代理工厂,第二通过getProxy方法构建代理对象。jdk比较熟悉这里假设返回的是jdk的代理工厂JdkDynamicAopProxy。接着跟下JdkDynamicAopProxy的getProxy方法
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
//动态代理构建代理对象
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
这里可以看到动态代理了。最后一个处理器的参数传入this,也就是说JdkDynamicAopProxy本质就是InvocationHandler,所以其一定有invoke方法。继续跟中
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
...略
Object retVal;
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// Get as late as possible to minimize the time we "own" the target,
// in case it comes from a pool.
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
//这里获得了一个增强方法链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
//如果无增强方法,直接调用连接点方法
if (chain.isEmpty()) {
// We can skip creating a MethodInvocation: just invoke the target directly
// Note that the final invoker must be an InvokerInterceptor so we know it does
// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// We need to create a method invocation...
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
//增强方法的调用 跟这里
retVal = invocation.proceed();
}
// Massage return value if necessary.
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// Special case: it returned "this" and the return type of the method
// is type-compatible. Note that we can't help if the target sets
// a reference to itself in another returned object.
retVal = proxy;
}
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
该方法比较长,不展开一一描述了,其主要流程如下
- getInterceptorsAndDynamicInterceptionAdvice方法通过Advisor集合获取MethodInterceptor集合。这里目的有三个
-
- 其一是Advisor集合是整个类的增强方法,所以需要二次过滤获取针对当前方法的增强方法集合
-
- 其二是提取Advisor中的Advice,因为增强方法只要Advice就够用了。其中BeanFactoryTransactionAttributeSourceAdvisor 中拿到的advice就是TransactionInterceptor
-
- 其三是个别Advice不是MethodInterceptor的子类需要做适配。统一适配成MethodInterceptor的目的是为了保证增强方法的执行顺序TransactionInterceptor就是MethodInterceptor的子类所以无需适配
- 将MethodInterceptor集合封装到ReflectiveMethodInvocation并执行其proceed方法进行增强方法的调用。继续跟proceed
public Object proceed() throws Throwable {
//this.interceptorsAndDynamicMethodMatchers 这里就是MethodInterceptor集合
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
//有方法重载的会走整个分支
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
}
//一般会进入这个分支 即执行MethodInterceptor的invoke方法
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
到这里可以知道TransactionInterceptor的invoke方法会被执行。接着跟踪invoke
public Object invoke(MethodInvocation invocation) throws Throwable {
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
//事务增强的全部逻辑都在该方法中执行
return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
}
TransactionInterceptor的增强逻辑都是在invokeWithinTransaction中实现的。该方法非常复杂涉及到了对事务传播性的处理。需要花费大量篇幅总结所以单独提取了一个分支TransactionInterceptor声明式学习总结
总结
Spring对事务的处理是基于AOP实现的,主要使用了三个核心类【BeanFactoryTransactionAttributeSourceAdvisor、AnnotationTransactionAttributeSource、TransactionInterceptor】。总结了核心类的加载、并且结合AOP的源码总结了核心类的调用时机。