详解Spring

深入了解Spring的原理与应用

Posted by chengweii on November 10, 2017

Spring

Spring是一个基于分层架构的开源框架,为J2EE企业应用程序提供一站式的解决方案。

Spring架构 Spring是一个开源框架,是为了解决企业应用程序开发复杂性而创建的。
框架的主要优势之一就是其分层架构,分层架构允许您选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架。
它是一个全面的、企业应用开发一站式的解决方案,贯穿表现层、业务层、持久层,但是Spring仍然可以和其他的框架无缝整合。
Spring框架的开发不是为了替代现有的优秀第三方框架,而是通过集成的方式把它们都连接起来。以下框架为在开发中集成的优秀框架:
权限(shiro)、缓存(Ehcache、Redis)、持久层框架(Hibernate、Mybatis)、定时任务(quartz、spring-task)、Web框架(Spring-MVC、Struts)、RPC框架(Dubbo)等

IOC

IOC/DI:控制反转,本质是将原来程序中对象创建、依赖的代码,反转交由容器去协助实现以达到统一管理对象的目的。

Spring中的IOC容器,它的主要作用是完成对象的创建和依赖的管理注入等等。Spring Bean的创建是典型的工厂模式,IOC容器的具体实现就是一系列的Bean工厂,它为开发者管理对象间的依赖关系提供了很多便利和基础服务。 Spring IOC概要模型 Spring IOC概要类图

BeanFactory加载Bean的核心实现

以下是BeanFactory加载Bean的核心代码实现:

//AbstractApplicationContext.refresh
public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
       //调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识  
       prepareRefresh();
       //告诉子类启动refreshBeanFactory()方法,Bean定义资源文件的载入从子类的refreshBeanFactory()方法启动
       ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
       //为BeanFactory配置容器特性,例如类加载器、事件处理器等
       prepareBeanFactory(beanFactory);
       try {
           //为容器的某些子类指定特殊的BeanPost事件处理器
           postProcessBeanFactory(beanFactory);
           //调用所有注册的BeanFactoryPostProcessor的Bean
           invokeBeanFactoryPostProcessors(beanFactory);
           //为BeanFactory注册BeanPost事件处理器。BeanPostProcessor是Bean后置处理器,用于监听容器触发的事件  
           registerBeanPostProcessors(beanFactory);
           //初始化信息源,和国际化相关
           initMessageSource();
           //初始化容器事件传播器
           initApplicationEventMulticaster();
           //调用子类的某些特殊Bean初始化方法
           onRefresh();
           //为事件传播器注册事件监听器
           registerListeners();
           //初始化所有剩余的单例Bean
           finishBeanFactoryInitialization(beanFactory);
           //初始化容器的生命周期事件处理器,并发布容器的生命周期事件
           finishRefresh();
       }
       catch (BeansException ex) {
           //销毁以创建的单态Bean  
           destroyBeans();
           //取消refresh操作,重置容器的同步标识
           cancelRefresh(ex);
           throw ex;
       }
   }
}

这段代码主要包含这样几个步骤:

  • 构建 BeanFactory
  • 注册可能感兴趣的事件
  • 创建 Bean 实例对象
  • 触发被监听的事件

构建 BeanFactory

在这个方法中,先判断BeanFactory是否存在,如果存在则先销毁beans并关闭beanFactory,接着创建DefaultListableBeanFactory,并调用loadBeanDefinitions(beanFactory)装载bean定义。

//AbstractRefreshableApplicationContext.refreshBeanFactory
protected final void refreshBeanFactory() throws BeansException {
   if (hasBeanFactory()) {//如果已经有容器,销毁容器中的bean,关闭容器  
       destroyBeans();
       closeBeanFactory();
   }
   try {
        //创建IoC容器  
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        beanFactory.setSerializationId(getId());
       //对IoC容器进行定制化,如设置启动参数,开启注解的自动装配等  
       customizeBeanFactory(beanFactory);
       //调用载入Bean定义的方法,主要这里又使用了一个委派模式,在当前类中只定义了抽象的loadBeanDefinitions方法,具体的实现调用子类容器  
       loadBeanDefinitions(beanFactory);
       synchronized (this.beanFactoryMonitor) {
           this.beanFactory = beanFactory;
       }
   }
   catch (IOException ex) {
       throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
   }
}

