1.事物的声明阶段

  @EnableTransactionManagement,是我们开启注解事物的第一步,我们来看下这个类为我们干了什么

  1. @Target(ElementType.TYPE)
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Documented
  4. @Import(TransactionManagementConfigurationSelector.class)
  5. public @interface EnableTransactionManagement {
  6.  
  7. boolean proxyTargetClass() default false;
  8.  
  9. AdviceMode mode() default AdviceMode.PROXY;
  10.  
  11. int order() default Ordered.LOWEST_PRECEDENCE;
  12. }

  我们主要看 TransactionManagementConfigurationSelector 干了件什么事情。它主要往spring 容器中导入了 AutoProxyRegistrar , ProxyTransactionManagementConfiguration两个对象。

  1. public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
  2. @Override
  3. protected String[] selectImports(AdviceMode adviceMode) {
  4. switch (adviceMode) {
  5. case PROXY:
  6. return new String[] {AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()};
  7. case ASPECTJ:
  8. return new String[] {TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME};
  9. default:
  10. return null;
  11. }
  12. }
  13.  
  14. }

ProxyTransactionManagementConfiguration的作用,我们可以看到此类是一个配置类,主要为spring容器中导入了3个bean。这三个bean分别的作用,我们下来详说

  1. @Configuration
  2. public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
  3.  
  4. @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
  5. @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
  6. public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
  7. BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
  8. advisor.setTransactionAttributeSource(transactionAttributeSource());
  9. advisor.setAdvice(transactionInterceptor());
  10. advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
  11. return advisor;
  12. }
  13.  
  14. @Bean
  15. @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
  16. public TransactionAttributeSource transactionAttributeSource() {
  17. return new AnnotationTransactionAttributeSource();
  18. }
  19.  
  20. @Bean
  21. @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
  22. public TransactionInterceptor transactionInterceptor() {
  23. TransactionInterceptor interceptor = new TransactionInterceptor();
  24. interceptor.setTransactionAttributeSource(transactionAttributeSource());
  25. if (this.txManager != null) {
  26. interceptor.setTransactionManager(this.txManager);
  27. }
  28. return interceptor;
  29. }
  30.  
  31. }

AutoProxyRegistrar 这个类,实现了ImportBeanDefinitionRegistrar接口,主要是为容器中注入了 InfrastructureAdvisorAutoProxyCreator 这个bean。

  1. public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
  2.  
  3. private final Log logger = LogFactory.getLog(getClass());
  4. @Override
  5. public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
  6. boolean candidateFound = false;
  7. Set<String> annoTypes = importingClassMetadata.getAnnotationTypes();
  8. for (String annoType : annoTypes) {
  9. AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annoType);
  10. if (candidate == null) {
  11. continue;
  12. }
  13. Object mode = candidate.get("mode");
  14. Object proxyTargetClass = candidate.get("proxyTargetClass");
  15. if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
  16. Boolean.class == proxyTargetClass.getClass()) {
  17. candidateFound = true;
  18. if (mode == AdviceMode.PROXY) {
  19. AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
  20. if ((Boolean) proxyTargetClass) {
  21. AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
  22. return;
  23. }
  24. }
  25. }
  26. }
  27. }
  28.   

  public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
    return registerAutoProxyCreatorIfNecessary(registry, null);
}

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

  1. }

我们首先来看一下这个类的继承关系图。

这个类首先是beanpostprocessor的实现类,他会对所有的bean做一次后置增强处理,我们在AbstractAutoProxyCreator中的 postProcessAfterInitialization 方法中可以看到,他会根据规则去对bean包装从而创造满足条件的代理。

  1. /**
  2. * Create a proxy with the configured interceptors if the bean is
  3. * identified as one to proxy by the subclass.
  4. * @see #getAdvicesAndAdvisorsForBean
  5. */
  6. @Override
  7. public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  8. if (bean != null) {
  9. Object cacheKey = getCacheKey(bean.getClass(), beanName);
  10. if (!this.earlyProxyReferences.contains(cacheKey)) {
  11. return wrapIfNecessary(bean, beanName, cacheKey);
  12. }
  13. }
  14. return bean;
  15. }

