spring中事务、缓存、@Async、aop等实现原理其实基本一致,都是通过cglib或jdk生成动态代理,然后通过拦截器执行对应的逻辑。如果同一个类中既有@Transactional
又有@Cacheable
生成的是同一个代理类,但是会有多个处理器Advice
,会适配成org.aopalliance.intercept.MethodInterceptor
,多个拦截器组成一个拦截器链,调用方法式时依次执行各个拦截器。一个典型的责任链模式
spring中事务的传播机制
例如:在方法a上标记了事务传播机制
public class UserInfoService {
@Transactional(propagation = Propagation.REQUIRED)
public void a(){
//...
}
}
@org.springframework.transaction.annotation.Transactional
中的属性:
-
TransactionDefinition.PROPAGATION_REQUIRED (default)
调用a方法的方法的已经在事务中,则不需要开启事务,否则a必须开启事务 -
TransactionDefinition.PROPAGATION_SUPPORTS
如果调用a的方法已经在事务中,则a也在事务中执行
如果调用a的方法没有在事务中,则a也不需要在事务中执行 -
TransactionDefinition.PROPAGATION_MANDATORY
调用a的方法必须要在事务中执行,如果没有则报错 -
TransactionDefinition.PROPAGATION_REQUIRES_NEW
不管调用a的方法有没有在事务中, a必须要再起一个事务,并且会要求挂起上一个方法的事务,
一般数据库不支持事务的嵌套,
所以这个在org.springframework.transaction.jta.JtaTransactionManager
才会有效,
并且org.springframework.transaction.jta.JtaTransactionManager是要求
javax.transaction.TransactionManager
是可用的, 特定于JavaEE服务器. -
TransactionDefinition.PROPAGATION_NOT_SUPPORTED
不支持事务,如果调用该方法的方法在事务中,会要求其挂起事务,所以也是针对
org.springframework.transaction.jta.JtaTransactionManager
有效. -
TransactionDefinition.PROPAGATION_NEVER
不在事务中执行,如果存在事务,则会抛出异常 -
TransactionDefinition.PROPAGATION_NESTED
如果存在当前事务,则在嵌套事务中执行,否则其行为将与所需的行为类似。EJB中没有类似的特性。注意:嵌套事务的实际创建仅在特定事务管理器上有效。在使用JDBC 3.0驱动程序时,
这只适用于JDBCorg.springframework.JDBC.datasource.DataSourceTransactionManager
。
一些JTA提供程序可能也支持嵌套事务
org.springframework.transaction.interceptor.TransactionAttributeSource
给TransactionInterceptor
用来检索元数据的策略接口,它的实现类(默认为AnnotationTransactionAttributeSource
)知道如何获取事务属性:无论从代码(java注解)层面的配置、元数据属性或者任意地方.
SpringBoot中默认会开启事务,并且使用的是cglib代理,源码如下:
ProxyProcessorSupport
实现了Ordered
接口,排序值最后会被子类设置成Ordered.HIGHEST_PRECEDENCE
(Integer.MIN_VALUE
),见源码:org.springframework.aop.config.AopConfigUtils#registerOrEscalateApcAsRequired
判断是否需要创建代理
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary
,实现了,
如果需要创建代理,则创建org.springframework.aop.framework.ProxyFactory
对象,设置相关属性,例如: proxyTargetClass=true
、Advisor
对象集合。如果proxyTargetClass=false则尝试获取targetClass实现的接口,如果没有接口则强制设置proxyTargetClass=true
org.aopalliance.aop.Advice
可以认为是一个拦截器,最后会被适配成org.aopalliance.intercept.MethodInterceptor
org.springframework.aop.framework.adapter.GlobalAdvisorAdapterRegistry
用于注册自己的Advisor
适配器
org.springframework.scheduling.annotation.AsyncAnnotationBeanPostProcessor
用于添加处理@Async
注解的Advisor,排序优先级设置为Ordered.LOWEST_PRECEDENCE
(Integer.MAX_VALUE
),最低。
如下三个Advice
子类是不是很熟悉,其实就是对应Spring aop中的几个注解。
org.springframework.aop.MethodBeforeAdvice
org.springframework.aop.AfterReturningAdvice
org.springframework.aop.ThrowsAdvice
@Transactional
中的属性会被封装到RuleBasedTransactionAttribute
中
通过try-catch-finally来捕获异常