• 回炉Spring-AOP及事务源码解读


    一、AOP

      AOP,面向切面编程

      即拓展功能不通过修改源代码来实现。

      采用横向抽取机制,取代了传统的纵向继承体系的重复性代码。在运行期间通过代理方式向目标类中织入增强代码。

      

    实现一个AOP的步骤:

      1、将需要增强的目标类和切面类都注入到Spring容器中,标注使Spring知道哪个是切面类,@Aspect(曾犯错,在切面类上没有标注@Component注解)

      2、在切面类上的通知方法上标注通知注解(如@Around,@Before等),并在注解中指明切入点表达式

      3、开启基于注解的aop模式,在配置类上加上注解@EnableAspectJAutoProxy

        注:(SpringBoot默认开启了基于注解的AOP模式,不用再启动类上再加@EnableAspectJAutoProxy)

        

    @AfterReturning注解的returning可将增强方法的返回值映射到参数上

        @AfterReturning(value = "pointCut()", returning = "result")
        public void afterReturning(Object result) throws Throwable {}

    @AfterThrowing(value="pointCut()",throwing="exception")的throwing将增强方法的异常信息映射到参数上

    获取切入点方法名:joinPoint.getSignature().getName() 

    获取方法入参:joinPoint.getArgs()

        @Before("pointCut()")
        // 方法若有多个参数,JoinPoint一定要放在第一位
        public void before(JoinPoint joinPoint) {
            String name = joinPoint.getSignature().getName();
            Object[] args = joinPoint.getArgs();
        }

    AOP原理:

      @EnableAspectJAutoProxy注解做了什么?

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Import(AspectJAutoProxyRegistrar.class)
    public @interface EnableAspectJAutoProxy {...}

      @EnableAspectJAutoProxy往容器中导入了AspectJAutoProxyRegistrar,利用AspectJAutoProxyRegistrar自定义往容器中注册了name为org.springframework.aop.config.internalAutoProxyCreator,class为AnnotationAwareAspectJAutoProxyCreator的bean。

      也就是说,@EnableAspectJAutoProxy往Spring容器中注册了AnnotationAwareAspectJAutoProxyCreator这个bean。

      技巧:如果看到了Enable开头的注解,就看这个注解有没有往容器中注册一些组件,如果注册组件了,这些组件的功能是什么,如果具体功能搞明白了,那么这个注解的原理就清楚了。

      那么既然@EnableAspectJAutoProxy往Spring容器中注册了AnnotationAwareAspectJAutoProxyCreator这个bean(从名字看是:注解装配切面代理创造器),那就看一下这个bean的功能是什么,源码走起:

      AnnotationAwareAspectJAutoProxyCreator 的继承关系如下:

      

    看到其祖先类实现了InstantiationAwareBeanPostProcessor 接口,而此接口又实现了BeanPostProcessor接口,而这个接口我们知道叫做后置处理器,后置处理器的功能就是在bean初始化的前后做一些工作。

    抽象父类AbstractAutoProxyCreator 又实现了BeanFactoryAware,可以往代码中注入BeanFactory。

    那么先重点看与setBeanFactory以及与后置处理器相关的逻辑,通过源码发现AbstractAutoProxyCreator有setBeanFactory()以及后置处理器相关的逻辑。而在AbstractAutoProxyCreator的子抽象类AbstractAdvisorAutoProxyCreator又重写了setBeanFactory()方法

    public void setBeanFactory(BeanFactory beanFactory) {
        super.setBeanFactory(beanFactory);
        if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
            throw new IllegalArgumentException("AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory);
        } else {
            this.initBeanFactory((ConfigurableListableBeanFactory)beanFactory);
        }
    }

    由于其子类AnnotationAwareAspectJAutoProxyCreator 重写了initBeanFactory方法,所以最终调用的是AnnotationAwareAspectJAutoProxyCreator 中的initBeanFactory方法中的逻辑:

    protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
            super.initBeanFactory(beanFactory);
            if (this.aspectJAdvisorFactory == null) {
                this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
            }
    
            this.aspectJAdvisorsBuilder = new AnnotationAwareAspectJAutoProxyCreator.BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
        }

     

    断点看AOP的整个执行流程:

    1、new AnnotationConfigApplicationContext(AopConfig.class); 创建Spring容器,接下来看其构造器逻辑

    2、先注册配置类,然后调用refresh()方法刷新容器,接下来看refresh()的逻辑

    3、invokeBeanFactoryPostProcessors(beanFactory);实例化并调用所有注册的BeanFactoryPostProcessor

    4、registerBeanPostProcessors(beanFactory); 注册bean的后置处理器来拦截bean的创建

      1):先获取ioc容器中已经定义了的所有实现BeanPostProcessor接口的后置处理器的name.  String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

      2):给容器中添加了额外的BeanPostProcessor  beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

      3):遍历所有的BeanPostProcessor,按照实现了PriorityOrdered接口的,和实现了Ordered接口的进行分组,分别保存在不同的List集合中

          ①:若实现了PriorityOrdered,则先创建其对象,当成普通bean注册到Spring容器中,然后将其放进priorityOrderedPostProcessors集合,若其又实现了MergedBeanDefinitionPostProcessor,将其再放进internalPostProcessors集合;

          ②:若其实现了Ordered接口,将其bean name放入orderedPostProcessorNames集合;

          ③:若两个接口都没实现,则将其bean name放进nonOrderedPostProcessorNames集合;

      4):优先注册实现了PriorityOrdered接口的BeanPostProcessor作为bean的后置处理器到Spring容器中,再注册实现了Ordered接口的BeanPostProcessor,最后注册其他的BeanPostProcessor.

         注册的BeanPostProcessor保存在AbstractBeanFactory的 private final List<BeanPostProcessor> beanPostProcessors = new BeanPostProcessorCacheAwareList();集合属性中

      5):注册其实就是步骤3)中的根据其name获取BeanPostProcessor对象{BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);},实际上就是创建BeanPostProcessor对象然后将其保存在Spring容器中。

          以创建name为internalAutoProxyCreator的BeanPostProcessor【AnnotationAwareAspectJAutoProxyCreator】为例,看一下创建过程:

        (1):创建bean的实例,getBean()——doGetBean()——getSingleton()——getObject()——createBean()——doCreateBean()

        (2):populateBean:给bean的各种属性赋值

        (3):initializeBean:初始化bean

           ①:invokeAwareMethods()判断bean是不是实现了xxxAware接口,如果实现了就调用相关的setXxx方法给bean的属性赋值

           ②:Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);应用bean的后置处理器的初始化前置方法,获取所有的后置处理器(之前注册保存在AbstractBeanFactoryList<BeanPostProcessor>属性中),遍历调用它们的postProcessBeforeInitialization()方法

           ③:invokeInitMethods(beanName, wrappedBean, mbd); 执行初始化方法,先@PostConstruct() 注解方法,然后如果实现了InitializingBean,执行afterPropertiesSet,再执行自定义的初始化方法(如果在@Bean注解指定了initMethod的话)

           ④:Object wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);应用bean的后置处理器的初始化后置方法,获取所有的后置处理器,遍历调用其postProcessAfterInitialization()方法

      6):由于AnnotationAwareAspectJAutoProxyCreator实现了 BeanFactoryAware接口,所以在invokeAwareMethods()方法中,回到了上面说的调用其抽象父类AbstractAdvisorAutoProxyCreator重写的setBeanFactory()方法。然后走到了AnnotationAwareAspectJAutoProxyCreator 的initBeanFactory()方法,至此,BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)创建成功

      7):最后将所有的BeanPostProcessor注册到BeanFactory

        registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

        -->beanFactory.addBeanPostProcessor(postProcessor);

        注册的BeanPostProcessor保存在AbstractBeanFactoryprivate final List<BeanPostProcessor> beanPostProcessors = new BeanPostProcessorCacheAwareList();集合属性中

      以上就是创建和注册AnnotationAwareAspectJAutoProxyCreator的过程。

      接下来看其作为一个BeanPostProcessor如何影响bean的创建过程的:

    5、finishBeanFactoryInitialization(beanFactory);完成BeanFactory初始化工作,创建剩下的单实例bean,为什么说是剩下的呢?因为BeanPostProcessors类型的bean在步骤4已经创建

      完成了

      1):preInstantiateSingletons()-->遍历获取容器中所有的beanDefinitionNames,遍历依此创建对象getBean(beanName); 在DefaultListableBeanFactory类中

      2):getBean(beanName)-->doGetBean()-->getSingleton(beanName) ,在创建bean之前先尝试获取单实例Bean的实例,为什么呢?因为只要创建好的bean就会被缓存起来

        ①:先去JVM缓存 private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);  /** Cache of singleton objects: bean name to bean instance. */ 中去获取缓存的创建好了的单实例bean对象

        ②:若创建完成的单实例bean缓存中没有,再去当前创建bean池中去尝试获取。

          当前创建bean池:private final Set<String> singletonsCurrentlyInCreation =Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(16)); // 池中保存中的是 bean name

          因为在创建单实例bean的时候会存在依赖注入的情况,为了避免循环依赖,Spring在创建bean的过程中,若发现有依赖bean,则尝试去创建依赖的bean,因此Spring将每一个正在创建的bean的beanName放在一个“当前创建bean池”中,bean在创建过程中,BeanName将一直存在这个池中。

        ③:如果当前线程创建bean池有,则尝试从提前创建单例bean缓存中加载bean:private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16); /** Cache of early singleton objects: bean name --> bean instance */

        ④:如果earlySingletonObjects 缓存中加载不成功,则再次尝试从singletonFactories中获取提前曝光的ObjectFactory,private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16); /** Cache of singleton factories: bean name --> ObjectFactory */

          如果根据beanName找到了ObjectFactory,则从ObjectFactory中获取bean实例,然后将其放在earlySingletonObjects 缓存中,再将其ObjectFactory从singletonFactories中移除。

          因为Spring为了避免循环依赖,在Spring中创建bean的原则是不等bean创建完就会将创建bean的ObjectFactory提早曝光加入到缓存中,一旦下一个bean创建时候需要依赖上一个bean则直接使用ObjectFactory去获取依赖bean的实例。

          

      3):createBean()  创建bean实例

        ①:Object bean=resolveBeforeInstantiation(beanName, mbdToUse); 参数:RootBeanDefinition mbdToUse,bean的定义信息。

           方法的作用是:给BeanPostProcessor一个机会返回一个代理对象就不用创建其对象了。如果可以,直接返回代理对象,如果不能,则继续执行doCreateBean(beanName, mbdToUse, args);,其实现为:

                bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                        if (bean != null) {
                            bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                        }

          这个方法的逻辑是:先拿到所有的后置处理器然后遍历,如果其中一个后置处理器实现了InstantiationAwareBeanPostProcessor接口,则执行这个后置处理器的postProcessBeforeInstantiation方法,如果返回了bean对象,则执行applyBeanPostProcessorsAfterInitialization并返回bean实例,结束bean的创建,不走下面的doCreateBean

       

        注意:InstantiationAwareBeanPostProcessor虽继承了BeanPostProcessor,但其定义了postProcessBeforeInstantiation和postProcessAfterInstantiation方法,与BeanPostProcessor的postProcessBeforeInitialization和postProcessAfterInitialization方法不同,BeanPostProcessor的两个方法是在bean实例创建完成之后的初始化前后调用的,而InstantiationAwareBeanPostProcessor的两个方法是在创建bean实例之前尝试返回代理对象的。

        这也是AnnotationAwareAspectJAutoProxyCreator的功能,在所有的bean创建之前会有一个拦截,尝试返回其代理对象

        ②:doCreateBean,真正的创建bean的实例,即上面4.5的流程

    AnnotationAwareAspectJAutoProxyCreator做了什么事情?

    一下逻辑都在create()方法中

    1、每一个bean创建之前,都会调用postProcessBeforeInstantiation(); 代码在AbstractAutoProxyCreator#postProcessBeforeInstantiation

      其处理逻辑是:

      1):判断当前bean是否在advisedBean(保存了所有增强过的bean的缓存)中,private final Map<Object, Boolean> advisedBeans = new ConcurrentHashMap<>(256);

      2):isInfrastructureClass(beanClass):判断当前bean是否是 基础类型的Advice、Pointcut、Advisor、AopInfrastructureBean或者是否是切面(是否有@Aspect注解)

      3):或者shouldSkip(beanClass, beanName):是否需要跳过

          ①:获取候选的增强器(切面里面的增强方法)List<Advisor> candidateAdvisors = findCandidateAdvisors();

          ②:遍历然后判断每一个增强器是否是AspectJPointcutAdvisor类型的,如果是,返回true,否则返回flase

          ③:而我们的增强器类型是:InstantiationModelAwarePointcutAdvisor,因此,shouldSkip方法永远返回false

    2、执行doCreateBean方法,创建bean,并初始化

    3、postProcessAfterInstantiationpostProcessBeforeInitialization一个返回true,一个返回bean对象本身,什么都没做

    4、postProcessAfterInitialization方法:创建完对象并初始化后,调用它。代码在AbstractAutoProxyCreator#postProcessAfterInitialization  其逻辑是:

      判断当前bean是否已经代理过,若没有则执行:return wrapIfNecessary(bean, beanName, cacheKey); 这个方法的作用是,封装bean如果必要的话,也就是在这里创建目标类的代理对象

      1):Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);找到所有能应用到当前bean的增强方法

        (1):获取配置的所有的切面增强方法

        (2):找到所有的增强方法中能应用到当前bean方法中的

        (3):获取到能在当前bean使用的增强方法的集合,并按照一定规则排序

        (4):如果能在当前bean使用的增强方法的集合不为空,则转为数组返回,否则返回null

      2):如果返回的数组不为空,则需要代理

        (1):将bean的name作为key,值为true,放在advisedBeans(所有增强过的bean的ConcurrentHashMap)中

        (2):创建代理对象,Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));

          ①:如果能在当前bean使用的增强方法

          ②:遍历将其添加到proxyFactory中

          ③: DefaultAopProxyFactory中创建代理对象,如果目标类实现了接口,则使用JDK动态代理;否则使用CGlib动态代理

             JdkDynamicAopProxy(AdvisedSupport config)

             ObjenesisCglibAopProxy(AdvisedSupport config)

        (3):将bean作为key,代理对象的class对象作为value,保存到private final Map<Object, Class<?>> proxyTypes = new ConcurrentHashMap<Object, Class<?>>(16);

        (4):返回代理对象(代理对象中包含了增强器和目标对象等)

        (5):以后在容器中获取到的就是这个组件的代理对象,执行目标方法的时候,代理对象就会执行增强方法的流程

      3)否则不需要代理,将bean的name作为key,值为false,放在advisedBeans中,表示不需要增强

     总结:AnnotationAwareAspectJAutoProxyCreator在初始化后置方法postProcessAfterInitialization中,判断是否有增强方法能应用到当前bean中,若有,则为当前bean创建代理对象,并保存到Spring容器中,以后从Spring容器中获取到的就是代理对象。

       

    从容器中获取的对象是代理对象,即容器中保存了组件的代理对象(cglib增强后的对象),这个对象里面保存了详细的信息(比如要应用的切面中的增强方法,也叫增强器,目标对象等)

    执行目标对象Target中的切入点方法,即执行被增强的方法的流程:

    F7进入切点方法:

    1、CglibAopProxy.intercept();  拦截目标方法的执行

    2、获取目标对象

      Object target = null; // 目标对象
      TargetSource targetSource = this.advised.getTargetSource();

      target = targetSource.getTarget();

    3、根据ProxyFactory对象获取将要执行的目标方法拦截器链

        List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

        DefaultAdvisorChainFactory#getInterceptorsAndDynamicInterceptionAdvice  // 实际逻辑代码

        1):List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);  

            保存所有的拦截器,包括一个默认的 ExposeInvocationInterceptor.ADVISOR 和 其他所有切点方法的增强器

        2):遍历所有的增强器,将其转为MethodInterceptor  【MethodInterceptor[] interceptors = registry.getInterceptors(advisor);】

                            如果增强器是MethodInterceptor,直接放入List<MethodInterceptor>集合中

             如果不是,使用AdvisorAdapter将增强器转为MethodInterceptor,然后再放入List<MethodInterceptor>集合中

             最后将集合转为数组返回

    4、如果没有拦截器链,则直接执行目标方法(拦截器链,每一个通知方法又被包装为方法拦截器,利用MethodInterceptor机制)

    5、如果有拦截器链,把需要执行的目标对象,目标方法,拦截器等信息作为参数创建一个CglibMethodInvocation对象并调用其proceed()方法

      retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed(); 

      CglibMethodInvocation对象:

      

      拦截器列表:

      

    6、拦截器的触发过程

      1):如果没有拦截器执行目标方法,或者拦截器的索引和拦截器数组-1大小一样(即执行到了最后一个拦截器),则执行目标方法

      2):链式获取每一个拦截器,拦截器执行invoke方法,每一个拦截器等待下一个拦截器执行完成返回后再去执行(类似于递归调用),

        如上面拦截器的调用顺序是 Expose-->AfterReturning-->Around-->Before,然后前面的等待后面的返回再执行,最后实际执行顺序是Before-->Around-->AfterReturning-->Expose

        拦截器链的机制,保证通知方法与目标方法的执行顺序。

      

    AOP总结

      1、@EnableAspectJAutoProxy  开启AOP功能

      2、@EnableAspectJAutoProxy  会给容器中注册一个组件 AnnotationAwareApectJAutoProxyCreator

      3、AnnotationAwareApectJAutoProxyCreator是一个后置处理器

      4、容器的创建流程

        1):registerBeanPostProcessors(beanFactory);  注册后置处理器,创建AnnotationAwareApectJAutoProxyCreator对象

        2):finishBeanFactoryInitialization(beanFactory);  初始化剩下的单实例bean

          (1):创建业务逻辑组件和切面组件

          (2):AnnotationAwareApectJAutoProxyCreator  拦截组件的创建过程

          (3): 组件创建完成之后,作为后置处理器的AnnotationAwareApectJAutoProxyCreatorpostProcessAfterInitialization方法中判断组件是否需要增强,如果需要则 将需要应用到目标对象的切面中的通知方法,包装成增强器Advisor,然后给业务逻辑组件创建一个代理对象。

      5、执行目标方法

        1):代理对象来执行目标方法

        2):CglibAopProxy.intercept();  拦截目标方法的执行

          (1):得到目标方法执行的拦截器链

          (2):利用拦截器的链式机制,依次进入每一个拦截器进行执行

          (3):实际执行顺序:

              正常执行:前置通知-->目标方法-->后置通知-->返回通知

              出现异常:前置通知-->目标方法-->后置通知-->异常通知

    二、事务

      声明式事务

      jdbc和tx依赖:

            <!--jdbc & tx-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-jdbc</artifactId>
            </dependency>

      数据源和mysql连接依赖:

         <!--dbcp datasource-->
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-dbcp2</artifactId>
                <version>2.7.0</version>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.47</version>
            </dependency>

      配置文件信息:

    /**
     * @EnableTransactionManagement 开启基于注解的事务管理功能
     * 1、配置数据源
     * 2、配置事务管理器来管理事务
     * 3、给方法上标注 @Transactional 表示当前方法是一个事务方法,@Transaction默认回滚Error和RuntimeException,但是不包括和RuntimeException
     * 一样同属于Exception子类的如IOException、SQLException和自定义异常等,对于这些异常如果也要回滚要在rollbackFor中指定
     */
    @EnableTransactionManagement
    @Configuration
    @ComponentScan(value = {"com.yang.service"})
    public class TransactionConfig {
    
        @Bean
        public DataSource myDataSource() {
            BasicDataSource dataSource = new BasicDataSource();
            dataSource.setUsername("yang");
            dataSource.setPassword("yang");
            dataSource.setDriverClassName("com.mysql.jdbc.Driver");
            dataSource.setUrl("jdbc:mysql://localhost:3306/test");
            return dataSource;
        }
    
        /**
         * 如果bean之间有依赖,直接放进参数中即可,参数值会从Spring容器中取,然后赋值
         * 参数从Spring容器中取
         *
         * @param myDataSource
         * @return
         */
        @Bean
        public JdbcTemplate jdbcTemplate(DataSource myDataSource) {
            JdbcTemplate jdbcTemplate = new JdbcTemplate(myDataSource);
            // 也可以直接调用,Spring对@Configuration类会特殊处理;给容器中加组件的方法,多次调用都只是从容器中找组件
            //        JdbcTemplate jdbcTemplate = new JdbcTemplate(myDataSource());
            return jdbcTemplate;
        }
    
        /**
         * 注册事务管理器在容器中
         *
         * @return
         * @throws Exception
         */
        @Bean
        public PlatformTransactionManager transactionManager() {
            return new DataSourceTransactionManager(myDataSource());
        }
    }

    @EnableTransactionManagement 做了什么?

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Import(TransactionManagementConfigurationSelector.class)
    public @interface EnableTransactionManagement {
    
        boolean proxyTargetClass() default false;
    
        AdviceMode mode() default AdviceMode.PROXY;
    
        int order() default Ordered.LOWEST_PRECEDENCE;
    }

    1、导入了TransactionManagementConfigurationSelector,TransactionManagementConfigurationSelector往容器中导入了两个组件

      AutoProxyRegistrar 、ProxyTransactionManagementConfiguration

    /**
         * Returns {@link ProxyTransactionManagementConfiguration} or
         * {@code AspectJ(Jta)TransactionManagementConfiguration} for {@code PROXY}
         * and {@code ASPECTJ} values of {@link EnableTransactionManagement#mode()},
         * respectively.
         */
        @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;
            }
        }
    
        private String determineTransactionAspectClass() {
            return (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader()) ?
                    TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME :
                    TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME);
        }
    
    //     public static final String JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME =
                "org.springframework.transaction.aspectj.AspectJJtaTransactionManagementConfiguration";
    
    //     public static final String TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME =
                "org.springframework.transaction.aspectj.AspectJTransactionManagementConfiguration";

    (1)、AutoProxyRegistrar

      给容器中注册了一个beanNameorg.springframework.aop.config.internalAutoProxyCreator,类型为InfrastructureAdvisorAutoProxyCreator的组件(bean),其是一个后置处理器,和AOP中的AnnotationAwareAspectJAutoProxyCreator类似,它们beanName相同。都是在对象创建完成之后利用后置处理器的初始化后置方法,包装对象,然后返回一个包含增强器的代理对象,代理对象执行方法利用拦截器链进行调用。

     (2)、ProxyTransactionManagementConfiguration是一个配置文件类

    /**
     * {@code @Configuration} class that registers the Spring infrastructure beans
     * necessary to enable proxy-based annotation-driven transaction management.
     *
     * @author Chris Beams
     * @since 3.1
     * @see EnableTransactionManagement
     * @see TransactionManagementConfigurationSelector
     */
    @Configuration
    public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
    
        @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
        @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
        public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() { // 事务增强器
            BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
            advisor.setTransactionAttributeSource(transactionAttributeSource());
            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();
        }
    
        @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;
        }
    
    }

      1、往容器中注册事务增强器transactionAdvisor,其中事务增强器中又依赖了:

        1):事务增强器要用事务注解的参数信息,TransactionAttributeSource,AnnotationTransactionAttributeSource来解析事务注解

        2):事务拦截器:TransactionInterceptor,保存了事务属性信息,事务管理器。其实现了MethodInterceptor接口。在目标方法执行的时候:执行拦截器链,然后执行事务拦截器:

          (1):先获取事务相关的属性

          (2):再获取PlatformTransactionManager事务管理器,如果在@Transactional注解中没有指定transactionManager,则最终会从容器中按照类型获取一个PlatformTransactionManager

          (3):执行目标方法

             如果异常,获取到事务管理器,利用事务管理回滚操作

             【transactionInfo.getTransactionManager().rollback(txInfo.getTransactionStatus())】

               如果正常,利用事务管理器,提交事务【transactionInfo.getTransactionManager().commit(txInfo.getTransactionStatus());】

        TransactionInterceptor#invoke

        @Override
        @Nullable
        public Object invoke(MethodInvocation invocation) throws Throwable {
            // Work out the target class: may be {@code null}.
            // The TransactionAttributeSource should be passed the target class
            // as well as the method, which may be from an interface.
            Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
    
            // Adapt to TransactionAspectSupport's invokeWithinTransaction...
            return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
        }

        

        @Transactional注解处理器的核心代码,TransactionAspectSupport#invokeWithinTransaction:278,从TransactionInterceptor#invoke进入:

     /**
         * General delegate for around-advice-based subclasses, delegating to several other template
         * methods on this class. Able to handle {@link CallbackPreferringPlatformTransactionManager}
         * as well as regular {@link PlatformTransactionManager} implementations.
         * @param method the Method being invoked
         * @param targetClass the target class that we're invoking the method on
         * @param invocation the callback to use for proceeding with the target invocation
         * @return the return value of the method, if any
         * @throws Throwable propagated from the target invocation
         */
        @Nullable
        protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
                final InvocationCallback invocation) throws Throwable {
    
            // If the transaction attribute is null, the method is non-transactional.
            TransactionAttributeSource tas = getTransactionAttributeSource();
            final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
            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); // Reset the TransactionInfo ThreadLocal.
                }
                commitTransactionAfterReturning(txInfo); // 提交事务
                return retVal;
            }
    
            else {
                ...
            }
        }

      

      回滚事务:

      /**
         * Handle a throwable, completing the transaction.
         * We may commit or roll back, depending on the configuration.
         * @param txInfo information about the current transaction
         * @param ex throwable encountered
         */
        protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) {
            if (txInfo != null && txInfo.getTransactionStatus() != null) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() +
                            "] after exception: " + ex);
                }
                if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {
                    try {
                        txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
                    }
                    catch (TransactionSystemException ex2) {
                        logger.error("Application exception overridden by rollback exception", ex);
                        ex2.initApplicationException(ex);
                        throw ex2;
                    }
                    catch (RuntimeException | Error ex2) {
                        logger.error("Application exception overridden by rollback exception", ex);
                        throw ex2;
                    }
                }
                else {
                    // We don't roll back on this exception.
                    // Will still roll back if TransactionStatus.isRollbackOnly() is true.
                    // 默认回滚(ex instanceof RuntimeException || ex instanceof Error) 异常,其他异常不会回滚,仍提交事务
                    try {
                        txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
                    }
                    catch (TransactionSystemException ex2) {
                        logger.error("Application exception overridden by commit exception", ex);
                        ex2.initApplicationException(ex);
                        throw ex2;
                    }
                    catch (RuntimeException | Error ex2) {
                        logger.error("Application exception overridden by commit exception", ex);
                        throw ex2;
                    }
                }
            }
        }

        最终回滚代码为:DataSourceTransactionManager#doRollback

    DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
    Connection con = txObject.getConnectionHolder().getConnection();
    con.rollback();

      提交事务:

      /**
         * Execute after successful completion of call, but not after an exception was handled.
         * Do nothing if we didn't create a transaction.
         * @param txInfo information about the current transaction
         */
        protected void commitTransactionAfterReturning(@Nullable TransactionInfo txInfo) {
            if (txInfo != null && txInfo.getTransactionStatus() != null) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "]");
                }
                txInfo.getTransactionManager().commit(txInfo.getTransactionStatus()); // 提交事务
            }
        }

       最终提交代码为:

    DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
    Connection con = txObject.getConnectionHolder().getConnection();
    con.commit();

    END.

  • 相关阅读:
    01
    Django2
    Django01
    DS18B20时序解析,以及读出85原因诠释
    python字符串打印-不同方法vars
    2.对象属性
    1.excel-vba-对象
    搭建 eclipse,maven,tomcat 环境
    jsp include flush true
    oracle数据库基础
  • 原文地址:https://www.cnblogs.com/yangyongjie/p/14638924.html
Copyright © 2020-2023  润新知