我们接下来进入 wrapIfNecessary 方法

  1. // 如果需要的话,包装给定的bean,也就是说它是否有资格代理。
  2. protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
  3. if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
  4. return bean;
  5. }
  6. if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
  7. return bean;
  8. }
  9. if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
  10. this.advisedBeans.put(cacheKey, Boolean.FALSE);
  11. return bean;
  12. }
  13.  
  14. // Create proxy if we have advice.
  15. Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
  16. if (specificInterceptors != DO_NOT_PROXY) {
  17. this.advisedBeans.put(cacheKey, Boolean.TRUE);
  18. Object proxy = createProxy(
  19. bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
  20. this.proxyTypes.put(cacheKey, proxy.getClass());
  21. return proxy;
  22. }
  23.  
  24. this.advisedBeans.put(cacheKey, Boolean.FALSE);
  25. return bean;
  26. }

我们着重关注一下 getAdvicesAndAdvisorsForBean 方法

  1. @Override
  2. protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
  3. List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
  4. if (advisors.isEmpty()) {
  5. return DO_NOT_PROXY;
  6. }
  7. return advisors.toArray();
  8. }

这个方法没什么说的,主要表达的意思是为bean找到合格的增强器。

  1. protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
         // 找到所有的候选者
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
  2. // 从候选者中找到合格的
         List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
  3. extendAdvisors(eligibleAdvisors);
  4. if (!eligibleAdvisors.isEmpty()) {
  5. eligibleAdvisors = sortAdvisors(eligibleAdvisors);
  6. }
  7. return eligibleAdvisors;
  8. }

在 findCandidateAdvisors 方法中,我们可以看到我们上文中注入的三个bean中的其中一个 BeanFactoryTransactionAttributeSourceAdvisor,这个bean可以理解为我们的事物增强器。

  1. public List<Advisor> findAdvisorBeans() {
  2. // Determine list of advisor bean names, if not cached already.
  3. String[] advisorNames = null;
  4. synchronized (this) {
  5. advisorNames = this.cachedAdvisorBeanNames;
  6. if (advisorNames == null) {
  7. // 找到上文注入的 BeanFactoryTransactionAttributeSourceAdvisor
  8. advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
  9. this.beanFactory, Advisor.class, true, false);
  10. this.cachedAdvisorBeanNames = advisorNames;
  11. }
  12. }
  13. if (advisorNames.length == 0) {
  14. return new LinkedList<Advisor>();
  15. }return advisors;
  16. }

接下来我们看 findAdvisorsThatCanApply 方法,这个方法主要实现了,候选的增强器是否可以对当前bean使用。

  1. public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
  2. if (candidateAdvisors.isEmpty()) {
  3. return candidateAdvisors;
  4. }
  5. List<Advisor> eligibleAdvisors = new LinkedList<Advisor>();
  6. for (Advisor candidate : candidateAdvisors) {
  7. if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
  8. eligibleAdvisors.add(candidate);
  9. }
  10. }
  11. boolean hasIntroductions = !eligibleAdvisors.isEmpty();
  12. for (Advisor candidate : candidateAdvisors) {
  13. if (candidate instanceof IntroductionAdvisor) {
  14. // already processed
  15. continue;
  16. }
  17. if (canApply(candidate, clazz, hasIntroductions)) {
  18. eligibleAdvisors.add(candidate);
  19. }
  20. }
  21. return eligibleAdvisors;
  22. }

我们进入方法走到canApply处,继续往下跟。

  1. public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
  2. if (advisor instanceof IntroductionAdvisor) {
  3. return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
  4. }
  5. else if (advisor instanceof PointcutAdvisor) {
  6. PointcutAdvisor pca = (PointcutAdvisor) advisor;
  7. return canApply(pca.getPointcut(), targetClass, hasIntroductions);
  8. }
  9. else {
  10. // It doesn't have a pointcut so we assume it applies.
  11. return true;
  12. }
  13. }

先判断类型后做一次转化,再次进入canApply方法

  1. public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
  2. Assert.notNull(pc, "Pointcut must not be null");
  3. if (!pc.getClassFilter().matches(targetClass)) {
  4. return false;
  5. }
  6.  
  7. MethodMatcher methodMatcher = pc.getMethodMatcher();
  8. if (methodMatcher == MethodMatcher.TRUE) {
  9. // No need to iterate the methods if we're matching any method anyway...
  10. return true;
  11. }
  12.  
  13. IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
  14. if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
  15. introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
  16. }
  17.  
  18. Set<Class<?>> classes = new LinkedHashSet<Class<?>>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
  19. classes.add(targetClass);
  20. for (Class<?> clazz : classes) {
  21. Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
  22. for (Method method : methods) {
  23. if ((introductionAwareMethodMatcher != null &&
  24. introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
  25. methodMatcher.matches(method, targetClass)) {
  26. return true;
  27. }
  28. }
  29. }
  30.  
  31. return false;
  32. }

