ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

SpringAOP[8]-如何自动代理@Transactional

2021-11-16 04:00:13  阅读:190  来源: 互联网

标签:return Transactional 代理 method txAttr SpringAOP new null public


事务的自动代理器为InfrastructureAdvisorAutoProxyCreator,若同时注册多个AbstractAutoProxyCreator子类,可能会存在多处代理的情况。

多次代理的效果如下图所示:

 

为什么该类会被二次代理呢?

@Configuration
@EnableTransactionManagement  //注册了一个自动代理器
public class DefaultAdvisorAutoProxyCreatorConfig {
    //目标类
    @Bean("tService")
    public TService tService() {
        return new TService();
    }
    //注册了一个自动代理器
    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        defaultAdvisorAutoProxyCreator.setProxyTargetClass(true); //启用cglib代理
        return defaultAdvisorAutoProxyCreator;
    }
}
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext =
                new AnnotationConfigApplicationContext(DefaultAdvisorAutoProxyCreatorConfig.class);
        //可以使用@Primary指定元素,或直接使用name名获取。
        TService bean = (TService) applicationContext.getBean("tService");
        bean.say();
    }

上述代码实际上注册了两个自动代理器,而他们均是继承于org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator

 

  

AbstractAutoProxyCreator类作用是为Bean生成代理对象,如何获取到beanAdvisor。它是交由了子类去实现。

AbstractAdvisorAutoProxyCreator作为子类,实现了自动获取Advisor的逻辑(实现了getAdvicesAndAdvisorsForBean)。


1. 自动代理含义

1. 获取整个Spring容器Advisor类型的bean,由生成器决定是否处理该Advisor。(若多个生成器均决定处理一个Advisor,可能存在二次代理)。

2. 每个生成器开始遍历自己决定处理的Advisor。通过Advisor的pointcut查看是否能切入bean。返回所有能够切入的Advisor。

3. 创建Proxy时,将能切入的Advisor传入,即完成自动代理。

 

 

解决上述二次代理的问题,即不要去注册defaultAdvisorAutoProxyCreator

 

2. 事务增强器织入bean

首先解析类/方法上的事务注解,若存在则解析为属性对象。那么如何判断注解是否存在?且如何解析为属性对象?

先抛开源码,看两个main函数(不依赖Spring容器)

2.1 解析自定义标签

自定义注解:

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface MyTransaction {
    String value() default "";
}
public class TService {
    @MyTransaction("解析自定义注解")
    public void run1() {
        System.out.println("This is a run1() Method!");
    }
    @Transactional
    public void say() {
        log.info("说话...");
    }
}

解析注解:

    @Test
    public void test4() throws NoSuchMethodException {
        Method method = TService.class.getMethod("run1");
        //读取事务注解
        AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
                method, MyTransaction.class, false, false);
        System.out.println(attributes);
    }

 

2.2 解析事务标签

得到的AnnotationAttributes对象,如何转化为一个我们自定义的属性对象呢

public void test1() throws NoSuchMethodException {  
    Method say = TService.class.getMethod("say");  
    //读取事务注解  
    AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(  
            say, Transactional.class, false, false);  
    //脱离Spring  
    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"));  
    //定义回滚策略  
    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);  
    System.out.println(JSON.toJSONString(rbta));  
}  

有小伙伴此时一定会好奇RollbackRuleAttribute对象是干啥的。

@Test  
public void test3() {  
    RollbackRuleAttribute rollbackRuleAttribute = new RollbackRuleAttribute(ArithmeticException.class);  
    try {  
        throw new BusinessException("业务异常");  
    } catch (Exception e) {  
        //判断抛出的e(及其父类)是否是ArithmeticException异常  
        int depth = rollbackRuleAttribute.getDepth(e);  
        System.out.println(depth);  
    }  
}  

也就是说,若异常(及其父类)符合指定的异常,返回正数;否则返回-1;
这样的话,就能决定是否是回滚的异常。

 

此时,注解标签解析为了属性对象。

 

2.3 Spring的事务切点

判断方法是否匹配时,会遍历bean中所有访问权限的方法。Spring会遍历public方法,判断该method/class上是否存在Transactional注解。若存在,解析为属性对象,且通过匹配。

 

 

3. Spring解析事务注解

 

3.1 增强器的注册

