-
什么是aop,什么是spring aop?
-
aop是面向切面编程,是oop(面向对象编程)的补充;在传统的OOP编程中,逻辑是自上而下的,所以在这个过程会产生很多横行性的问题并散落在各个地方(比如权限校验,日志打印);aop就是为分散对象提供了一种公共行为的抽象,降低了代码的重复率以及降低了模块间的耦合;
- spring aop是对aop编程的具体实现,是在程序运行阶段完成对方法的增强。主要原理通过动态代理的方式以及spring内置的一些BeanPostProcessor完成对方法的横切增强;spring aop也支持@AspectJ风格的编码支持,及借助了AspectJ包下的一些注解(@AspectJ也是aop的实现,主要在编译阶段完成aop增强。)
-
-
spring中的动态代理
- spring aop支持两种动态代理,JDK动态代理,cglib动态代理字节码增强技术,spring对存在接口的bean采用jdk动态代理。在bean的生命周期中,通过BeanPostProcessor完成生成代理对象;
- JDK动态代理只能对实现了的接口的类生成代理(内部利用反射机制实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理),是一种委托机制,创建对象效率高,执行效率比较低
- cglib是针对类实现代理,主要是对指定类生成一个子类,覆盖其中的方法(利用ASM字节码增强技术,操作字节码,所以不能代理final修饰的类),是一种继承机制,创建效率低,执行效率更高
- 静态AOP: 在编译阶段对源程序代码进行修改,生成了静态的AOP代理类,生成的.class文件是已经修改过了,比如Aspect静态AOP框架;
-
JDK动态代理
- JDK动态代理会对接口中所有的方法进行代理增强
public class JDKProxy implements InvocationHandler { private Object targetObject; public Object newProxy(Object target){ this.targetObject = target; return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //进行动态代理的增强处理 print(); return method.invoke(targetObject, args); } public void print(){ System.out.println("JDK实现动态代理"); } }-
cglib动态代理
- cglib动态代理可以通过设置Enhancer的CallbackFilters完成对不同方法进行拦截增强
public class CglibProxy implements MethodInterceptor { private Object targetObject; public Object createProxyObject(Object targetObject){ this.targetObject = targetObject; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(targetObject.getClass()); enhancer.setCallback(this); return enhancer.create(); } @Override public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { //代理增强方法 check(); return method.invoke(targetObject, args); } private void check() { System.out.println("检查权限:check()!"); } } -
spring aop重要的几个概念
- AOP中相关的概念: Aspect(切面),JointPoint(连接点),Advice(通知),Pointcut(切入点),引入(Introduction),织入(Weaving);
- Aspect(切面):切面是通知和切点的结合,被@Aspect修饰的类,主要包括:1.通知的内容即需要增强的业务逻辑实现;2:通知的时机-Before,AfterReturning,AfterThrowing,After,Around;3通知的目标,即需要通知执行的切点上的所有连接点上。
- JointPoint(连接点):连接点表示应用执行过程中能够插入切面的一个点,是一个结果;在Spring AOP中,连接点总是方法的调用。
- Pointcut(切入点):一组连接点的集合,可以对连接点进行分组。所以每一组就是一个切点。
- 连接点的匹配规则,execution,within,this,target,args,@target,@args,@annotation,并且可以通过表达式组合,即利用上述的表达式通过逻辑运算,与,或,非,组合在一起。
- execution 可以精确到某个类中的某个方法
- within:只能精确到某个类
- args: args表达式的作用是匹配指定参数类型和指定参数数量的方法,与包名和类名无关
- this: 代理对象是否继承或实现了对应类
- target: 目标对象是否继承或实现了对应接口,与this不一样的是二者关注的对象不同,一个是代理对象,一个是目标对象
- Advice(通知): 通知描述了切面何时以及如何执行增强处理,在spring中 xml与注解版本中After与AfterReturning的执行时机有区别,注解版本中AfterReturning优先于After,但在xml中与定义通知的顺序有关;并且可以指定通知的优先顺序order与
- @Before:在目标方法之前执行
- @After:在目标方法之后执行
- @Around:在目标方法前后执行
- @AfterReturning:在目标方法返回执行
- @AfterThrowing:在目标方法异常执行
- 引入(Introduction): spring aop可以不再修改代码的情况下,让某个类实现某个接口,并指定接口的默认实现方法,允许我们向现有类添加新的方法或者属性;
- 织入(Weaving): 将增强处理添加到目标对象,并创建一个被增强的对象,这过程就是织入;
- AOP中相关的概念: Aspect(切面),JointPoint(连接点),Advice(通知),Pointcut(切入点),引入(Introduction),织入(Weaving);
-
spring aop流程解析
- 在sping bean的生命周期中,执行initializeBean方法中会执行所有BeanPostProcessor的生命周期初始化的后置回调方法BeanPostProcessor.postProcessAfterInitialization方法;其中有一个BeanPostProcessor叫做AnnotationAwareAspectJAutoProxyCreator,完成了spring中的aop,注意所有的bean都会执行该方法;
- 找到容器中所有的切面(遍历容器中所有的BeanDefition或单例池,是否存在@Aspect注解),并将切面中的通知方法,转换成Advisor列表;执行连接点匹配规则,spring底层复用了AspectJ的规则来过滤出作用在当前Bean的Advisor列表,然后进行排序(Order,PriorityOrder)排序;
- 通过ProxyFactory代理工厂,设置对应的TargetResources对象,通过 DefaultAopProxyFactory.createAopProxy创建动态代理工厂(JdkDynamicAopProxy或ObjenesisCglibAopProxy),最后通过动态代理工厂对象,完成动态代理的对象的生成;
- 代理对象执行对应的方法时,会调用JdkDynamicAopProxy中.invoke方法或者ObjenesisCglibAopProxy.DynamicAdvisedInterceptor内部类的intercept方法,判断过滤当前方法上的通知advice列表,形成责任链,来完成spring aop的增强逻辑
- spring aop的通知adive逻辑实际是通过责任链模式完成各种通知的逻辑增强,当所有的责任链都执行完后,会执行目标对象的方法;
- @Around注解对应AspectJAroundAdvice,他会执行对应的方法然后通过调用 ProceedingJoinPoint.proceed方法完成责任链的方法调用的传递;
- @Before注解对应MethodBeforeAdviceInterceptor,他会优先调用BeforeAdvice前置通知后,在执行责任链的下一个Advice
- @After注解对应AspectJAfterAdvice,会在finally代码块完成通知方法的调用
- @AfterReturning注解对应AfterReturningAdviceInterceptor,他会先执行调用链的方法,然后执行通知方法
- @AfterThrowing注解对应AspectJAfterThrowingAdvice会在catch异常块中执行具体的通知
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //spring aop 代理对象真正执行的方法 Object oldProxy = null; boolean setProxyContext = false; TargetSource targetSource = this.advised.targetSource; Object target = null; try { if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { // The target does not implement the equals(Object) method itself. return equals(args[0]); } else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { // The target does not implement the hashCode() method itself. return hashCode(); } else if (method.getDeclaringClass() == DecoratingProxy.class) { // There is only getDecoratedClass() declared -> dispatch to proxy config. return AopProxyUtils.ultimateTargetClass(this.advised); } else if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) { // Service invocations on ProxyConfig with the proxy config... return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); } Object retVal; if (this.advised.exposeProxy) { // Make invocation available if necessary. oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } // Get as late as possible to minimize the time we "own" the target, // in case it comes from a pool. //获取目标对象 target = targetSource.getTarget(); Class<?> targetClass = (target != null ? target.getClass() : null); // Get the interception chain for this method. //目标对象target(targetSource返回)的方法配置增强的advisor列表,并构建拦截器链chain List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); // Check whether we have any advice. If we don't, we can fall back on direct // reflective invocation of the target, and avoid creating a MethodInvocation. if (chain.isEmpty()) { // We can skip creating a MethodInvocation: just invoke the target directly // Note that the final invoker must be an InvokerInterceptor so we know it does // nothing but a reflective operation on the target, and no hot swapping or fancy proxying. Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); } else { // We need to create a method invocation... MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); // Proceed to the joinpoint through the interceptor chain. //执行通知链上所有通知 retVal = invocation.proceed(); } // Massage return value if necessary. Class<?> returnType = method.getReturnType(); if (retVal != null && retVal == target && returnType != Object.class && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { // Special case: it returned "this" and the return type of the method // is type-compatible. Note that we can't help if the target sets // a reference to itself in another returned object. retVal = proxy; } else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) { throw new AopInvocationException( "Null return value from advice does not match primitive return type for: " + method); } return retVal; } finally { if (target != null && !targetSource.isStatic()) { // Must have come from TargetSource. targetSource.releaseTarget(target); } if (setProxyContext) { // Restore old proxy. AopContext.setCurrentProxy(oldProxy); } } }
-
spring中的默认的通知ExposeInvocationInterceptor
- ExposeInvocationInterceptor拦截器的代码,执行invoke()方法的入参mi,其实就是ReflectiveMethodInvocation实例,而ReflectiveMethodInvocation中是包含了拦截器链,通过当前的ReflectiveMethodInvocation实例变量放入了ThreadLocal中,这样在同一个线程中,通过ThreadLocal来共享拦截器链;
-
自定义编码完成springaop
public static void test(){ ProxyFactory pf = new ProxyFactory(); pf.setInterfaces(LogApi.class); pf.setTarget(new LogApiImpl()); pf.addAdvice(new BeforeAdvice()); LogApi proxy = (LogApi)pf.getProxy(); proxy.printLog(); } //手动实现了BeforeAdvice @Slf4j public class BeforeAdvice implements MethodInterceptor { @Override public Object invoke(MethodInvocation methodInvocation) throws Throwable { log.error("--------BeforeAdvice-----before"); return methodInvocation.proceed(); } } -
spring aop源码解析
- 执行postProcessAfterInitialization方法,调用wrapIfNecessary方法对增强类,创建代理对象;
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { return bean; } if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } // Create proxy if we have advice. //遍历容器中所有切面,过滤筛选作用在当前bean的advice列表 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); if (specificInterceptors != DO_NOT_PROXY) { this.advisedBeans.put(cacheKey, Boolean.TRUE); //spring aop -创建代理工厂,spring aop代理对象是根据TargetSource有关,和目标对象无关 Object proxy = createProxy( bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; }- 执行AbstractAdvisorAutoProxyCreator.findEligibleAdvisors方法查找容器中所有切面,并过滤筛选出作用在当前bean的adviceor列表(并进行排序)
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { //获取容器中所有切面的Advisor,包括事务通知BeanFactoryTransactionAttributeSourceAdvisor List<Advisor> candidateAdvisors = findCandidateAdvisors(); //过滤出作用在当前bean 上的Advisor列表(执行连接点的匹配规则,底层采用了aspectj包的匹配功能),注解版本的并完成排序 List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { //对Advisor进行排序,切面可以实现Ordered,PriorityOrder接口 eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; }- 调用BeanFactoryAspectJAdvisorsBuilder.buildAspectJAdvisors方法找到容器中所有的advice通知列表
public List<Advisor> buildAspectJAdvisors() { List<String> aspectNames = this.aspectBeanNames; if (aspectNames == null) { synchronized (this) { aspectNames = this.aspectBeanNames; if (aspectNames == null) { List<Advisor> advisors = new ArrayList<>(); aspectNames = new ArrayList<>(); //获取spring容器中所有的bean与beanDefinition的名称 String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Object.class, true, false); for (String beanName : beanNames) { //判断是否为合格的bean if (!isEligibleBean(beanName)) { continue; } // We must be careful not to instantiate beans eagerly as in this case they // would be cached by the Spring container but would not have been weaved. Class<?> beanType = this.beanFactory.getType(beanName, false); if (beanType == null) { continue; } //判断当前bean是否是切面 被@Aspect注解 if (this.advisorFactory.isAspect(beanType)) { aspectNames.add(beanName); AspectMetadata amd = new AspectMetadata(beanType, beanName); if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) { MetadataAwareAspectInstanceFactory factory = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName); //获取切面中所有的Advise通知的方法(会排除@Pontcut方法),并且转换成Advisor List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory); //判断是否为单例bean if (this.beanFactory.isSingleton(beanName)) { //设置缓存 this.advisorsCache.put(beanName, classAdvisors); } else { //设置解析工厂对象缓存 this.aspectFactoryCache.put(beanName, factory); } advisors.addAll(classAdvisors); } else { // Per target or per this. if (this.beanFactory.isSingleton(beanName)) { throw new IllegalArgumentException("Bean with name '" + beanName + "' is a singleton, but aspect instantiation model is not singleton"); } MetadataAwareAspectInstanceFactory factory = new PrototypeAspectInstanceFactory(this.beanFactory, beanName); this.aspectFactoryCache.put(beanName, factory); advisors.addAll(this.advisorFactory.getAdvisors(factory)); } } } this.aspectBeanNames = aspectNames; return advisors; } } } if (aspectNames.isEmpty()) { return Collections.emptyList(); } List<Advisor> advisors = new ArrayList<>(); for (String aspectName : aspectNames) { List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName); if (cachedAdvisors != null) { advisors.addAll(cachedAdvisors); } else { MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName); advisors.addAll(this.advisorFactory.getAdvisors(factory)); } } return advisors; }- 调用ReflectiveAspectJAdvisorFactory.getAdvisor方法判断是否添加了Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class,并为通知方法构建advisor对象InstantiationModelAwarePointcutAdvisorImpl
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrderInAspect, String aspectName) { validate(aspectInstanceFactory.getAspectMetadata().getAspectClass()); //private static final Class<?>[] ASPECTJ_ANNOTATION_CLASSES = new Class<?>[] { // Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class}; //从增强方法获取切点信息,判断方法是否存在以上注解 AspectJExpressionPointcut expressionPointcut = getPointcut( candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass()); if (expressionPointcut == null) { return null; } //为增强方法构建Advisor对象 return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod, this, aspectInstanceFactory, declarationOrderInAspect, aspectName); }- 调用JdkDynamicAopProxy或CglibAopProxy的getProxy方法创建代理对象
//JdkDynamicAopProxy.getProxy创建代理对象 public Object getProxy(@Nullable ClassLoader classLoader) { if (logger.isTraceEnabled()) { logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource()); } return Proxy.newProxyInstance(determineClassLoader(classLoader), this.proxiedInterfaces, this); } //CglibAopProxy.getProxy,cglib实现动态代理 public Object getProxy(@Nullable ClassLoader classLoader) { if (logger.isTraceEnabled()) { logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource()); } try { Class<?> rootClass = this.advised.getTargetClass(); Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy"); Class<?> proxySuperClass = rootClass; if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) { proxySuperClass = rootClass.getSuperclass(); Class<?>[] additionalInterfaces = rootClass.getInterfaces(); for (Class<?> additionalInterface : additionalInterfaces) { this.advised.addInterface(additionalInterface); } } // Validate the class, writing log messages as necessary. validateClassIfNecessary(proxySuperClass, classLoader); // Configure CGLIB Enhancer... Enhancer enhancer = createEnhancer(); if (classLoader != null) { enhancer.setClassLoader(classLoader); if (classLoader instanceof SmartClassLoader && ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) { enhancer.setUseCache(false); } } enhancer.setSuperclass(proxySuperClass); enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised)); enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE); enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader)); //设置spring aop中方法的的增强执行 Callback[] callbacks = getCallbacks(rootClass); Class<?>[] types = new Class<?>[callbacks.length]; for (int x = 0; x < types.length; x++) { types[x] = callbacks[x].getClass(); } // fixedInterceptorMap only populated at this point, after getCallbacks call above enhancer.setCallbackFilter(new ProxyCallbackFilter( this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset)); enhancer.setCallbackTypes(types); // Generate the proxy class and create a proxy instance. return createProxyClassAndInstance(enhancer, callbacks); } catch (CodeGenerationException | IllegalArgumentException ex) { throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() + ": Common causes of this problem include using a final class or a non-visible class", ex); } catch (Throwable ex) { // TargetSource.getTarget() failed throw new AopConfigException("Unexpected AOP exception", ex); } }- 执行代理对象的方法,会执行对应的方法调用
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //spring aop 代理对象真正执行的方法 Object oldProxy = null; boolean setProxyContext = false; TargetSource targetSource = this.advised.targetSource; Object target = null; try { if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { // The target does not implement the equals(Object) method itself. return equals(args[0]); } else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { // The target does not implement the hashCode() method itself. return hashCode(); } else if (method.getDeclaringClass() == DecoratingProxy.class) { // There is only getDecoratedClass() declared -> dispatch to proxy config. return AopProxyUtils.ultimateTargetClass(this.advised); } else if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) { // Service invocations on ProxyConfig with the proxy config... return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); } Object retVal; if (this.advised.exposeProxy) { // Make invocation available if necessary. oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } // Get as late as possible to minimize the time we "own" the target, // in case it comes from a pool. //获取目标对象,目标对象是通过targetSource获取的,所以spring aop是和TargetSource有关 target = targetSource.getTarget(); Class<?> targetClass = (target != null ? target.getClass() : null); // Get the interception chain for this method. //目标对象target(targetSource返回)的方法配置增强的advisor列表,并构建拦截器链chain List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); // Check whether we have any advice. If we don't, we can fall back on direct // reflective invocation of the target, and avoid creating a MethodInvocation. if (chain.isEmpty()) { // We can skip creating a MethodInvocation: just invoke the target directly // Note that the final invoker must be an InvokerInterceptor so we know it does // nothing but a reflective operation on the target, and no hot swapping or fancy proxying. Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); } else { // We need to create a method invocation... MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); // Proceed to the joinpoint through the interceptor chain. //执行通知链上所有通知 retVal = invocation.proceed(); } // Massage return value if necessary. Class<?> returnType = method.getReturnType(); if (retVal != null && retVal == target && returnType != Object.class && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { // Special case: it returned "this" and the return type of the method // is type-compatible. Note that we can't help if the target sets // a reference to itself in another returned object. retVal = proxy; } else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) { throw new AopInvocationException( "Null return value from advice does not match primitive return type for: " + method); } return retVal; } finally { if (target != null && !targetSource.isStatic()) { // Must have come from TargetSource. targetSource.releaseTarget(target); } if (setProxyContext) { // Restore old proxy. AopContext.setCurrentProxy(oldProxy); } } }- spring aop通知执行的逻辑是通过ReflectiveMethodInvocation.proceed方法执行拦截器链,cglib会执行对应的Interceptor方法,然后通过DynamicAdvisedInterceptor对方法进行aop增强,获取过滤当前方法的advice列表,构建CglibMethodInvocation继承了ReflectiveMethodInvocation方法,来执行拦截器链上的链路执行,具体的流程是一样的;
public Object proceed() throws Throwable { // We start with an index of -1 and increment early. //判断拦截器链是否已经全部执行 if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { //执行后目标对象的方法(通过反射) return invokeJoinpoint(); } //依次获取拦截器链上的通知 Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { // Evaluate dynamic method matcher here: static part will already have // been evaluated and found to match. InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice; Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass()); if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) { return dm.interceptor.invoke(this); } else { // Dynamic matching failed. // Skip this interceptor and invoke the next in the chain. return proceed(); } } else { // It's an interceptor, so we just invoke it: The pointcut will have // been evaluated statically before this object was constructed. //执行链上的通知 return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } } -
spring中事务
-
spring框架提供了事务管理的功能,允许用户定义事务的边界和行为等(定义事务的传播行为,隔离级别等),以确保数据的完整性和一致。spring提供了两种事务管理机制,声明式事务管理和编程式事务管理。spring声明事务管理是基于spring aop实现的;
- 声明式事务管理
- 基于注解@Transactional + @EnableTransactionManagement(开启事务管理)
- 基于XML实现,在Spring的XML配置文件中,你可以使用
<tx:advice>和<aop:config>标签来定义事务通知和切点
- 编程事务管理
- 使用TransactionTemplate管理事务,如果有返回值,采用TransactionCallback;如果没有返回值,采用TransactionCallbackWithoutResult;
- 使用PlatformTransactionManager管理事务
- 声明式事务管理
@Configuration
public class DataSourceConfiguration {
/**
* datasource:
* url:
* username: root
* password: 123456
* driverClassName: com.mysql.cj.jdbc.Driver
* @return
*/
@Bean
public DataSource dataSource(){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setPassword("123456");
dataSource.setUrl("");
dataSource.setUsername("root");
return dataSource;
}
@Bean
public JdbcTemplate jdbcTemplate(){
return new JdbcTemplate(dataSource());
}
@Bean
public PlatformTransactionManager transactionManager(){
DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
dataSourceTransactionManager.setDataSource(dataSource());
return dataSourceTransactionManager;
}
@Bean
public TransactionTemplate transactionTemplate(){
return new TransactionTemplate(transactionManager());
}
}
/**
* spring事务
* <p>
* 1。编程式事务管理
* <p>
* 2。声明式事务管理
*/
@Slf4j
@Component("SpringTransaction")
@EnableTransactionManagement
public class SpringTransaction {
@Autowired
private TransactionTemplate transactionTemplate;
@Autowired
private PlatformTransactionManager transactionManager;
@Autowired
private JdbcTemplate jdbcTemplate;
/**
* 使用TransactionTemplate,实现编程式事务
* 1.如果有返回值,采用TransactionCallback;
* 2.如果没有返回值,采用TransactionCallbackWithoutResult;
*/
public void testTransactionTemplate() {
Integer count = transactionTemplate.execute(new TransactionCallback<Integer>() {
@Override
public Integer doInTransaction(TransactionStatus transactionStatus) {
try {
return testUpdate("testTransactionTemplate");
} catch (Exception e) {
log.error("testTransactionTemplate异常{}", e.getMessage(), e);
transactionStatus.setRollbackOnly();
return -1;
}
}
});
log.info("testTransactionTemplate执行结果:{}", count);
}
/**
* 利用PlatformTransactionManager完成编程式事务
* 1.定义事务配置(事务隔离级别,传播级别,事务名称等),通过PlatformTransactionManager获取事务状态TransactionStatus
* 主要通过对应的TransactionManager获取对应的ConnectionHolder,并将TransactionSynchronizationManager事务同步管理器,
*
*
*/
public void testPlatformTransactionManager() {
DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition();
transactionDefinition.setName("testPlatformTransactionManager");
TransactionStatus transactionStatus = transactionManager.getTransaction(transactionDefinition);
Integer count = null;
try {
count = testUpdateWithPropagation("testPlatformTransactionManager.testUpdateWithPropagation");
transactionManager.commit(transactionStatus);
} catch (Exception e) {
log.error("testTransactionTemplate异常{}", e.getMessage(), e);
transactionManager.rollback(transactionStatus);
}
log.info("testPlatformTransactionManager执行结果:{}", count);
}
public int testUpdateWithPropagation(String message) {
DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition();
transactionDefinition.setName("testUpdateWithPropagation");
transactionDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_NEVER);
TransactionStatus transactionStatus = transactionManager.getTransaction(transactionDefinition);
try {
int count = jdbcTemplate.update("update t_cu_wyr_bank set core_cust_id = '" + message + "' where core_mer_no = 'myId1711190640426'");
log.info("更新条数:{}", count);
transactionManager.commit(transactionStatus);
//int i = 1/0;
return count;
} catch (Exception e) {
log.error("testUpdateWithPropagation{}", e.getMessage(), e);
transactionManager.rollback(transactionStatus);
return -1;
}
}
/**
* ProxyTransactionManagementConfiguration
* <p>
* org.springframework.transaction.config.internalTransactionAdvisor ------> BeanFactoryTransactionAttributeSourceAdvisor
* <p>
* TransactionAttributeSourcePointcut的内部类TransactionAttributeSourceClassFilter.match方法匹配bean上的每个方法,
* 采用SpringTransactionAnnotationParser.isCandidateClass方法是否添加了@Transactional注解
* <p>
* <p>
* TransactionInterceptor 执行事务增强逻辑
*
*
*
* TransactionSynchronizationManager spring中管理事务同步的核心类,主要通过TreadLocal来进行不同线程之间的数据隔离,以及相同线程之间的事务同步共享
* 它负责管理每个线程的数据库连接资源和事务同步,确保事务在多线程环境下的正确执行
*
* @EnableTransactionManagement开启spring注解声明式事务;
* @Transactional 事务注解
*/
@Transactional
public void testTransactionalAnnotation() {
testUpdate("testTransactionalAnnotation222222");
}
public int testUpdate(String message) {
int count = jdbcTemplate.update("update t_cu_wyr_bank set core_cust_id = '" + message + "' where core_mer_no = 'myId1711190640426'");
log.info("更新条数:{}", count);
//int i = 1/0;
return count;
}
}
-
spring事务解析流程
-
spring自定义事务流程解析
- spring事务是基于spring aop来实现的。所以当@EnableTransactionManagement开启事务时, @Import({TransactionManagementConfigurationSelector.class})在spring扫描的时候,会将TransactionManagementConfigurationSelector作为一个配置类注册到单例池中,由于它实现了ImportSelector,所以会调用其的selectImports方法,向容器中注册BeanFactoryTransactionAttributeSourceAdvisor对象以及TransactionInterceptor对象
@Configuration( proxyBeanMethods = false ) @Role(2) public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration { public ProxyTransactionManagementConfiguration() { } @Bean( name = {"org.springframework.transaction.config.internalTransactionAdvisor"} ) @Role(2) public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) { BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor(); advisor.setTransactionAttributeSource(transactionAttributeSource); advisor.setAdvice(transactionInterceptor); if (this.enableTx != null) { advisor.setOrder((Integer)this.enableTx.getNumber("order")); } return advisor; } @Bean @Role(2) public TransactionAttributeSource transactionAttributeSource() { return new AnnotationTransactionAttributeSource(); } @Bean @Role(2) public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) { TransactionInterceptor interceptor = new TransactionInterceptor(); interceptor.setTransactionAttributeSource(transactionAttributeSource); if (this.txManager != null) { interceptor.setTransactionManager(this.txManager); } return interceptor; } }- 当spring在bean的生命周期中,执行spring aop的AnnotationAwareAspectJAutoProxyCreator.postProcessAfterInitialization的方法时,去筛选对应的;因为spring的扫描时机在bean的生命周期之前完成的。所以在advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Advisor.class, true, false)会将BeanFactoryTransactionAttributeSourceAdvisor加到Advisor列表中;
/** * Find all candidate Advisors to use in auto-proxying. * @return the List of candidate Advisors */ protected List<Advisor> findCandidateAdvisors() { Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available"); //当spring采用了声明式事务的话,会有一个BeanFactoryTransactionAttributeSourceAdvisor return this.advisorRetrievalHelper.findAdvisorBeans(); } public List<Advisor> findAdvisorBeans() { // Determine list of advisor bean names, if not cached already. String[] advisorNames = this.cachedAdvisorBeanNames; if (advisorNames == null) { // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let the auto-proxy creator apply to them! advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Advisor.class, true, false); this.cachedAdvisorBeanNames = advisorNames; } if (advisorNames.length == 0) { return new ArrayList<>(); } List<Advisor> advisors = new ArrayList<>(); for (String name : advisorNames) { if (isEligibleBean(name)) { if (this.beanFactory.isCurrentlyInCreation(name)) { if (logger.isTraceEnabled()) { logger.trace("Skipping currently created advisor '" + name + "'"); } } else { try { advisors.add(this.beanFactory.getBean(name, Advisor.class)); } catch (BeanCreationException ex) { Throwable rootCause = ex.getMostSpecificCause(); if (rootCause instanceof BeanCurrentlyInCreationException) { BeanCreationException bce = (BeanCreationException) rootCause; String bceBeanName = bce.getBeanName(); if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) { if (logger.isTraceEnabled()) { logger.trace("Skipping advisor '" + name + "' with dependency on currently created bean: " + ex.getMessage()); } // Ignore: indicates a reference back to the bean we're trying to advise. // We want to find advisors other than the currently created bean itself. continue; } } throw ex; } } } } return advisors; }- 在执行AbstractAdvisorAutoProxyCreator.findAdvisorsThatCanApply筛选过滤作用在当前bean的List列表,最终调用到AopUtils.canApply方法判断该Advisor是否作用到当前bean上; 在类级别过滤筛选时,最终会调用SpringTransactionAnnotationParser.isCandidateClass方法,判断类上是否添加@Transactional注解;在方法级别过滤时,调用TransactionAttributeSourcePointcut.matchs方法,最终调用 AnnotationTransactionAttributeSource.getTransactionAttribute方法判断方法是否添加@Transactional注解
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) { Assert.notNull(pc, "Pointcut must not be null"); //先在类级别进行匹配,如果不匹配,那么直接返回false if (!pc.getClassFilter().matches(targetClass)) { return false; } MethodMatcher methodMatcher = pc.getMethodMatcher(); if (methodMatcher == MethodMatcher.TRUE) { // No need to iterate the methods if we're matching any method anyway... return true; } IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null; if (methodMatcher instanceof IntroductionAwareMethodMatcher) { introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher; } Set<Class<?>> classes = new LinkedHashSet<>(); if (!Proxy.isProxyClass(targetClass)) { classes.add(ClassUtils.getUserClass(targetClass)); } classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass)); //遍历处理目标类和目标类的接口 for (Class<?> clazz : classes) { Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz); for (Method method : methods) { // if (introductionAwareMethodMatcher != null ? introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) : methodMatcher.matches(method, targetClass)) { return true; } } } return false; } public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) { if (method.getDeclaringClass() == Object.class) { return null; } // First, see if we have a cached value. Object cacheKey = getCacheKey(method, targetClass); TransactionAttribute cached = this.attributeCache.get(cacheKey); if (cached != null) { // Value will either be canonical value indicating there is no transaction attribute, // or an actual transaction attribute. if (cached == NULL_TRANSACTION_ATTRIBUTE) { return null; } else { return cached; } } else { // We need to work it out. TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass); // Put it in the cache. if (txAttr == null) { this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE); } else { String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass); if (txAttr instanceof DefaultTransactionAttribute) { DefaultTransactionAttribute dta = (DefaultTransactionAttribute) txAttr; dta.setDescriptor(methodIdentification); dta.resolveAttributeStrings(this.embeddedValueResolver); } if (logger.isTraceEnabled()) { logger.trace("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr); } this.attributeCache.put(cacheKey, txAttr); } return txAttr; } }- 执行代理方法时完成spring事务增强,TransactionInterceptor.invoke完成声明式事务管理
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); //传入一个回调函数,让advice通知责任链继续执行 return invokeWithinTransaction(invocation.getMethod(), targetClass, new CoroutinesInvocationCallback() { @Override @Nullable public Object proceedWithInvocation() throws Throwable { return invocation.proceed(); } @Override public Object getTarget() { return invocation.getThis(); } @Override public Object[] getArguments() { return invocation.getArguments(); } }); }- 执行编程式事务PlatformTransactionManager执行流程,创建TransactionInfo事务对象信息后,继续执行拦截器链上的通知以及目标方法后,出现异常调用completeTransactionAfterThrowing进行事务回滚或提交;执行commitTransactionAfterReturning进行事务提交;
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对象,用于从类或者方法上事务注解分析相应的事务属性,如果是注解版本AnnotationTransactionAttributeSource对象 TransactionAttributeSource tas = getTransactionAttributeSource(); //获取方法或类上获取事务属性信息(事务回滚策略,事务传播机制,隔离级别等)---RuleBasedTransactionAttribute final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null); //获取TransactionManager事务管理对象, final TransactionManager tm = determineTransactionManager(txAttr); //spring 5.2版本引入的反应式事务编程管理,主要用于异步处理 if (this.reactiveAdapterRegistry != null && tm instanceof ReactiveTransactionManager) { boolean isSuspendingFunction = KotlinDetector.isSuspendingFunction(method); boolean hasSuspendingFlowReturnType = isSuspendingFunction && COROUTINES_FLOW_CLASS_NAME.equals(new MethodParameter(method, -1).getParameterType().getName()); if (isSuspendingFunction && !(invocation instanceof CoroutinesInvocationCallback)) { throw new IllegalStateException("Coroutines invocation not supported: " + method); } CoroutinesInvocationCallback corInv = (isSuspendingFunction ? (CoroutinesInvocationCallback) invocation : null); ReactiveTransactionSupport txSupport = this.transactionSupportCache.computeIfAbsent(method, key -> { Class<?> reactiveType = (isSuspendingFunction ? (hasSuspendingFlowReturnType ? Flux.class : Mono.class) : method.getReturnType()); ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(reactiveType); if (adapter == null) { throw new IllegalStateException("Cannot apply reactive transaction to non-reactive return type [" + method.getReturnType() + "] with specified transaction manager: " + tm); } return new ReactiveTransactionSupport(adapter); }); InvocationCallback callback = invocation; if (corInv != null) { callback = () -> CoroutinesUtils.invokeSuspendingFunction(method, corInv.getTarget(), corInv.getArguments()); } Object result = txSupport.invokeWithinTransaction(method, targetClass, callback, txAttr, (ReactiveTransactionManager) tm); if (corInv != null) { Publisher<?> pr = (Publisher<?>) result; return (hasSuspendingFlowReturnType ? KotlinDelegate.asFlow(pr) : KotlinDelegate.awaitSingleOrNull(pr, corInv.getContinuation())); } return result; } //将编程式事务管理器PlatformTransactionManager PlatformTransactionManager ptm = asPlatformTransactionManager(tm); final String joinpointIdentification = methodIdentification(method, targetClass, txAttr); if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) { // Standard transaction demarcation with getTransaction and commit/rollback calls. // TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification); Object retVal; 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); } if (retVal != null && vavrPresent && VavrDelegate.isVavrTry(retVal)) { // Set rollback-only in case of Vavr failure matching our rollback rules... TransactionStatus status = txInfo.getTransactionStatus(); if (status != null && txAttr != null) { retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status); } } //事务提交 commitTransactionAfterReturning(txInfo); return retVal; } else { Object result; final ThrowableHolder throwableHolder = new ThrowableHolder(); //CallbackPreferringPlatformTransactionManager,通过回调(Callback)来处理事务,比较依赖回调方法; // 事务管理策略和代码逻辑与回调机制相协调 // It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in. try { result = ((CallbackPreferringPlatformTransactionManager) ptm).execute(txAttr, status -> { TransactionInfo txInfo = prepareTransactionInfo(ptm, txAttr, joinpointIdentification, status); try { Object retVal = invocation.proceedWithInvocation(); if (retVal != null && vavrPresent && VavrDelegate.isVavrTry(retVal)) { // Set rollback-only in case of Vavr failure matching our rollback rules... retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status); } return retVal; } catch (Throwable ex) { if (txAttr.rollbackOn(ex)) { // A RuntimeException: will lead to a rollback. if (ex instanceof RuntimeException) { throw (RuntimeException) ex; } else { throw new ThrowableHolderException(ex); } } else { // A normal return value: will lead to a commit. throwableHolder.throwable = ex; return null; } } finally { cleanupTransactionInfo(txInfo); } }); } catch (ThrowableHolderException ex) { throw ex.getCause(); } catch (TransactionSystemException ex2) { if (throwableHolder.throwable != null) { logger.error("Application exception overridden by commit exception", throwableHolder.throwable); ex2.initApplicationException(throwableHolder.throwable); } throw ex2; } catch (Throwable ex2) { if (throwableHolder.throwable != null) { logger.error("Application exception overridden by commit exception", throwableHolder.throwable); } throw ex2; } // Check result state: It might indicate a Throwable to rethrow. if (throwableHolder.throwable != null) { throw throwableHolder.throwable; } return result; } }- PlatformTransactionManager.getTransaction获取事务状态信息DefaultTransactionStatus; 构建对应的TransactionInfo对象(它持有事务的状态信息,事务嵌套关系,以及事务的调用链表oldTransactionInfo<链表的头指针>)与当前线程绑定;
/** * 获取当前事务状态TransactionStatus * * 1.获取当前事务的ConnectionHolder链接对象 * 2.事务的传播属性验证(传播属性规则) * 2.1 若存在事务时,判断事务传播属性,判断是否抛异常,是否需要挂起当前事务后(创建新事物或非事务运行),是否支持嵌套事务(创建事务保存点),或者加入当前事务或者以非事务执行 * 2.2 若创建新事务时,隔离级别,timeout ,ConnectionHolder等配置并绑定到当前线程 */ @Override public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException { // Use defaults if no transaction definition given. TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults()); //获取当前线程缓存在threadLocal里面的ConnectionHolder, 如果没有 ,DataSourceTransactionObject里的ConnectionHolder为null Object transaction = doGetTransaction(); boolean debugEnabled = logger.isDebugEnabled(); //判断当前是否存在事务,当前DataSourceTransactionObject里的ConnectionHolder不为空且transactionActive为true if (isExistingTransaction(transaction)) { // Existing transaction found -> check propagation behavior to find out how to behave. return handleExistingTransaction(def, transaction, debugEnabled); } // Check definition settings for new transaction. //事务的超时设置验证 if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) { throw new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout()); } // No existing transaction found -> check propagation behavior to find out how to proceed. //当前事务传播机制为TransactionDefinition.PROPAGATION_MANDATORY==2;但当前没有事务,所以抛出异常 if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) { throw new IllegalTransactionStateException( "No existing transaction found for transaction marked with propagation 'mandatory'"); } //当前不存在事务,创建新的事务执行 else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED || def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW || def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) { //事务挂起,传null,不会做任何操作 SuspendedResourcesHolder suspendedResources = suspend(null); if (debugEnabled) { logger.debug("Creating new transaction with name [" + def.getName() + "]: " + def); } try { //创建一个新的事务 return startTransaction(def, transaction, debugEnabled, suspendedResources); } catch (RuntimeException | Error ex) { resume(null, suspendedResources); throw ex; } } else { // Create "empty" transaction: no actual transaction, but potentially synchronization. //以非事务方式执行,但隔离级别不为默认,会抛出一个warn日志 if (def.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) { logger.warn("Custom isolation level specified but no actual transaction initiated; " + "isolation level will effectively be ignored: " + def); } boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS); return prepareTransactionStatus(def, null, true, newSynchronization, debugEnabled, null); } }private TransactionStatus handleExistingTransaction( TransactionDefinition definition, Object transaction, boolean debugEnabled) throws TransactionException { //当前存在事务,但是传播属性PROPAGATION_NEVER 所以会抛异常 if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) { throw new IllegalTransactionStateException( "Existing transaction found for transaction marked with propagation 'never'"); } if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) { if (debugEnabled) { logger.debug("Suspending current transaction"); } //当前存在事务,挂起当前事务-suspendedResources = SuspendedResourcesHolder Object suspendedResources = suspend(transaction); boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS); //并以非事务运行 return prepareTransactionStatus( definition, null, false, newSynchronization, debugEnabled, suspendedResources); } if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) { if (debugEnabled) { logger.debug("Suspending current transaction, creating new transaction with name [" + definition.getName() + "]"); } //当前存在事务,挂起当前事务 SuspendedResourcesHolder suspendedResources = suspend(transaction); try { //创建一个新的事务运行 return startTransaction(definition, transaction, debugEnabled, suspendedResources); } catch (RuntimeException | Error beginEx) { resumeAfterBeginException(transaction, suspendedResources, beginEx); throw beginEx; } } if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) { if (!isNestedTransactionAllowed()) { throw new NestedTransactionNotSupportedException( "Transaction manager does not allow nested transactions by default - " + "specify 'nestedTransactionAllowed' property with value 'true'"); } if (debugEnabled) { logger.debug("Creating nested transaction with name [" + definition.getName() + "]"); } if (useSavepointForNestedTransaction()) { // Create savepoint within existing Spring-managed transaction, // through the SavepointManager API implemented by TransactionStatus. // Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization. //transaction DataSourceTransactionObject DefaultTransactionStatus status = prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null); //创建事务保存点-----底层通过transaction(DataSourceTransactionObject)中的ConnectionHolder的 //Connection去创建保存点(底层是JDBC的封装) status.createAndHoldSavepoint(); return status; } else { // Nested transaction through nested begin and commit/rollback calls. // Usually only for JTA: Spring synchronization might get activated here // in case of a pre-existing JTA transaction. return startTransaction(definition, transaction, debugEnabled, null); } } // Assumably PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED. if (debugEnabled) { logger.debug("Participating in existing transaction"); } if (isValidateExistingTransaction()) { //判断隔离级别非默认 if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) { Integer currentIsolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel(); if (currentIsolationLevel == null || currentIsolationLevel != definition.getIsolationLevel()) { Constants isoConstants = DefaultTransactionDefinition.constants; throw new IllegalTransactionStateException("Participating transaction with definition [" + definition + "] specifies isolation level which is incompatible with existing transaction: " + (currentIsolationLevel != null ? isoConstants.toCode(currentIsolationLevel, DefaultTransactionDefinition.PREFIX_ISOLATION) : "(unknown)")); } } if (!definition.isReadOnly()) { if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) { throw new IllegalTransactionStateException("Participating transaction with definition [" + definition + "] is not marked as read-only but existing transaction is"); } } } boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); //当前存在事务,则加入事务 return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null); }-
事务提交与回滚
- 事务的提交与回滚都是JDBC的connection来进行事务提交和回滚
private void processCommit(DefaultTransactionStatus status) throws TransactionException { try { boolean beforeCompletionInvoked = false; try { boolean unexpectedRollback = false; //用于在事务提交之前进行准备工作和触发前置回调-在事务提交之前进行准备工作,如资源锁定、日志记录等1 //扩展方法 prepareForCommit(status); //扩展机制 triggerBeforeCommit(status); //扩展机制 triggerBeforeCompletion(status); beforeCompletionInvoked = true; //当前事务提交的时候,存在事务保存点(嵌套事务),则释放保存点,无须提交事务 if (status.hasSavepoint()) { if (status.isDebug()) { logger.debug("Releasing transaction savepoint"); } unexpectedRollback = status.isGlobalRollbackOnly(); //释放持有的回滚点 status.releaseHeldSavepoint(); } //新的事务,调用子类doCommit提交事务 else if (status.isNewTransaction()) { if (status.isDebug()) { logger.debug("Initiating transaction commit"); } unexpectedRollback = status.isGlobalRollbackOnly(); //提交事务-DataSourceTransactionManager, //获取DefaultTransactionStatus中的DataSourceTransactionObject中ConnectionHolder中的Connection去提交事务 doCommit(status); } else if (isFailEarlyOnGlobalRollbackOnly()) { unexpectedRollback = status.isGlobalRollbackOnly(); } // Throw UnexpectedRollbackException if we have a global rollback-only // marker but still didn't get a corresponding exception from commit. //判断是否标记了 全局回滚,RollbackOnly=true(当前的ConnectionHolder的RollbackOnly属性) if (unexpectedRollback) { throw new UnexpectedRollbackException( "Transaction silently rolled back because it has been marked as rollback-only"); } } catch (UnexpectedRollbackException ex) { // can only be caused by doCommit //事务回滚成功后-扩展点 triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK); throw ex; } catch (TransactionException ex) { // can only be caused by doCommit if (isRollbackOnCommitFailure()) { //异常回滚 doRollbackOnCommitException(status, ex); } else { //当前事务状态未知--扩展点 triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN); } throw ex; } catch (RuntimeException | Error ex) { if (!beforeCompletionInvoked) { triggerBeforeCompletion(status); } //异常回滚 doRollbackOnCommitException(status, ex); throw ex; } // Trigger afterCommit callbacks, with an exception thrown there // propagated to callers but the transaction still considered as committed. try { //事务提交成功后-扩展点 triggerAfterCommit(status); } finally { //事务提交成功后-扩展机制 triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED); } } finally { //完成后清除事务信息,清除当前ThreadLocal中的信息,释放connection,恢复挂起的事务 cleanupAfterCompletion(status); } } /** * This implementation of rollback handles participating in existing * transactions. Delegates to {@code doRollback} and * {@code doSetRollbackOnly}. * @see #doRollback * @see #doSetRollbackOnly */ @Override public final void rollback(TransactionStatus status) throws TransactionException { if (status.isCompleted()) { throw new IllegalTransactionStateException( "Transaction is already completed - do not call commit or rollback more than once per transaction"); } DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status; processRollback(defStatus, false); } /** * Process an actual rollback. * The completed flag has already been checked. * @param status object representing the transaction * @throws TransactionException in case of rollback failure */ private void processRollback(DefaultTransactionStatus status, boolean unexpected) { try { boolean unexpectedRollback = unexpected; try { //扩展点 triggerBeforeCompletion(status); //判读是否存在事务保存点 if (status.hasSavepoint()) { if (status.isDebug()) { logger.debug("Rolling back transaction to savepoint"); } //事务回滚---回滚至事务保存点 status.rollbackToHeldSavepoint(); } else if (status.isNewTransaction()) { if (status.isDebug()) { logger.debug("Initiating transaction rollback"); } //进行事务回滚 doRollback(status); } else { // Participating in larger transaction // 存在事务-但不是新事物(加入的事务) if (status.hasTransaction()) { if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) { if (status.isDebug()) { logger.debug("Participating transaction failed - marking existing transaction as rollback-only"); } //设置事务回滚 doSetRollbackOnly(status); } else { if (status.isDebug()) { logger.debug("Participating transaction failed - letting transaction originator decide on rollback"); } } } else { logger.debug("Should roll back transaction but cannot - no transaction available"); } // Unexpected rollback only matters here if we're asked to fail early if (!isFailEarlyOnGlobalRollbackOnly()) { unexpectedRollback = false; } } } catch (RuntimeException | Error ex) { triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN); throw ex; } triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK); // Raise UnexpectedRollbackException if we had a global rollback-only marker if (unexpectedRollback) { throw new UnexpectedRollbackException( "Transaction rolled back because it has been marked as rollback-only"); } } finally { cleanupAfterCompletion(status); } }- 用户显示调用提交将事务进行事务回滚 在事务执行过程中,由于某种原因,事务中的代码显式地请求事务回滚的操作,可以直接调用TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();将当前线程中的事务进行回滚。
-
spring事务传播机制
-
spring事务传播机制共有7种以及对象的特性
-
spring默认的事务传播机制,TransactionDefinition.PROPAGATION_REQUIRED = 0; 如果当前存在事务则加入该事务,如果当前没有事务,则创建一个新的事务;
-
TransactionDefinition.PROPAGATION_SUPPORTS = 1; 如果当前存在事务则加入该事务 如果当前没有事务 则以非事务的方式继续运行;
-
TransactionDefinition.PROPAGATION_MANDATORY = 2;如果当前存在事务则加入该事务 如果当前没有事务 则抛出异常;
-
TransactionDefinition.PROPAGATION_REQUIRES_NEW = 3; 创建一个新的事务 如果当前存在事务 则把当前事务挂起;
-
TransactionDefinition.PROPAGATION_NOT_SUPPORTED = 4; 以非事务方式运行 如果当前存在事务 则把当前事务挂起;
-
TransactionDefinition.PROPAGATION_NEVER = 5;以非事务方式运行如果当前存在事务则抛出异常;
-
TransactionDefinition.PROPAGATION_NESTED = 6;如果当前存在事务则创建一个事务作为当前事务的嵌套事务来运行,如果不存在则创建一个新的事务;
- 嵌套事务,对于JDBC来说,嵌套事务是通过事务保存点来实现的;当子事务提交,只会释放对应的保存点;子事务回滚,只会回滚至保存点;而父事务能控制所有子事务的提交与回滚的特性;
-
-
spring事务原理
-
事务执行流程
- spring事务是通过PlatformTransactionManager事务管理器来实现的;
- 当@EnableTransactionManagement开启声明式事务时,spring进行扫描的时候会向容器中注入三个Bean分别是BeanFactoryTransactionAttrubuteSourceAdvisor,TransactionInterceptor, AnnotationTransactionAttributeSource;当spring执行bean的生命周期初始化回调的后置方法postProcessAfterInitialization方法时,会扫描当前类上或者方法中添加@Transactional注解;来创建代理对象,并构建对应的拦截器链;
- 当调用代理对象的增强方法时,会执行对应的拦截器链上的通知,会执行TransactionInterceptor.invoke方法,完成事务增强;
-
spring事务-DataSourceTransactionManager事务管理原理
- 获取方法上或类上的事务信息TransactionAttribute,并构建获取TransactionStatus事务状态信息。
- 通过TransactionSynchronizationManager获取当前线程中ConnectionHolder无事务,则为空;创建新事务时startTransaction,会创建ConnectionHolder并与当前线程做绑定;如果以非事务执行时,就不会创建ConnectionHolder对象,进行事务管理;如果需要挂起当前事务时,解除线程绑定的ConnectionHolder,以及重置TransactionSynchronizationManager事务同步管理器中,当前线程的事务属性信息;如果是嵌套事务则,调用JDBC的底层接口,创建事务保存点即可;对于加入该事务时,执行共有同一个ConnectionHolder对象,并设置相应的事务属性即可;
-
-
spring声明式事务失效的场景
-
方法权限问题导致@Transactional失效-声明式事务是基于spring aop来实现的
- 方法必须是public,非final,不能调用this.方法(即方法必须被代理增强,可以通过获取当前bean的代理增强对象,调用对应的方法即可),未被spring管理
-
多线程调用
- DataSourceTransactionManager事务管理是基于Connection连接来实现的,而数据源以及对应的连接是与线程绑定的;(ConnectionHolder是TransactionSynchronizationManager里ThreadLocal中)
-
数据库不支持事务
-
spring事务回滚失效的几个场景
- 当前事务回滚的异常不支持或者手动吃了(以及嵌套事务未手动处理子事务的异常)
-
-
spring事务中,重要的几个组件
- TransactionStatus用于保存当前事物状态,比如是否只能回滚、是否包含回滚点、是否只读,其实现类内部包含事物操作对象transaction事物操作对象transaction包含不同的实现,比如JDBC的DataSourceTransactionObject、Hibernate的HibernateTransactionObject等
- BeanFactoryTransactionAttrubuteSourceAdvisor
- TransactionInterceptor
- AnnotationTransactionAttributeSource
- DataSourceTransactionManager
- TransactionSynchronizationManager
- TransactionStatus(DefaultTransactionStatus)
- ConnectionHolder
- DataSourceUtils :主要用于从当前事务上下文中获取绑定的JDBC连接,并支持Spring的事务管理,并于数据访问技术框架集成;