小区网站建设,有什么网站可以接手工加工做,自己做的美食在哪个网站上卖,wordpress网页loder插件在使用事务的时候需要添加EnableTransactionManagement注解来开启事务#xff0c;Spring事务底层是通过AOP来实现的#xff0c;所以启用事务后#xff0c;同样会向容器中注入一个代理对象创建器#xff0c;AOP使用的是AnnotationAwareAspectJAutoProxyCreator#xff0c;事…在使用事务的时候需要添加EnableTransactionManagement注解来开启事务Spring事务底层是通过AOP来实现的所以启用事务后同样会向容器中注入一个代理对象创建器AOP使用的是AnnotationAwareAspectJAutoProxyCreator事务使用的是InfrastructureAdvisorAutoProxyCreator。 Advice通知定义在切点上需要执行什么样的操作 PointCut切点定义在哪些方法上使用通知 AdvisorAdvice和Pointcut加起来组成了Advisor可以看做是对切面的封装
在使用AOP时一般会创建一个切面里面包含了切点和通知事务既然基于AOP实现所以也会有对应的通知和切点。
事务Advisor
开启事务时还会向Spring容器中注册一个BeanFactoryTransactionAttributeSourceAdvisor从名字上可以看出它是一个Advisor它重点有以下几个类型的成员变量 Advice通知传入的实际类型为TransactionInterceptor它是事务拦截器实现了Advice接口这个拦截器就相当于AOP中的通知在执行目标方法前会进行拦截进行事务处理 TransactionAttributeSourcePointcut切点它实现了Pointcut和MethodMatcher接口是一个切点目标方法是否需要被事务代理就是通过它判断的 TransactionAttributeSource传入的实际类型为AnnotationTransactionAttributeSource用于解析事务属性相关配置信息
Advisor由Advice和Pointcut组成现在Advice和Pointcut都已经知道了接下来就去看看是如何判断当前Bean是否需要进行事务代理的。
事务底层是通过AOP实现的所以它的处理逻辑与AOP类似启动时会注册一个后置处理器在postProcessAfterInitialization方法中判断是否需要进行代理逻辑与AOP一致会获取所有的Advisor判断是否有匹配当前Bean的AdvisorSpring会自动为事务注册AdvisorBeanFactoryTransactionAttributeSourceAdvisor匹配的处理逻辑在TransactionAttributeSourcePointcut切点中实现是否匹配的判断条件如下
判断当前Bean的Class是否匹配具体是通过ClassFilterTransactionAttributeSourceClassFilter的matches方法实现的注意这里并不是判断当前Bean所在类上面是否有事务注解这个条件主要是为了排除一些Spring认为不需要进行事务代理的类比如某个Bean的类路径以java.开头而我们编写的类一般不会是以java开头的所以这个Bean就会跳过代理对于我们编写的Bean一般不会被这个条件过滤掉会进行下一个条件判断 TransactionAttributeSourceClassFilter是TransactionAttributeSourcePointcut的内部类里面有matches方法的实现。 判断当前Bean中的方法是否与事务切点匹配具体是通过MethodMatcherTransactionAttributeSourcePointcut的matches方法实现这里会获取当前Bean的所有方法一个个与事务切点进行匹配匹配规则如下
1从方法中获取事务注解相关的设置 2从方法所在类中获取事务注解相关设置 2如果方法所在的类实现了接口还会从接口上面解析是否有事务注解相关的配置 如果我们使用了Transactional注解对方法或者类进行了配置就会在这一步解析到相关内容。 如果通过以上方式中的任意一种获取到了事务相关设置就会认为当前Bean需要进行事务代理为其创建代理对象实现与AOP一致会为其创建一个AOP代理对象只不过在执行目标方法时Spring会通过已经设定好的事务切面进行拦截也就是BeanFactoryTransactionAttributeSourceAdvisor中的TransactionInterceptor对进行方法拦截而在AOP中一般是我们自己编写切面。
事务拦截
上面我们知道对于需要进行事务拦截的Bean会为其创建代理对象在执行目标方法的时候会进入事务拦截器的处理逻辑主要步骤如下
获取事务管理器创建事务这里主要是向后执行拦截器链待所有的拦截器都执行完毕之后执行目标方法捕捉异常如果出现异常进行回滚提交事务 事务的创建
事务的创建分为两部分
一、 获取事务
1首先获取事务对象它是一个抽象方法数据源的不同具体的实现类也不同 以DataSourceTransactionManager为例它主要是创建了一个数据源事务对象DataSourceTransactionObject然后根据数据源信息源获取当前线程绑定的ConnectionHolder对象如果有的话会获取到否则获取为空ConnectionHolder中存有数据库连接及事务的活跃状态之后会将这个ConnectionHolder设置到数据源事务对象中将数据源事务对象返回 2根据上一步获取到的事务对象判断当前线程是否存在事务如果存在事务需要根据事务传播行为进行不同的处理 是否存在事务的判断方式是通过当前线程是否持有数据库连接数据源事务对象中的ConnectionHolder不为空并且事务处于活跃状态。 如果事务传播行为设是PROPAGATION_NEVER表示不能存在事务当前存在事务会抛出异常;如果事务的传播行为是PROPAGATION_NOT_SUPPORTED表示以不使用事务的方式执行如果当前存在事务则挂起当前的事务执行完当前逻辑后不使用事务再恢复挂起的事务如果事务的传播行为是PROPAGATION_REQUIRES_NEW表示每次执行都新建事务如果当前存在事务需要挂起当前事务创建一个自己的事务执行之后再恢复挂起的事务如果事务的传播行为是PROPAGATION_NESTED表示嵌套事务判断是否使用保存点如果是则使用嵌套事务否则开启一个新事务其他情况使用当前的事务
3如果当前线程不存在事务 如果事务的传播行为是PROPAGATION_MANDATORY它要求必须存在事务当前不存在事务会抛出异常 如果传播行为是PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW或者PROPAGATION_NESTED新建事务 其他情况创建一个空事务 新建事务说明之前不存在事务ConnectionHolder为空此时会从数据库连接池中获取一个连接设置到ConnectionHolder中并将当前线程对应这个ConnectionHolder与数据源绑定底层ThreadLocal实现上面第1步中可以看到会通过数据源获取当前线程的ConnectionHolder数据就是在这里添加的之后就可以通过这个判断当前线程是否已经存在事务。 二、 预处理事务
主要是进行事务相关信息的封装以及事务和线程的绑定。
事务回滚
当执行过程中出现异常时会进行事务回滚回滚的处理逻辑如下
判断事务是否设置了保存点如果设置了将事务回滚到保存点如果是一个独立的新事务直接回滚即可如果既没有设置保存点也不是一个新事务说明可能处于嵌套事务中此时只设置回滚状态rollbackOnly为true当它的外围事务进行提交时如果发现回滚状态为true外围事务则不提交;
资源清理
在事务提交/回滚之后需要根据情况清理相关的资源以及恢复被挂起的事务主要有以下操作
清除当前线程绑定的事务相关信息清除当前线程对应的ConnectionHolder与数据源的绑定关系及ConnectionHolder自身的清理如果挂起的事务不为空恢复挂起的事务