首先需要存在一个Advisor负责去增强@Transactional标签的方法。
注意:BeanFactoryTransactionAttributeSourceAdvisor实现的是PointcutAdvisor接口,既可以设置Advice,又可以设置Pointcut。
但是下面代码中只配置了Adice,而pointcut是由BeanFactoryTransactionAttributeSourceAdvisor类完成的配置。
@Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
    //注册了Advisor
    @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)  //声明的role为基础类(Spring内部使用的类)
    public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
        BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
        advisor.setTransactionAttributeSource(transactionAttributeSource());
       //配置Advice
        advisor.setAdvice(transactionInterceptor());
        if (this.enableTx != null) {
            advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
        }
        return advisor;
    }

    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public TransactionAttributeSource transactionAttributeSource() {
        return new AnnotationTransactionAttributeSource();
    }
    //注册了Advice
    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public TransactionInterceptor transactionInterceptor() {
        TransactionInterceptor interceptor = new TransactionInterceptor();
        interceptor.setTransactionAttributeSource(transactionAttributeSource());
        if (this.txManager != null) {
            interceptor.setTransactionManager(this.txManager);
        }
        return interceptor;
    }
}
public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {

    @Nullable
    private TransactionAttributeSource transactionAttributeSource;
    //pointcut 是TransactionAttributeSourcePointcut 的子类,实现了TransactionAttributeSource 方法。
    //该方法的作用,是用户可以配置`解析器`。
    private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
        @Override
        @Nullable
        protected TransactionAttributeSource getTransactionAttributeSource() {
            return transactionAttributeSource;
        }
    };
}

 

 

3.2 方法匹配

如何判断bean方法符合规则?判断是否能获取事务属性对象。

自动代理器会遍历bean的所有方法,判断是否与MethodMatcher匹配。实际上会调用TransactionAttributeSourcePointcutmatches方法。

abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {

    @Override
    public boolean matches(Method method, Class<?> targetClass) {
        TransactionAttributeSource tas = getTransactionAttributeSource();
        //若TransactionAttributeSource 对象不为空,那么获取方法上的事务属性对象。
        return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
    }
    //抽象方法,但是注册的Advisor中的pointcut是TransactionAttributeSourcePointcut 子类。
    //实际上获取的是TransactionAttributeSource 对象
    @Nullable
    protected abstract TransactionAttributeSource getTransactionAttributeSource();
}

 

 

3.3 事务属性获取

解析事务注解,获取事务属性对象。

实际上TransactionAttributeSource为3.1配置的AnnotationTransactionAttributeSource对象。

当然这个类实现的只是特有的方法,而算法骨干由其父类AbstractFallbackTransactionAttributeSource实现。

注意getTransactionAttribute方法返回null,则证明pointcut不匹配bean的某方法。

public abstract class AbstractFallbackTransactionAttributeSource implements TransactionAttributeSource {

    @Override
    @Nullable
    public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
        //若是Object的方法,直接返回null
        if (method.getDeclaringClass() == Object.class) {
            return null;
        }
        // 首先看缓存是否存在
        Object cacheKey = getCacheKey(method, targetClass);
        TransactionAttribute cached = this.attributeCache.get(cacheKey);
        if (cached != null) {
            if (cached == NULL_TRANSACTION_ATTRIBUTE) {
                return null;
            }
            else {
                return cached;
            }
        }
        else {
            //获取TransactionAttribute 对象的核心方法(如下所示)
            TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
            //填充缓存
            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;
        }
    }
    @Nullable
    protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
        // 该方法是否要求必须是public级别(因为自动代理会对所有方法进行代匹配)
        if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
            return null;
        }
        //获取明确类的方法(处理桥接方法)
        Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
        //由子类实现(获取方法上的事务配置)
        TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
        if (txAttr != null) {
            return txAttr;
        }
        //由子类实现(获取类上的事务配置)
        txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
        if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
            return txAttr;
        }
        //获取原始方法上的事务配置
        if (specificMethod != method) {
            // Fallback is to look at the original method.
            txAttr = findTransactionAttribute(method);
            if (txAttr != null) {
                return txAttr;
            }
            // Last fallback is the class of the original method.
            txAttr = findTransactionAttribute(method.getDeclaringClass());
            if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
                return txAttr;
            }
        }
        return null;
    }

}

下图的两个抽象方法,由子类实现。

 

还需要注意的一个细节,AnnotationTransactionAttributeSource是其唯一子类。
public class AnnotationTransactionAttributeSource extends AbstractFallbackTransactionAttributeSource
        implements Serializable {
    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 {
            //通用模式下,为SpringTransactionAnnotationParser解析器
            this.annotationParsers = Collections.singleton(new SpringTransactionAnnotationParser());
        }
    }
    @Override
    @Nullable
    protected TransactionAttribute findTransactionAttribute(Class<?> clazz) {
        return determineTransactionAttribute(clazz);
    }

    @Override
    @Nullable
    protected TransactionAttribute findTransactionAttribute(Method method) {
        return determineTransactionAttribute(method);
    }
    //遍历解析器,获取事务注解(方法如2.2所示)
    @Nullable
    protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
        for (TransactionAnnotationParser parser : this.annotationParsers) {
            TransactionAttribute attr = parser.parseTransactionAnnotation(element);
            if (attr != null) {
                return attr;
            }
        }
        return null;
    }
}

parseTransactionAnnotation()方法如2.2所示,遍历方法/类上的事务注解。获取到TransactionAttribute对象。

 

MethodMatcher返回true,则证明该方法可以被事务增强器去增强。将Advisor加入到List中,并开始处理下一个Advisor。最终获取到所有可切入的Advisor。去创建代理对象。

 

 

标签:return,Transactional,代理,method,txAttr,SpringAOP,new,null,public
来源: https://www.cnblogs.com/chenxingyang/p/15559352.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有