其中载入Bean定义的loadBeanDefinitions方法是后续创建Bean实例对象的关键前提步骤,它的主要内容是加载、解析 Bean 的定义,然后存储到Spring IOC容器(BeanFactory)中。以下是部分关键代码:

//BeanDefinitionReaderUtils.registerBeanDefinition:将解析的BeanDefinitionHolder注册到容器中 
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
    throws BeanDefinitionStoreException {
        //获取解析的BeanDefinition的名称
        String beanName = definitionHolder.getBeanName();
        //向IoC容器注册BeanDefinition 
        registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
        //如果解析的BeanDefinition有别名,向容器为其注册别名  
        String[] aliases = definitionHolder.getAliases();
        if (aliases != null) {
            for (String aliase : aliases) {
                registry.registerAlias(beanName, aliase);
            }
        }
}
//DefaultListableBeanFactory.registerBeanDefinition
public class DefaultListableBeanFactory 
    extends AbstractAutowireCapableBeanFactory 
    implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
        throws BeanDefinitionStoreException {
        //...
        this.beanDefinitionNames.add(beanName);
        //...
        this.beanDefinitionMap.put(beanName, beanDefinition);
        //...
    }
}

注意:BeanDefinitionRegistry的具体实现类其实是以上构建的BeanFactory(DefaultListableBeanFactory), 而最终加载、解析的Bean定义会存储到BeanFactory的成员beanDefinitionMap、beanDefinitionNames中。

注册可能感兴趣的事件

创建好 BeanFactory 后,接下去添加一些 Spring 本身需要的一些工具类,这个操作在 AbstractApplicationContext 的 prepareBeanFactory 方法完成。
接下来的postProcessBeanFactory、invokeBeanFactoryPostProcessors、registerBeanPostProcessors是对 Spring 的功能进行扩展。其中postProcessBeanFactory、invokeBeanFactoryPostProcessors主要是让你现在可以对已经构建的 BeanFactory 的配置做修改,而registerBeanPostProcessors就是让你可以对以后再创建 Bean 的实例对象时添加一些自定义的操作。
而initMessageSource、initApplicationEventMulticaster、registerListeners是初始化监听事件和对系统的其他监听者的注册,监听者必须是 ApplicationListener 的子类。

//BeanFactoryPostProcessor.postProcessBeanFactory:在 invokeBeanFactoryPostProcessors 方法中主要是获取实现 BeanFactoryPostProcessor 接口的子类的Bean实例。并调用它的 postProcessBeanFactory 方法
public interface BeanFactoryPostProcessor {
    void postProcessBeanFactory(ConfigurableListableBeanFactory var1) throws BeansException;
}
//BeanPostProcessor.postProcessBeforeInitialization、BeanPostProcessor.postProcessAfterInitialization
//registerBeanPostProcessors 方法也是可以获取用户定义的实现了 BeanPostProcessor 接口的子类,并把它们注册到 BeanFactory 对象中的 beanPostProcessors 变量中。BeanPostProcessor 中声明了两个方法:postProcessBeforeInitialization、postProcessAfterInitialization 分别用于在 Bean 对象初始化时执行,其中可以定义用户自己的操作。
public interface BeanPostProcessor {
    Object postProcessBeforeInitialization(Object var1, String var2) throws BeansException;
    Object postProcessAfterInitialization(Object var1, String var2) throws BeansException;
}

创建 Bean 实例对象

Bean 的实例化是在 BeanFactory 中完成的。其中核心代码在 preInstantiateSingletons 方法中:

//AbstractApplicationContext.finishBeanFactoryInitialization
//对单态模式Bean进行预实例化处理  
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
   //这是Spring3以后新加的代码,为容器指定一个转换服务(ConversionService)在对某些Bean属性进行转换时使用  
   if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) && beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
       beanFactory.setConversionService(beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
   }
   //为了类型匹配,停止使用临时的类加载器  
   beanFactory.setTempClassLoader(null);
   //缓存容器中所有注册的BeanDefinition元数据,以防被修改  
   beanFactory.freezeConfiguration();
   //对单态模式Bean进行预实例化处理  
   beanFactory.preInstantiateSingletons();
}
//DefaultListableBeanFactory.preInstantiateSingletons
//对单态模式Bean进行预实例化处理
public void preInstantiateSingletons() throws BeansException {
   //...
   //在对单态模式Bean进行预实例化处理过程中,必须多线程同步,以确保数据一致性  
   synchronized (this.beanDefinitionMap) {
       for (String beanName : this.beanDefinitionNames) {
           //获取指定名称的Bean定义  
           RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
           //Bean不是抽象的,是单态模式的,且lazy-init属性配置为false  
           if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
               //如果指定名称的bean是创建容器的Bean  
               if (isFactoryBean(beanName)) {
                   //...
               } else {
                   //调用getBean方法,触发容器对Bean实例化和依赖注入过程  
                   getBean(beanName);
               }
           }
       }
   }
}

