前言

如果这是你第二次看到师长,说明你在觊觎我的美色!

点赞+关注再看,养成习惯

没别的意思,就是需要你的窥屏^_^

专车介绍

该趟专车是开往Spring Boot事务源码分析的专车

专车问题

  • 为什么加上@Transactional注解就可以实现事务?
  • 分析事务源码之后我们可以学到什么?

专车名词

事务

程序中通常使用事务来达到数据的一致性,从而避免脏数据

编程式事务

在业务方法开头开启事务,然后对我们的业务进行try-catch,假设没有异常则提交事务,如果出现异常,则在catch模块回滚事务

声明式事务由来

如果采用编程式事务,那么在任何需要事务的地方都要开启事务、try-catch、提交或者回滚事务,会导致重复编码、编写与业务无关的代码。基于Spring Aop思想,我们可以利用Aop的方式,对需要使用事务的方法进行增强,将公用的部分提取出来,那么就实现了声明式事务。

Spring提供的声明式事务

在需要使用事务的业务方法上添加@Transactional注解,那么就可以使用事务的特性,要么成功,要么失败

Spring Aop核心概念

  • 切面:切面是由切点和通知组成
  • 切点:用来匹配符合条件类或方法
  • 通知:需要执行的操作

专车分析

基于Spring Boot自动配置原理,我们应该寻找xxxAutoConfiguration自动配置类,此处要寻找和事务相关的,那么自然是TransactionAutoConfiguration

自动配置

打开TransactionAutoConfiguration自动配置类

@Configuration@ConditionalOnBean(PlatformTransactionManager.class)@ConditionalOnMissingBean(AbstractTransactionManagementConfiguration.class)public static class EnableTransactionManagementConfiguration {@Configuration@EnableTransactionManagement(proxyTargetClass = false)@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = false)public static class JdkDynamicAutoProxyConfiguration {}@Configuration@EnableTransactionManagement(proxyTargetClass = true)@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true)public static class CglibAutoProxyConfiguration {}}

可以看到开启事务管理器的注解@EnableTransactionManagement

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

查看TransactionManagementConfigurationSelector导入的类

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;}}

可以看到导入了AutoProxyRegistrar和ProxyTransactionManagementConfiguration

首先看看AutoProxyRegistrar,该类实现了ImportBeanDefinitionRegistrar