进入matches方法,下来的代码我会合并的连贯一些

  1. @Override
  2. public boolean matches(Method method, Class<?> targetClass) {
  3. if (targetClass != null && TransactionalProxy.class.isAssignableFrom(targetClass)) {
  4. return false;
  5. }
  6. TransactionAttributeSource tas = getTransactionAttributeSource();
  7. return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
  8. }
    // 进入AbstractFallbackTransactionAttributeSource.getTransactionAttribute()
      TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
      TransactionAttribute txAttr = findTransactionAttribute(specificMethod);

进入解析的流程

  1. public class SpringTransactionAnnotationParser implements TransactionAnnotationParser, Serializable {
  2.  
  3. @Override
  4. public TransactionAttribute parseTransactionAnnotation(AnnotatedElement ae) {
  5. AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ae, Transactional.class);
  6. if (attributes != null) {
  7. return parseTransactionAnnotation(attributes);
  8. }
  9. else {
  10. return null;
  11. }
  12. }
  13.  
  14. public TransactionAttribute parseTransactionAnnotation(Transactional ann) {
  15. return parseTransactionAnnotation(AnnotationUtils.getAnnotationAttributes(ann, false, false));
  16. }
  17.  
  18. protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
  19. RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
  20. Propagation propagation = attributes.getEnum("propagation");
  21. rbta.setPropagationBehavior(propagation.value());
  22. Isolation isolation = attributes.getEnum("isolation");
  23. rbta.setIsolationLevel(isolation.value());
  24. rbta.setTimeout(attributes.getNumber("timeout").intValue());
  25. rbta.setReadOnly(attributes.getBoolean("readOnly"));
  26. rbta.setQualifier(attributes.getString("value"));
  27. ArrayList<RollbackRuleAttribute> rollBackRules = new ArrayList<RollbackRuleAttribute>();
  28. Class<?>[] rbf = attributes.getClassArray("rollbackFor");
  29. for (Class<?> rbRule : rbf) {
  30. RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);
  31. rollBackRules.add(rule);
  32. }
  33. String[] rbfc = attributes.getStringArray("rollbackForClassName");
  34. for (String rbRule : rbfc) {
  35. RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);
  36. rollBackRules.add(rule);
  37. }
  38. Class<?>[] nrbf = attributes.getClassArray("noRollbackFor");
  39. for (Class<?> rbRule : nrbf) {
  40. NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);
  41. rollBackRules.add(rule);
  42. }
  43. String[] nrbfc = attributes.getStringArray("noRollbackForClassName");
  44. for (String rbRule : nrbfc) {
  45. NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);
  46. rollBackRules.add(rule);
  47. }
  48. rbta.getRollbackRules().addAll(rollBackRules);
  49. return rbta;
  50. }
  51. }

此方法会先拿到标记为 Transcantional 注解的方法,然后遍历属性。最后返回attr,如果解析到的attr不为空,则会将此增强器对待增强的bean做增强处理。

  1. protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
  2. if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
  3. return bean;
  4. }
  5. if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
  6. return bean;
  7. }
  8. if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
  9. this.advisedBeans.put(cacheKey, Boolean.FALSE);
  10. return bean;
  11. }
  12.  
  13. // Create proxy if we have advice.
  14. Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
  15. if (specificInterceptors != DO_NOT_PROXY) {
  16. this.advisedBeans.put(cacheKey, Boolean.TRUE);
  17. Object proxy = createProxy(
  18. bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
  19. this.proxyTypes.put(cacheKey, proxy.getClass());
  20. return proxy;
  21. }
  22.  
  23. this.advisedBeans.put(cacheKey, Boolean.FALSE);
  24. return bean;
  25. }

我们回到 wrapIfNecessary方法,如果返回的advisor不为空,我们会为他生成代理对象。

Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));

这里就跟我们的使用AOP创建代理无缝融合,在找到当前bean确定要进行增强处理和增强的advisor后,使用动态代理的方式创建代理对象。

 