触发被监听的事件

在getBean实例化Bean之后,调用AbstractAutowireCapableBeanFactory.initializeBean方法实现为容器创建的Bean实例对象执行BeanPostProcessor后置处理器。

//初始容器创建的Bean实例对象,为其执行BeanPostProcessor后置处理器  
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
   //...
   Object wrappedBean = bean;
   //对BeanPostProcessor后置处理器的postProcessBeforeInitialization  
   //回调方法的调用,为Bean实例初始化前做一些处理  
   if (mbd == null || !mbd.isSynthetic()) {
       wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
   }
   //调用Bean实例对象初始化的方法,这个初始化方法是在Spring Bean定义配置文件中通过init-method属性指定的  
   try {
       invokeInitMethods(beanName, wrappedBean, mbd);
   }
   catch (Throwable ex) {
       throw new BeanCreationException(
               (mbd != null ? mbd.getResourceDescription() : null),
               beanName, "Invocation of init method failed", ex);
   }
   //对BeanPostProcessor后置处理器的postProcessAfterInitialization回调方法的调用,为Bean实例初始化之后做一些处理  
   if (mbd == null || !mbd.isSynthetic()) {
       wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
   }
   return wrappedBean;
}
//调用BeanPostProcessor后置处理器实例对象初始化之前的处理方法  
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
       throws BeansException {
   Object result = existingBean;
   //遍历容器为所创建的Bean添加的所有BeanPostProcessor后置处理器  
   for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
       //调用Bean实例所有的后置处理中的初始化前处理方法,为Bean实例对象在初始化之前做一些自定义的处理操作  
       result = beanProcessor.postProcessBeforeInitialization(result, beanName);
       if (result == null) {
           return result;
       }
   }
   return result;
}
//调用BeanPostProcessor后置处理器实例对象初始化之后的处理方法  
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
       throws BeansException {
   Object result = existingBean;
   //遍历容器为所创建的Bean添加的所有BeanPostProcessor后置处理器  
   for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
       //调用Bean实例所有的后置处理中的初始化后处理方法,为Bean实例对象在初始化之后做一些自定义的处理操作  
       result = beanProcessor.postProcessAfterInitialization(result, beanName);
       if (result == null) {
           return result;
       }
   }
   return result;
}

AOP

AOP(Aspect Oriented Programming)是针对方法调用编程的思路。AOP将每一个方法调用(连接点)作为编程的入口,针对方法调用进行编程。从执行的逻辑上来看,就是将之前的程序横向切割成若干的面,即Aspect.每个面被称为切面。

动态代理(CGLIB和JDK)