public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {boolean candidateFound = false;Set annoTypes = importingClassMetadata.getAnnotationTypes();for (String annoType : annoTypes) {AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annoType);if (candidate == null) {continue;}Object mode = candidate.get("mode");Object proxyTargetClass = candidate.get("proxyTargetClass");if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&Boolean.class == proxyTargetClass.getClass()) {candidateFound = true;if (mode == AdviceMode.PROXY) { // 注册自动代理创建器AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);if ((Boolean) proxyTargetClass) {AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);return;}}}}}

注册自动代理创建器,AopConfigUtils#registerAutoProxyCreatorIfNecessary

public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, @Nullable Object source) { // 注册了InfrastructureAdvisorAutoProxyCreator到IOC容器中return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);}

InfrastructureAdvisorAutoProxyCreator是AbstractAutoProxyCreator的子类,AbstractAutoProxyCreator又实现了BeanPostProcessor接口,那么在bean初始化完毕后就会调用postProcessAfterInstantiation()方法,postProcessAfterInstantiation()定义在AbstractAutoProxyCreator类中

BeanPostProcessor后置处理

打开AbstractAutoProxyCreator

@Overridepublic Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {if (bean != null) {Object cacheKey = getCacheKey(bean.getClass(), beanName);if (!this.earlyProxyReferences.contains(cacheKey)) { // 如果满足条件对bean进行包裹return wrapIfNecessary(bean, beanName, cacheKey);}}return bean;}

该方法调用了wrapIfNecessary()方法

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {// Create proxy if we have advice. // 获取bean的切面和通知Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); // 需要代理if (specificInterceptors != DO_NOT_PROXY) {this.advisedBeans.put(cacheKey, Boolean.TRUE); // 创建代理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;}

根据注释的意思就是如果存在advice,那么就创建代理,

寻找切面

进入AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean

protected Object[] getAdvicesAndAdvisorsForBean(Class> beanClass, String beanName, @Nullable TargetSource targetSource) { // 查找符合条件的切面List advisors = findEligibleAdvisors(beanClass, beanName);// 不存在符合条件的切面,则不生成代理if (advisors.isEmpty()) {return DO_NOT_PROXY;}return advisors.toArray();}

该代码第一句最重要,如果不存在符合条件的切面,那么最终的结果返回null,根据上面分析的,如果为null就不创建代理,否则创建代理。接下来看看第一句的实现

protected List findEligibleAdvisors(Class> beanClass, String beanName) { // 获取所有候选的切面,也就是类型为Advisor的切面,此处获取到的候选切面为BeanFactoryTransactionAttributeSourceAdvisor List candidateAdvisors = findCandidateAdvisors(); // 从候选的切面中获取可以解析当前bean的切面,最终符合条件的切面为BeanFactoryTransactionAttributeSourceAdvisor List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors;}

为什么上面获取到的切面是BeanFactoryTransactionAttributeSourceAdvisor?是否还记得之前导入配置类的时候还有一个配置类没有分析?那就是ProxyTransactionManagementConfiguration

打开ProxyTransactionManagementConfiguration

@Configurationpublic class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration { // 创建BeanFactoryTransactionAttributeSourceAdvisor@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.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;}}

通过上面的自动配置,可得知获取到的候选切面为什么是BeanFactoryTransactionAttributeSourceAdvisor

接下来看看如何从候选切面中找到可以解析当前bean的切面?

protected List findAdvisorsThatCanApply(List candidateAdvisors, Class> beanClass, String beanName) {ProxyCreationContext.setCurrentProxiedBeanName(beanName);try { // 查找可以解析当前bean对应的切面return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);}finally {ProxyCreationContext.setCurrentProxiedBeanName(null);}}

查找可以解析当前bean对应的切面,AopUtils#findAdvisorsThatCanApply

public static List findAdvisorsThatCanApply(List candidateAdvisors, Class> clazz) {if (candidateAdvisors.isEmpty()) {return candidateAdvisors;}List eligibleAdvisors = new ArrayList<>();for (Advisor candidate : candidateAdvisors) {if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {eligibleAdvisors.add(candidate);}}boolean hasIntroductions = !eligibleAdvisors.isEmpty();for (Advisor candidate : candidateAdvisors) {if (candidate instanceof IntroductionAdvisor) {// already processedcontinue;}// 当前切面是否可以解析beanif (canApply(candidate, clazz, hasIntroductions)) {eligibleAdvisors.add(candidate);}}return eligibleAdvisors;}

候选切面是否可以解析bean

public static boolean canApply(Advisor advisor, Class> targetClass, boolean hasIntroductions) {if (advisor instanceof IntroductionAdvisor) {return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);}else if (advisor instanceof PointcutAdvisor) { // 由上面分析知道最终的候选切面为BeanFactoryTransactionAttributeSourceAdvisor // 该类实现了PointcutAdvisorPointcutAdvisor pca = (PointcutAdvisor) advisor;return canApply(pca.getPointcut(), targetClass, hasIntroductions);}else {// It doesn't have a pointcut so we assume it applies.return true;}}

候选切面是否可以解析bean

public static boolean canApply(Pointcut pc, Class> targetClass, boolean hasIntroductions) {Assert.notNull(pc, "Pointcut must not be null");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> classes = new LinkedHashSet<>();if (!Proxy.isProxyClass(targetClass)) {classes.add(ClassUtils.getUserClass(targetClass));}classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));for (Class> clazz : classes) { // 通过反射获取当前类所有的Method对象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;}

匹配方法TransactionAttributeSourcePointcut#matches

public boolean matches(Method method, Class> targetClass) {if (TransactionalProxy.class.isAssignableFrom(targetClass) ||PlatformTransactionManager.class.isAssignableFrom(targetClass) ||PersistenceExceptionTranslator.class.isAssignableFrom(targetClass)) {return false;}TransactionAttributeSource tas = getTransactionAttributeSource();// 如果事务属性源对象为空或者事务属性对象不为null返回true,代表匹配成功;否则返回false,匹配失败return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);}

获取事务属性对象,AbstractFallbackTransactionAttributeSource#getTransactionAttribute

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 {// 计算事务属性对象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) txAttr).setDescriptor(methodIdentification);}if (logger.isTraceEnabled()) {logger.trace("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);}this.attributeCache.put(cacheKey, txAttr);}return txAttr;}}

计算事务属性对象

protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class> targetClass) {// Don't allow no-public methods as required.if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {return null;}// The method may be on an interface, but we need attributes from the target class.// If the target class is null, the method will be unchanged.Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);// First try is the method in the target class.// 首先根据Method对象获取事务属性对象TransactionAttribute txAttr = findTransactionAttribute(specificMethod);if (txAttr != null) {return txAttr;}// Second try is the transaction attribute on the target class.// 如果根据Method对象获取不到事务属性对象,那么根据Class来获取属性对象txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {return txAttr;}if (specificMethod != method) {// Fallback is to look at the original method.txAttr = findTransactionAttribute(method);if (txAttr != null) {return txAttr;}// Last fallback is the class of the original method.txAttr = findTransactionAttribute(method.getDeclaringClass());if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {return txAttr;}}return null;}

获取属性对象AnnotationTransactionAttributeSource#findTransactionAttribute

protected TransactionAttribute findTransactionAttribute(Class> clazz) {return determineTransactionAttribute(clazz);}

决定事务属性对象

protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {for (TransactionAnnotationParser annotationParser : this.annotationParsers) {TransactionAttribute attr = annotationParser.parseTransactionAnnotation(element);if (attr != null) {return attr;}}return null;}

解析事务属性对象,SpringTransactionAnnotationParser#parseTransactionAnnotation

public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) { // 判断元素是否含有@Transactional注解,通过前面的分析我们可以得出如下结论: // 1、首选判断类的方法上是否含有@Transactional注解,如果有就解析 // 2、如果所有的方法都不含有@Transactional注解,那么判断当前类是否含有@Transactional注解,如果有就解析 // 3、如果类或者类的某个方法含有@Transactional注解,那么事务属性对象就不为空,则说明次切面可以解析当前beanAnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(element, Transactional.class, false, false);if (attributes != null) {return parseTransactionAnnotation(attributes);}else {return null;}}

回到AbstractAutoProxyCreator#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.// 此处有值返回,进行代理,否则不进行代理Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);// 需要进行代理if (specificInterceptors != DO_NOT_PROXY) {this.advisedBeans.put(cacheKey, Boolean.TRUE);// 创建代理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;}

创建代理

创建代理AbstractAutoProxyCreator#createProxy

protected Object createProxy(Class> beanClass, @Nullable String beanName,@Nullable Object[] specificInterceptors, TargetSource targetSource) {if (this.beanFactory instanceof ConfigurableListableBeanFactory) {AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);} // 创建代理工厂ProxyFactory proxyFactory = new ProxyFactory();proxyFactory.copyFrom(this);if (!proxyFactory.isProxyTargetClass()) {if (shouldProxyTargetClass(beanClass, beanName)) {proxyFactory.setProxyTargetClass(true);}else {evaluateProxyInterfaces(beanClass, proxyFactory);}} // 构建切面,此处的切面为BeanFactoryTransactionAttributeSourceAdvisorAdvisor[] advisors = buildAdvisors(beanName, specificInterceptors);// 设置切面proxyFactory.addAdvisors(advisors);proxyFactory.setTargetSource(targetSource);customizeProxyFactory(proxyFactory);proxyFactory.setFrozen(this.freezeProxy);if (advisorsPreFiltered()) {proxyFactory.setPreFiltered(true);}return proxyFactory.getProxy(getProxyClassLoader());}

获取代理ProxyFactory#getProxy

public Object getProxy(@Nullable ClassLoader classLoader) {return createAopProxy().getProxy(classLoader);}

创建aop代理

protected final synchronized AopProxy createAopProxy() {if (!this.active) {activate();}// 此处的this实际上就是ProxyFactoryreturn getAopProxyFactory().createAopProxy(this);}

aop代理工厂创建aop代理DefaultAopProxyFactory#createAopProxy

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {Class> targetClass = config.getTargetClass();if (targetClass == null) {throw new AopConfigException("TargetSource cannot determine target class: " +"Either an interface or a target is required for proxy creation.");}if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {return new JdkDynamicAopProxy(config);}// 创建cglib aop代理return new ObjenesisCglibAopProxy(config);}else {return new JdkDynamicAopProxy(config);}}

实例化ObjenesisCglibAopProxy对象

public ObjenesisCglibAopProxy(AdvisedSupport config) {super(config);}

父类实例化

public CglibAopProxy(AdvisedSupport config) throws AopConfigException {Assert.notNull(config, "AdvisedSupport must not be null");if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {throw new AopConfigException("No advisors and no TargetSource specified");}// 此处的config就是之前的ProxyFactorythis.advised = config;this.advisedDispatcher = new AdvisedDispatcher(this.advised);}

回到之前获取代理的地方

public Object getProxy(@Nullable ClassLoader classLoader) {return createAopProxy().getProxy(classLoader);}

通过上面的分析可以得知createAopProxy()返回的是CglibAopProxy

通过CglibAopProxy获取代理,CglibAopProxy#getProxy

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 (ClassUtils.isCglibProxyClass(rootClass)) {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 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 ClassLoaderAwareUndeclaredThrowableStrategy(classLoader)); // 获取回调,重点分析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 aboveenhancer.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() failedthrow new AopConfigException("Unexpected AOP exception", ex);}}

获取回调

private Callback[] getCallbacks(Class> rootClass) throws Exception {// Parameters used for optimization choices...boolean exposeProxy = this.advised.isExposeProxy();boolean isFrozen = this.advised.isFrozen();boolean isStatic = this.advised.getTargetSource().isStatic();// Choose an "aop" interceptor (used for AOP calls).// 实例化回调,在调用目标对象方法的时候执行Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);return callbacks;}

实例化回调部分

private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {private final AdvisedSupport advised;public DynamicAdvisedInterceptor(AdvisedSupport advised) { // 设置切面信息,也就是之前的ProxyFactorythis.advised = advised;}@Override@Nullable// 调用目标方法的时候执行public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {Object oldProxy = null;boolean setProxyContext = false;Object target = null;TargetSource targetSource = this.advised.getTargetSource();try {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); // 获取通知,此处的通知为TransactionInterceptorList chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);Object retVal;// Check whether we only have one InvokerInterceptor: that is,// no real advice, but just reflective invocation of the target.if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {// 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 = methodProxy.invoke(target, argsToUse);}else {// We need to create a method invocation...retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();}retVal = processReturnType(proxy, target, method, retVal);return retVal;}finally {if (target != null && !targetSource.isStatic()) {targetSource.releaseTarget(target);}if (setProxyContext) {// Restore old proxy.AopContext.setCurrentProxy(oldProxy);}}}@Overridepublic boolean equals(Object other) {return (this == other ||(other instanceof DynamicAdvisedInterceptor &&this.advised.equals(((DynamicAdvisedInterceptor) other).advised)));}/** * CGLIB uses this to drive proxy creation. */@Overridepublic int hashCode() {return this.advised.hashCode();}}

调用invocation的处理方法,ReflectiveMethodInvocation#proceed

public Object proceed() throws Throwable {//We start with an index of -1 and increment early.if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {return invokeJoinpoint();} // 此处的通知TransactionInterceptorObject 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.// 调用TransactionInterceptor#invokereturn ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);}}

调用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);// Adapt to TransactionAspectSupport's invokeWithinTransaction...// 以事务的方式进行调用return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);}

事务方式调用

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);}// 提交事务commitTransactionAfterReturning(txInfo);return retVal;}else {final ThrowableHolder throwableHolder = new ThrowableHolder();// It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.try {Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr, status -> {TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);try {return invocation.proceedWithInvocation();}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);}});// Check result state: It might indicate a Throwable to rethrow.if (throwableHolder.throwable != null) {throw throwableHolder.throwable;}return result;}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;}}}

到此事务的源码分析就结束了

专车总结

  • 导入AutoProxyRegistrar、ProxyTransactionManagementConfiguration配置类
  • AutoProxyRegistrar用来注册InfrastructureAdvisorAutoProxyCreator到IOC中,InfrastructureAdvisorAutoProxyCreator实现了BeanPostProcessor
  • 执行BeanPostProcessor的后置处理
  • 获取由ProxyTransactionManagementConfiguration配置类创建的切面
  • 通过切面解析bean是否需要创建代理,需要就创建代理
  • 执行代理的回调,在回调中拿到通知
  • 执行通知,通知里面逻辑:开启事务、执行目标方法、提交或回滚事务

专车回顾

回顾下开头的两个问题:

  • 为什么加上@Transactional注解就可以实现事务?
  • 分析事务源码之后我们可以学到什么?

通过以上分析,第一个问题应该就迎刃而解了,那么通过以上学到的知识我们可以实现什么功能呢?在下一篇我们会在此基础上进行实战,通过@SystemLog注解实现系统日志功能。感谢各位撸友乘坐此趟专车,欢迎下次继续乘坐

最后

师长,【java进阶架构师】号主,短短一年在各大平台斩获15W+程序员关注,专注分享Java进阶、架构技术、高并发、微服务、BAT面试、redis专题、JVM调优、Springboot源码、mysql优化等20大进阶架构专题。

springboot 事务_原创002 | 搭上SpringBoot事务源码分析专车相关推荐

  1. Android上百实例源码分析以及开源分析集合打包

    感谢网友banketree的收集,压缩包的内容如下: 1.360新版特性界面源代码 实现了360新版特性界面的效果,主要涉及到Qt的一些事件处理与自定义控件.但源码好像是c++. 2.aidl跨进程调 ...

  2. springboot事务回滚源码_002 | 搭上SpringBoot事务源码分析专车

    发车啦,发车啦,上车要求: 点击左上方的"java进阶架构师"进入页面 选择右上角的"置顶公众号"上车 专车介绍 该趟专车是开往Spring Boot事务源码分 ...

  3. java tomcat源码_详解Tomcat系列(一)-从源码分析Tomcat的启动

    在整个Tomcat系列文章讲解之前, 我想说的是虽然整个Tomcat体系比较复杂, 但是Tomcat中的代码并不难读, 只要认真花点功夫, 一定能啃下来. 由于篇幅的原因, 很难把Tomcat所有的知 ...

  4. java ee是什么_死磕 java集合之HashSet源码分析

    问题 (1)集合(Collection)和集合(Set)有什么区别? (2)HashSet怎么保证添加元素不重复? (3)HashSet是否允许null元素? (4)HashSet是有序的吗? (5) ...

  5. hashmap修改对应key的值_死磕 java集合之HashMap源码分析

    简介 HashMap采用key/value存储结构,每个key对应唯一的value,查询和修改的速度都很快,能达到O(1)的平均时间复杂度.它是非线程安全的,且不保证元素存储的顺序: 继承体系 Has ...

  6. Android+上百实例源码分析以及开源分析+集合打包

    1.360新版特性界面源代码 实现了360新版特性界面的效果,主要涉及到Qt的一些事件处理与自定义控件.但源码好像是c++. 2.aidl跨进程调用 服务端onBind暴露,然后客户端bindServ ...

  7. idea加入springboot插件_带你搭一个SpringBoot+SpringData JPA的环境

    前言 只有光头才能变强. 不知道大家对SpringBoot和Spring Data JPA了解多少,如果你已经学过Spring和Hibernate的话,那么SpringBoot和SpringData ...

  8. 悟空分词与mysql结合_悟空分词的搜索和排序源码分析之——搜索

    转自:http://blog.codeg.cn/2016/02/02/wukong-source-code-reading/ 搜索过程分析 下面我们来分析一下搜索的过程.首先构造一个SearchReq ...

  9. 悟空分词与mysql结合_悟空分词的搜索和排序源码分析之——索引

    转自:http://blog.codeg.cn/2016/02/02/wukong-source-code-reading/ 索引过程分析 下面我们来分析索引过程. // 将文档加入索引 // // ...

最新文章

  1. HDU1756(判断一个点是否在多边形内)
  2. 计算机网络工程应用,计算机网络工程网络命令的应用
  3. mysql innodb 1017_MySQL InnoDB表压缩
  4. python 二进制文件_使用Python进行二进制文件读写的简单方法(推荐)
  5. 学习笔记之-Kubernetes(K8S)介绍,集群环境搭建,Pod详解,Pod控制器详解,Service详解,数据存储,安全认证,DashBoard
  6. CCF——图像旋转201503-1
  7. 苹果手机怎么拍星空_手机怎么拍星空
  8. 直播电商只能卖便宜货吗?
  9. 不知道如何实现服务的动态发现?快来看看 Dubbo 是如何做到的
  10. 14.5-全栈Java笔记:java.awt这些布局怎么写?|流式|边界|网格
  11. 并发编程的挑战——sychronized锁
  12. 人大金仓数据库软件下载
  13. 联想新电脑桌面没有计算机,联想电脑没有wifi图标不见了怎么办
  14. android 爱加密 脱壳,简单尝试脱“爱加密”官网加固的DEX壳
  15. wh计算公式_锂电池计算公式wh 锂电池的mah和wh如何换算?
  16. 计算机是如何储存信息的,计算机是如何储存信息的
  17. java io 操作实例
  18. [毕业生的商业软件开发之路]积累与创新
  19. 天猫精灵智能家居对接,及天猫iot官网配置图文讲解(二)
  20. TransE模型:知识图谱的经典表示学习方法

热门文章

  1. linux-----shell高级编程----grep应用
  2. 步步为营 .NET 设计模式学习笔记 十九、Chain of Responsibility(职责链模式)
  3. JavaScript事件监听
  4. 程序员请不要问“在吗?”
  5. 看完你也想编写自己的 react 插件
  6. Linux下查看/修改系统时区、时间
  7. poj 3660 Cow Contest
  8. 鲍尔默说:你的东西再大 微软也装得下
  9. html表格标签模板 实现跨行和跨列
  10. 数据库弱一致性四个隔离级别