spring事物(一),@EnableTransactionManagement @Transactional 启动解析的更多相关文章

  1. Spring源码解析02:Spring IOC容器之XmlBeanFactory启动流程分析和源码解析

    一. 前言 Spring容器主要分为两类BeanFactory和ApplicationContext,后者是基于前者的功能扩展,也就是一个基础容器和一个高级容器的区别.本篇就以BeanFactory基 ...

  2. Spring源码解析 | 第二篇:Spring IOC容器之XmlBeanFactory启动流程分析和源码解析

    一. 前言 Spring容器主要分为两类BeanFactory和ApplicationContext,后者是基于前者的功能扩展,也就是一个基础容器和一个高级容器的区别.本篇就以BeanFactory基 ...

  3. spring 事物的一些理解

    推荐一个我认为Spring事物写得很好的文章. 文章链接:http://www.codeceo.com/article/spring-transactions.html  文章作者:码农网 – 吴极心 ...

  4. Spring事物

    简介 Spring并不直接管理事务,而是提供了多种事务管理器,他们将事务管理的职责委托给Hibernate或者JTA等持久化机制所提供的相关平台框架的事务来实现. Spring事务管理器的接口是org ...

  5. MyBatis6:MyBatis集成Spring事物管理(下篇)

    前言 前一篇文章<MyBatis5:MyBatis集成Spring事物管理(上篇)>复习了MyBatis的基本使用以及使用Spring管理MyBatis的事物的做法,本文的目的是在这个的基 ...

  6. spring事物的传播行为

    1.spring事物的传播行为,主要是用来解决业务层拥有事物的方法,相互调用的问题. 2.声明事物, 在代码执行前,开启事务.代码执行完,提交事务 3.spring并没有提供事务具体的处理,而只是调用 ...

  7. Spring 事物Transaction

    日常开发中Spring 为我们提供了两种事物的定义方式 XML 配置 方式 :这种方式配置起来比较麻烦,但后期比较好进行维护 注解方式:配置起来比较方便,也是日常开发常用的: 我们这里进行第二种注解的 ...

  8. spring事物深入了解

    1.问题 1.以前对事物的了解只是停留在声明式事物,配置xml,或使用注解,事物的传播行为也只用过REQUIRED和SUPPORTS,可以说对事物的了解很模糊. 2.直到在开发中遇到问题.. 问题的描 ...

  9. 事物注解方式: @Transactional

    当标于类前时, 标示类中所有方法都进行事物处理 , 例子: 1 @Transactional public class TestServiceBean implements TestService { ...

随机推荐

  1. %E3%80%90%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B%E3%80%91

    "%3Cdiv%20class%3D%22htmledit_views%22%20id%3D%22content_views%22%3E%0A%20%20%20%20%20%20%20%20 ...

  2. TomcatJVM参数优化降低内存使用率(重点)!

    JVM是jdk最底层的支柱 做JVM参数优化主要是为了改善服务器性能以及内存使用率 JAVA堆分为三大部分:(新生代.老年代.永久代) ================================ ...

  3. 浅谈Java三大特性之继承

    前言 简单用伪代码去介绍一些 父类与子类的构造函数问题 others 前言 类的继承性是面向对象语言的基本特性,多态性前提是继承性.Java 支持继承性和多态性.——Java从小白到大牛 继承:三大特 ...

  4. 3分钟让你的Eclipse拥有自动代码提示功能

    第一步:Window->Preferences->Java 第二步:Java->Editor->Content Assist->Auto Activation->将 ...

  5. updataxml报错注入

    // take the variables//接受变量 // //也就是插入post提交的uname和passwd,参见:https://www.w3school.com.cn/sql/sql_ins ...

  6. 更新Android Studio,提示后直接点更新即可。gradle 两种更新方法,我用的第二种:手动添加gradle

    直接更新即可. 更新完毕后,随即会让你更新gradle,但是会一直更新一直更新...... 解决方法: 第一种方法: 手动下载Android Studio 对应的 gradle版本,然后设置一下即可. ...

  7. 140、Java内部类之实例化内部类对象

    01.代码如下: package TIANPAN; class Outer { // 外部类 private String msg = "Hello World !"; class ...

  8. ypeError: __init__() got an unexpected keyword argument 'shape'

    采用TensorFlow支持通过tf.Graph函数来生成新的向量图,代码如下: import tensorflow as tf g1 = tf.Graph() with g1.as_default( ...

  9. unity 骨骼 蒙皮

    https://blog.csdn.net/weixin_44350205/article/details/100551233 https://www.jianshu.com/p/d5e2870eb3 ...

  10. HTML<video></video>视频无法自动播放

    1.video 标签属性 src: 设置显示视频路径 controls: 显示控制栏 loop: 控制视频循环播放 autoplay: 自动播放 muted:设置静音播放 2.解决视频或音频标签自动播 ...