Spring AOP是通过动态代理实现的。AOP代理由Spring的IOC容器负责生成、管理,创建代理的规则为:

  • 默认使用Java动态代理来创建AOP代理,这样就可以为任何接口实例创建代理了
  • 当需要代理的类不是代理接口的时候,Spring会切换为使用CGLIB代理,也可强制使用CGLIB AOP的核心逻辑是在AnnotationAwareAspectJAutoProxyCreator类里面实现,而AnnotationAwareAspectJAutoProxyCreator其实是BeanPostProcessor后置处理器,因为它实现了BeanPostProcessor接口,具体后置处理内容就是为每个需要代理的Bean创建代理,该部分逻辑在AnnotationAwareAspectJAutoProxyCreator的父类AbstractAutoProxyCreator中。
    //AbstractAutoProxyCreator.postProcessAfterInitialization
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
      if (bean != null) {
          Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
          if (!this.earlyProxyReferences.contains(cacheKey)) {
              //为需要代理的Bean生成代理
              return this.wrapIfNecessary(bean, beanName, cacheKey);
          }
      }
      return bean;
    }
    //AbstractAutoProxyCreator.wrapIfNecessary
    //提取当前bean 的所有增强方法,然后获取到适合的当前bean 的增强方法,然后对增强方法进行排序,如果需要代理则调用createProxy方法,创建代理,同时织入增强方法。
    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
      if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
          return bean;
      } else if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
          return bean;
      } else if (!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) {
          Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);
          if (specificInterceptors != DO_NOT_PROXY) {
              this.advisedBeans.put(cacheKey, Boolean.TRUE);
              Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
              this.proxyTypes.put(cacheKey, proxy.getClass());
              return proxy;
          } else {
              this.advisedBeans.put(cacheKey, Boolean.FALSE);
              return bean;
          }
      } else {
          this.advisedBeans.put(cacheKey, Boolean.FALSE);
          return bean;
      }
    }
    //AbstractAutoProxyCreator.createProxy
    //创建Bean代理时,首先创建代理工厂proxyFactory,然后获取当前bean 的增强器advisors,把当前获取到的增强器注册到代理工厂proxyFactory,然后设置当前的代理工厂的代理目标对象为当前bean,最后根据配置创建JDK的动态代理工厂,或者CGLIB的动态代理工厂,通过具体的动态代理工厂proxyFactory创建代理对象并返回。
    protected Object createProxy(Class<?> beanClass, String beanName, 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 (this.shouldProxyTargetClass(beanClass, beanName)) {
              proxyFactory.setProxyTargetClass(true);
          } else {
              this.evaluateProxyInterfaces(beanClass, proxyFactory);
          }
      }
    
      Advisor[] advisors = this.buildAdvisors(beanName, specificInterceptors);
      proxyFactory.addAdvisors(advisors);
      proxyFactory.setTargetSource(targetSource);
      this.customizeProxyFactory(proxyFactory);
      proxyFactory.setFrozen(this.freezeProxy);
      if (this.advisorsPreFiltered()) {
          proxyFactory.setPreFiltered(true);
      }
    
      return proxyFactory.getProxy(this.getProxyClassLoader());
    }
    

    动态代理工厂配置为JDK代理

    //JdkDynamicAopProxy.getProxy
    public Object getProxy(ClassLoader classLoader) {
      if (logger.isDebugEnabled()) {
          logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
      }
    
      Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
      this.findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
      return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    }
    //JdkDynamicAopProxy.invoke
    //JDK动态代理核心内容,主要是织入拦截器链
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      Object oldProxy = null;
      boolean setProxyContext = false;
      TargetSource targetSource = this.advised.targetSource;
      Class<?> targetClass = null;
      Object target = null;
    
      Class var10;
      try {
          if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
              Boolean var20 = this.equals(args[0]);
              return var20;
          }
    
          if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
              Integer var18 = this.hashCode();
              return var18;
          }
    
          if (method.getDeclaringClass() != DecoratingProxy.class) {
              Object retVal;
              if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) {
                  retVal = AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
                  return retVal;
              }
    
              if (this.advised.exposeProxy) {
                  oldProxy = AopContext.setCurrentProxy(proxy);
                  setProxyContext = true;
              }
    
              //获得目标对象的类
              target = targetSource.getTarget();
              if (target != null) {
                  targetClass = target.getClass();
              }
              //获取可以应用到此方法上的Interceptor列表
              List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
                
              //判断拦截器链是否为空,如果是空的话直接调用切点方法,
              //如果拦截器不为空的话那么便创建ReflectiveMethodInvocation类,把拦截器方法都封装在里面,执行拦截器链和连接点方法
              if (chain.isEmpty()) {
                  Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
                  retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
              } else {
                  MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                  retVal = invocation.proceed();
              }
    
              Class<?> returnType = method.getReturnType();
              if (retVal != null && retVal == target && returnType != Object.class && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
                  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);
              }
    
              Object var13 = retVal;
              return var13;
          }
    
          var10 = AopProxyUtils.ultimateTargetClass(this.advised);
      } finally {
          if (target != null && !targetSource.isStatic()) {
              targetSource.releaseTarget(target);
          }
    
          if (setProxyContext) {
              AopContext.setCurrentProxy(oldProxy);
          }
    
      }
    
      return var10;
    }
    

拦截器

