上回说到,使用事务的模板TransactionTemplate可以极大地减少我们使用事务时的工作,我们只需将我们的业务逻辑写到TransactionCallback接口方法中即可。
使用TransactionTemplate虽然帮我们省略了一些相同的操作,但是每次数据库操作都要写到TransactionCallback中,也业务逻辑还不是分离的。这就引出了AOP代理。
要将Spring AOP和事务结合起来,也有很多的表现形式,但原理都是一样的。
最简单的莫过于在Configuration类中增加@EnableTransactionManagement,Spring将标注有@Transactional的对象创建出代理对象。
生成beanDefinition
在Configuration类中增加了@EnableTransactionManagement,Spring启动时在解析Configuration时
调用invokeBeanFactoryPostProcessors生成beanDefinition
invokeBeanFactoryPostProcessors ->PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors ->invokeBeanDefinitionRegistryPostProcessors ->ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(registry) ->processConfigBeanDefinitions(registry) ->ConfigurationClassParser.parse(candidates) ->processConfigurationClass(configClass) ->doProcessConfigurationClass(configClass, sourceClass)
invokeBeanDefinitionRegistryPostProcessors
在处理Import注释时,我们知道@EnableTransactionManagement中加了注释@Import(TransactionManagementConfigurationSelector.class),因此会调用ConfigurationClassParser.processImports。
1 | private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass, |
importCandidates里传入的是TransactionManagementConfigurationSelector。
可以看到,因为传入的TransactionManagementConfigurationSelector是ImportSelector的子类,于是首先调用AdviceModeImportSelector.selectImports获取需要导入的类,能看到是org.springframework.context.annotation.AutoProxyRegistrar和org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration。然后递归调用processImports。
接着看AutoProxyRegistrar,它是ImportBeanDefinitionRegistrar的子类。调用ParserStrategyUtils.invokeAwareMethods执行实现的Aware接口。然后调用configClass.addImportBeanDefinitionRegistrar在config类中增加importBeanDefinitionRegistrar。
接着看ProxyTransactionManagementConfiguration,它既不是ImportSelector类也不是ImportBeanDefinitionRegistrar类,于是进入else代码块,调用processConfigurationClass,将它作为一个配置类来处理。
查看ProxyTransactionManagementConfiguration类的代码,我们可以看到ProxyTransactionManagementConfiguration被@Configuraion注释,它还新建了3个bean:BeanFactoryTransactionAttributeSourceAdvisor、TransactionAttributeSource、TransactionInterceptor。
loadBeanDefinitions
回到ConfigurationClassPostProcessor.processConfigBeanDefinitions方法,经过parser.parse的解析,configClasses中包含了我们自定义的Configuration类以及ProxyTransactionManagementConfiguration,还包含通过ComponentScan扫描得到的类。
调用ConfigurationClassBeanDefinitionReader.loadBeanDefinitions:
- 加载自定义Configuration类中定义bean的beanDefinition。之前在importBeanDefinitionRegistrar中添加了
AutoProxyRegistrar,因此调用registerBeanDefinitions方法注册了InfrastructureAdvisorAutoProxyCreator - 加载
ProxyTransactionManagementConfiguration以及其中四个bean(BeanFactoryTransactionAttributeSourceAdvisor、TransactionAttributeSource、TransactionInterceptor、TransactionalEventListenerFactory)的beanDefinition。
invokeBeanFactoryPostProcessors
调用ConfigurationClassPostProcessor.postProcessBeanFactory:
- 使用cglib对Configuration类进行增强
- 增加一个
ImportAwareBeanPostProcessor
注册beanPostProcessors
在调用registerBeanPostProcessors之前,beanFactory的beanPostProcessors中有三个beanPostProcessor:
- ApplicationContextAwareProcessor
- ApplicationListenerDetector
- ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor
在调用invokeBeanFacotryPostProcessors之后,调用registerBeanPostProcessors注册beanPostProcessor。注册完之后beanFactory的beanPostProcessors中有8个beanPostProcessor:
- ApplicationContextAwareProcessor
- ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor
- PostProcessorRegistrationDelegate$BeanPostProcessorChecker
- InfrastructureAdvisorAutoProxyCreator
- CommonAnnotationBeanPostProcessor
- AutowiredAnnotationBeanPostProcessor
- RequiredAnnotationBeanPostProcessor
- ApplicationListenerDetector
创建bean并初始化
与AOP代理类相同,bean创建工作在DefaultListableBeanFactory.doCreateBean中完成:
- 调用
AbstractAutowireCapableBeanFactory.createBeanInstance创建bean实例。 - 调用
AbstractAutowireCapableBeanFactory.populateBean填充bean实例。 - 调用
AbstractAutowireCapableBeanFactory.initializeBean初始化bean实例
在initializeBean方法中,调用applyBeanPostProcessorsAfterInitialization,它调用各个beanPostProcessor的postProcessAfterInitialization。
重点是InfrastructureAdvisorAutoProxyCreator,它创建了使用事务的类的代理类。
AbstractAutoProxyCreator.postProcessAfterInitialization ->AbstractAutoProxyCreator.wrapIfNecessary ->
在AbstractAutoProxyCreator.wrapIfNecessary方法中:
1 | Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); |
寻找拦截器
Spring通过调用AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean方法来获取某个bean的所有advice。它实际调用的是AbstractAdvisorAutoProxyCreator.findEligibleAdvisors方法,为这个类寻找合适的advice。主要流程如下:
- 调用
AbstractAdvisorAutoProxyCreator.findCandidateAdvisors()方法寻找所有的advisor。其中会在Spring容器里寻找名称为org.springframework.transaction.config.internalTransactionAdvisor的bean对象,返回的是一个BeanFactoryTransactionAttributeSourseAdvisor类对象,它用于在一个使用事务的方法中加入事务通知。 调用
AbstractAdvisorAutoProxyCreator.findAdvisorsThatCanApply()方法在所有advisor中筛选适合这个类对象的advisor。它实际调用的是
AopUtils.canApply方法来确定advisor的pointcut是否能匹配这个类对象,原理如下:- 调用Pointcut的
getMethodMatcher方法获取MethodMatcher对象。该对象是Pointcut的一部分,用于判断目标方法是否匹配advice。 - 获取目标对象的所有的方法,然后遍历这些方法,调用
BeanFactoryTransactionAttributeSourseAdvisor父类TransactionAttributeSourcePointcut的matches方法来判断目标方法是否匹配Pointcut。其原理是通过是否能在目标方法的注释中找到事务属性(TransactionAttribute)来判断是否匹配Pointcut。
- 调用Pointcut的
创建代理类
通过getAdvicesAndAdvisorsForBean方法找到一个拦截器BeanFactoryTransactionAttributeSourceAdvisor。因此需要创建一个代理类:
- 调用
DefaultAopProxyFactory.createAopProxy来创建一个AopProxy - 调用
CglibAopProxy.getProxy来获取一个代理类
代理类中加入了DynamicAdvisedInterceptor、StaticUnadvisedInterceptor、SerializableNoOp、StaticDispatcher、AdvisedDispatcher、EqualsInterceptor、HashCodeInterceptor等一系列的拦截器。
执行@Transactional注释的方法
当调用@Transactional注释的方法时,调用的是DynamicAdvisedInterceptor.intercept。
首先执行AdvisedSupport.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass)获取拦截器列表。调用流程如下:
- DefaultAdvisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice
- DefaultAdvisorAdapterRegistry.getInterceptors方法返回TransactionInterceptor
获取到的拦截器链中有TransactionInterceptor。
接着新建CglibMethodInvocation对象,执行ReflectiveMethodInvocation.proceed方法
1 | public Object proceed() throws Throwable { |
其中interceptorOrInterceptionAdvice中获得的拦截器是TransactionInterceptor,然后执行到((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this)语句,进入TransactionInterceptor.invoke,然后进入TransactionAspectSupport.invokeWithinTransaction。
1 | ... |
调用createTransactionIfNecessary创建事务:
1 | protected TransactionInfo createTransactionIfNecessary( |
调用tm.getTransaction获取事务状态,具体可以参考Spring与事务(一)。
接着调用prepareTransactionInfo封装一个事务信息的对象。
回到TransactionAspectSupport.invokeWithinTransaction方法,调用createTransactionIfNecessary根据需要创建一个事务之后,再调用回调函数:invocation.proceedWithInvocation调用用户代码,进入ReflectiveMethodInvocation.proceed,:
1 | public Object proceed() throws Throwable { |
调用invokeJoinPoint执行用户的业务代码:
1 | protected Object invokeJoinpoint() throws Throwable { |
回到TransactionAspectSupport.invokeWithinTransaction方法。如果invocation.proceedWithInvocation执行成功,则调用commitTransactionAfterReturning提交事务;否则调用completeTransactionAfterThrowing回滚事务。