@Aspect
@Component
public class AopInterceptor {

    @Pointcut("execution(public * com.ck.aopTest.dao.impl.*.get*(..))")
    private void aopTest() {

    }
    @Before("aopTest()")
    public void before() {
        System.out.println("调用dao方法前拦截" + new Date().getTime());
    }
    @After("aopTest()" + "&&args(user)")
    public void after(UserModel user) {
        System.out.println(user.getName());
        System.out.println("调用dao方法之后拦截" + new Date().getTime());
    }
    @Around("aopTest()")
    public void around(ProceedingJoinPoint pdj) {
        System.out.println("调用dao之前的环绕拦截" + new Date().getTime());
        try {
            pdj.proceed();
        } catch (Throwable e) {
            e.printStackTrace();
        }
        System.out.println("调用dao之后的环绕拦截" + new Date().getTime());
    }
}

织入(AspectJ)

//ReflectiveMethodInvocation.proceed
//逐一执行拦截器链方法,执行完拦截器链后,最后执行连接点方法并返回值
protected final List<?> interceptorsAndDynamicMethodMatchers;
public Object proceed() throws Throwable {
    if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
        return this.invokeJoinpoint();
    } else {
        Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
        if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
            InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice;
            return dm.methodMatcher.matches(this.method, this.targetClass, this.arguments) ? dm.interceptor.invoke(this) : this.proceed();
        } else {
            return ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this);
        }
    }
}

Bean管理

Spring Bean是被实例的,组装的及被Spring 容器管理的Java对象。Spring容器会自动完成bean对象的实例化。创建应用对象之间的协作关系的行为称为:装配(wiring),这就是依赖注入的本质。

Bean的创建

Bean的创建过程由Spring容器对对象实例、组装的过程。
只有被注册的类型才会被Spring管理,通过@Component,@Repository,@Controller,@Service,@Configration这些注解可以将要使用的对象的类型注册到Spring容器中。
被注册的类型被实例化为对象之后,还需要通过组装将对象、属性、方法关联到一起,才能使用。属性组装时通过@Autowired(根据类型)、@Resource(根据名称)这些注解完成。

Bean的生命周期

Bean的作用域有singleton(单例)、prototype(非单例)、(session、request、global session)(不常用,Web作用域,基于Web容器(Servlet)或框架(Portlet))。

singleton(单例)

当一个bean的作用域设置为singleton, 那么Spring IOC容器中只会存在一个共享的bean实例,并且所有对bean的请求,只要id与该bean定义相匹配,则只会返回bean的同一实例。

prototype(非单例)

prototype作用域部署的bean,每一次请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法)都会产生一个新的bean实例。

不管何种作用域,容器都会调用所有对象的初始化生命周期回调方法,而对prototype而言,任何配置好的析构生命周期回调方法都将不会被调用。 清除prototype作用域的对象并释放任何prototype bean所持有的昂贵资源,都是客户端代码的职责。

事务

Spring的声明式事务管理是建立在 代理+AOP 基础上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。 大致执行流程如下:

  • 创建事务状态对象,获取一个新的连接,重置连接的autoCommit、fetchSize、timeout等属性
  • 把连接绑定到ThreadLocal变量
  • 根据传播特性配置决定是否挂起当前事务(把当前事务状态对象,连接等信息封装成SuspendedResources对象,可用于恢复)
  • 根据传播特性配置决定是否创建新的事务(创建事务状态对象,重新获取新的连接,重置新连接的autoCommit、fetchSize、timeout等属性,同时,保存SuspendedResources对象,用于事务的恢复,把新的连接绑定到ThreadLocal变量(覆盖操作))
  • 捕获到异常,回滚ThreadLocal中的连接,恢复连接参数,关闭连接,恢复SuspendedResources
  • 提交ThreadLocal变量中的连接,还原连接参数,关闭连接,连接归还数据源

其核心实现逻辑如下:

//TransactionInterceptor.invoke
//事务处理的AOP Interceptor
public Object invoke(final MethodInvocation invocation) throws Throwable {
    Class<?> targetClass = invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null;
    return this.invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {
        public Object proceedWithInvocation() throws Throwable {
            return invocation.proceed();
        }
    });
}
//TransactionAspectSupport.invokeWithinTransaction
//事务处理的核心代码
public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean {
    //事务状态对象ThreadLocal容器
    private static final ThreadLocal<TransactionAspectSupport.TransactionInfo> transactionInfoHolder = new NamedThreadLocal("Current aspect-driven transaction");
    protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final TransactionAspectSupport.InvocationCallback invocation) throws Throwable {
        final TransactionAttribute txAttr = this.getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
        final PlatformTransactionManager tm = this.determineTransactionManager(txAttr);
        final String joinpointIdentification = this.methodIdentification(method, targetClass);
        if (txAttr != null && tm instanceof CallbackPreferringPlatformTransactionManager) {
            //...
        } else {
            //创建并开始事务
            TransactionAspectSupport.TransactionInfo txInfo = this.createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
            Object retVal = null;
    
            try {
                retVal = invocation.proceedWithInvocation();
            } catch (Throwable var15) {
                this.completeTransactionAfterThrowing(txInfo, var15);
                throw var15;
            } finally {
                this.cleanupTransactionInfo(txInfo);
            }
            //提交事务
            this.commitTransactionAfterReturning(txInfo);
            return retVal;
        }
    }
}
//TransactionAspectSupport.createTransactionIfNecessary
//首先根据配置的事务传播特性取得(创建或获取)一个事务
protected TransactionAspectSupport.TransactionInfo createTransactionIfNecessary(PlatformTransactionManager tm, TransactionAttribute txAttr, final String joinpointIdentification) {
    if (txAttr != null && ((TransactionAttribute)txAttr).getName() == null) {
        txAttr = new DelegatingTransactionAttribute((TransactionAttribute)txAttr) {
            public String getName() {
                return joinpointIdentification;
            }
        };
    }

    TransactionStatus status = null;
    if (txAttr != null) {
        if (tm != null) {
            status = tm.getTransaction((TransactionDefinition)txAttr);
        } else if (this.logger.isDebugEnabled()) {
            this.logger.debug("Skipping transactional joinpoint [" + joinpointIdentification + "] because no transaction manager has been configured");
        }
    }

    return this.prepareTransactionInfo(tm, (TransactionAttribute)txAttr, joinpointIdentification, status);
}
//AbstractPlatformTransactionManager.getTransaction
public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
    //获取事务对象
    Object transaction = this.doGetTransaction();
    boolean debugEnabled = this.logger.isDebugEnabled();
    if (definition == null) {
        definition = new DefaultTransactionDefinition();
    }

    if (this.isExistingTransaction(transaction)) {
        return this.handleExistingTransaction((TransactionDefinition)definition, transaction, debugEnabled);
    } else if (((TransactionDefinition)definition).getTimeout() < -1) {
        throw new InvalidTimeoutException("Invalid transaction timeout", ((TransactionDefinition)definition).getTimeout());
    } else if (((TransactionDefinition)definition).getPropagationBehavior() == 2) {
        throw new IllegalTransactionStateException("No existing transaction found for transaction marked with propagation 'mandatory'");
    } else if (((TransactionDefinition)definition).getPropagationBehavior() != 0 && ((TransactionDefinition)definition).getPropagationBehavior() != 3 && ((TransactionDefinition)definition).getPropagationBehavior() != 6) {
        if (((TransactionDefinition)definition).getIsolationLevel() != -1 && this.logger.isWarnEnabled()) {
            this.logger.warn("Custom isolation level specified but no actual transaction initiated; isolation level will effectively be ignored: " + definition);
        }

        boolean newSynchronization = this.getTransactionSynchronization() == 0;
        return this.prepareTransactionStatus((TransactionDefinition)definition, (Object)null, true, newSynchronization, debugEnabled, (Object)null);
    } else {
        AbstractPlatformTransactionManager.SuspendedResourcesHolder suspendedResources = this.suspend((Object)null);
        if (debugEnabled) {
            this.logger.debug("Creating new transaction with name [" + ((TransactionDefinition)definition).getName() + "]: " + definition);
        }

        try {
            boolean newSynchronization = this.getTransactionSynchronization() != 2;
            DefaultTransactionStatus status = this.newTransactionStatus((TransactionDefinition)definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
            //开始事务
            this.doBegin(transaction, (TransactionDefinition)definition);
            this.prepareSynchronization(status, (TransactionDefinition)definition);
            return status;
        } catch (RuntimeException var7) {
            this.resume((Object)null, suspendedResources);
            throw var7;
        } catch (Error var8) {
            this.resume((Object)null, suspendedResources);
            throw var8;
        }
    }
}
//DataSourceTransactionManager.doGetTransaction
//获取事务状态对象
protected Object doGetTransaction() {
    DataSourceTransactionManager.DataSourceTransactionObject txObject = new DataSourceTransactionManager.DataSourceTransactionObject();
    txObject.setSavepointAllowed(this.isNestedTransactionAllowed());
    ConnectionHolder conHolder = (ConnectionHolder)TransactionSynchronizationManager.getResource(this.dataSource);
    txObject.setConnectionHolder(conHolder, false);
    return txObject;
}
//DataSourceTransactionManager.doBegin
//开始事务
protected void doBegin(Object transaction, TransactionDefinition definition) {
    DataSourceTransactionManager.DataSourceTransactionObject txObject = (DataSourceTransactionManager.DataSourceTransactionObject)transaction;
    Connection con = null;

    try {
        if (txObject.getConnectionHolder() == null || txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
            Connection newCon = this.dataSource.getConnection();
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
            }

            txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
        }

        txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
        con = txObject.getConnectionHolder().getConnection();
        Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
        txObject.setPreviousIsolationLevel(previousIsolationLevel);
        if (con.getAutoCommit()) {
            txObject.setMustRestoreAutoCommit(true);
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
            }

            con.setAutoCommit(false);
        }

        txObject.getConnectionHolder().setTransactionActive(true);
        int timeout = this.determineTimeout(definition);
        if (timeout != -1) {
            txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
        }

        if (txObject.isNewConnectionHolder()) {
            TransactionSynchronizationManager.bindResource(this.getDataSource(), txObject.getConnectionHolder());
        }

    } catch (Throwable var7) {
        if (txObject.isNewConnectionHolder()) {
            DataSourceUtils.releaseConnection(con, this.dataSource);
            txObject.setConnectionHolder((ConnectionHolder)null, false);
        }

        throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", var7);
    }
}
//TransactionAspectSupport.commitTransactionAfterReturning
//提交事务
protected void commitTransactionAfterReturning(TransactionAspectSupport.TransactionInfo txInfo) {
    if (txInfo != null && txInfo.hasTransaction()) {
        if (this.logger.isTraceEnabled()) {
            this.logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "]");
        }

        txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
    }
}
//DataSourceTransactionManager.doCommit
protected void doCommit(DefaultTransactionStatus status) {
    DataSourceTransactionManager.DataSourceTransactionObject txObject = (DataSourceTransactionManager.DataSourceTransactionObject)status.getTransaction();
    Connection con = txObject.getConnectionHolder().getConnection();
    if (status.isDebug()) {
        this.logger.debug("Committing JDBC transaction on Connection [" + con + "]");
    }

    try {
        con.commit();
    } catch (SQLException var5) {
        throw new TransactionSystemException("Could not commit JDBC transaction", var5);
    }
}

事务的传播特性

  • PROPAGATION_REQUIRED(常用)
    • 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。
  • PROPAGATION_REQUIRES_NEW(常用)
    • 新建事务,如果当前存在事务,把当前事务挂起。
  • PROPAGATION_NESTED(常用)
    • 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。
  • PROPAGATION_SUPPORTS
    • 支持当前事务,如果当前没有事务,就以非事务方式执行。
  • PROPAGATION_MANDATORY
    • 使用当前的事务,如果当前没有事务,就抛出异常。
  • PROPAGATION_NOT_SUPPORTED
    • 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
  • PROPAGATION_NEVER
    • 以非事务方式执行,如果当前存在事务,则抛出异常。

      【整理中】扩展

参考文献

1000行代码读懂Spring(一)- 实现一个基本的IoC容器
Spring:源码解读Spring IOC原理
Spring多种加载Bean方式简析
Spring技术内幕——深入解析Spring架构与设计原理(二)AOP
Spring 框架的设计理念与设计模式分析
BeanPostProcessor与AB测试
Spring思维导图,让spring不再难懂(一)
Spring思维导图,让Spring不再难懂(ioc篇)
Spring思维导图,让Spring不再难懂(aop篇)
Spring事务-说说Propagation及其实现原理