springboot事务必要组件和过程:
1.注册事务管理器DatasouceTransactionManager
2.注册事务增强器BeanFactoryTransactionAttributeSourceAdvisor,里面包含事务拦截器TransactionInterceptor
3.注册事务注解解析用的后置处理器AnnotationAwareAspectJAutoProxyCreator,里面用来生成代理对象
4.通过代理对象调用方法,会先走代理对象的invoke()方法,通过事务拦截器来开启事务,执行目标方法,提交或回滚事务
一、注入BeanFactoryTransactionAttributeSourceAdvisor和TransactionInterceptor和DatasouceTransactionManager
1.注册DatasouceTransactionManager
通过springboot的spi机制,在DataSourceTransactionManagerAutoConfiguration中的DataSourceTransactionManagerConfiguration中,通过@Bean的方式注入了DataSourceTransactionManager到spring容器
2.注入BeanFactoryTransactionAttributeSourceAdvisor和TransactionInterceptor
扫描spring-boot-autoconfigure依赖包下的META-INF/spring.factories,加载文件里的TransactionAutoConfiguration类,可以看到sringboot在2.0之后默认使用了cglib代理,下面将的是jdk的代理,原理是一样的
解析TransactionAutoConfiguration类里的@EnableTransactionManagement注解,根据该注解上的@Import加载TransactionManagementConfigurationSelector类
通过TransactionManagementConfigurationSelector类的selectImports方法加载ProxyTransactionManagementConfiguration类
ProxyTransactionManagementConfiguration类通过@Bean加载BeanFactoryTransactionAttributeSourceAdvisor类,该类实现了Pointcut,并且在该类里注入了实现了Advise接口的TransactionInterceptor类,TransactionInterceptor就是事务拦截器。
这里setTransactionManager其实是一个null,后面拿事务管理器时是从单例池中拿,不是用的这个。
另外要提一点的是很多类中之所以可以用到BeanFactory(DefaultListableBeanFactory),是因为实现了BeanFactoryAware,spring在初始化bean的时候会将beanFactory设置进去
二、注入AnnotationAwareAspectJAutoProxyCreator切面解析处理器
通过spi机制自动装载AopAutoConfiguration类,加载AopAutoConfiguration类,根据proxyTargetClass配置来选择是使用jdk的proxy还是cglib来生成动态代理类,截图如下:
解析@EnableAspectJAutoProxy注解,通过该注解上的@Import加载AspectJAutoProxyRegistrar类
AspectJAutoProxyRegistrar类会向Spring容器注册AnnotationAwareAspectJAutoProxyCreator类,该类实现了BeanPostProcessor接口,所以这个aop逻辑是在Springbean生成过程中通过后置处理器逻辑来实现的。
AnnotationAwareAspectJAutoProxyCreator继承AspectJAwareAdvisorAutoProxyCreator继承AbstractAdvisorAutoProxyCreator继承AbstractAutoProxyCreator实现BeanFactoryAware,
因为AnnotationAwareAspectJAutoProxyCreator最顶层实现了BeanFactoryAware所以初始化时需要调用AbstractAdvisorAutoProxyCreator的setBeanFactory方法,就会走下图的逻辑,就会走this.initBeanFactory逻辑,
其实就是调用了子类AnnotationAwareAspectJAutoProxyCreator的initBeanFactory方法,然后调用super.initBeanFactory方法
也就是调用了AbstractAdvisorAutoProxyCreator的initBeanFactory方法,这个方法里面初始化了this.advisorRetrievalHelper = new BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory);
后面会有一句代码叫this.advisorRetrievalHelper.findAdvisorBeans()。所以要知道this.advisorRetrievalHelper就是在这里初始化的
三、事务注解解析和代理生成过程
前面的步骤暂时省略了,这里只分析从开始走后置处理器的逻辑
AnnotationAwareAspectJAutoProxyCreator
执行AnnotationAwareAspectJAutoProxyCreator的父类AbstractAutoProxyCreator的postProcessAfterInitialzation方法
this.wrapIfNecessary()方法就是要进行生成代理了
this.getAdvicesAndVisorsForBean调用的是AbstractAutoProxyCreator子类AbstractAdvisorAutoProxyCreator中的
ProxyTransactionManagementConfiguration中通过@Bean注册的BeanFactoryTransactionAttributeSourceAdvisor名称就叫做"org.springframework.transaction.config.internalTransactionAdvisor",所以下面传入一个DefaultListableBeanFactory和Avisor.class,从spring容器中查找Avisor类型的bean,然后获取它们的名称,advisorNames就包含了"org.springframework.transaction.config.internalTransactionAdvisor",下面就通过name和Advisor.class获取对应的BeanFactoryTransactionAttributeSourceAdvisor事务增强器
那么candidateAdvisors中包含从spring容器中获取出来的所有增强器,candidateAdvisors之所以是一个集合,是因为容器中是Advisor.class类型的bean可能不止是BeanFactoryTransactionAttributeSourceAdvisor,下图中就是还有一个Druid连接池sql监控的增强器
然后通过传入目标beanName和beanClass筛选出属于本类需要的增强器,如果你的类或者方法上有@Transactional注解,那么返回的eligibleAdvisors中就有BeanFactoryTransactionAttributeSourceAdvisor,
AopUtils#canApply(Pointcut, Class , boolean) 方法中会调用到 TransactionAttributeSourcePointcut#matches 方法
BeanFactoryTransactionAttributeSourceAdvisor继承了PoincutAdvisor
canApply中会调用BeanFactoryTransactionAttributeSourceAdvisor.getPointCut()返回一个TransactionAttributeSourcePointcut
然后pointcut再调用getMethodMatcher()返回一个MethodMatcher也就是TransactionAttributeSourcePointcut自己,因为getMethodMatcher()是在父类StaticMethodMatcherPointcut中调用的,而父类StaticMethodMatcherPointcut继承了StaticMethodMatcher继承了MethodMatcher,所以TransactionAttributeSourcePointcut也是一个MethodMatcher。
TransactionAttributeSourcePointcut#getTransactionAttributeSource 返回的是:AnnotationTransactionAttributeSource 实例,AnnotationTransactionAttributeSource继承自:AbstractFallbackTransactionAttributeSource, 故此TransactionAttributeSourcePointcut#matches 最终会调用到 AbstractFallbackTransactionAttributeSource#getTransactionAttribute 方法
SringTransactionAnnotationParser实在下图中被创建的
以上是this.getAdvicesAndAdvisorForBean方法内部调用过程,调用完该方法出来后,回到下图中创建代理对象this.createProxy
Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);返回指定的拦截器
this.createAopProxy就是创建一个JdkDynamicAopProxy代理对象(jdk代理为例子),JdkDynamicAopProxy继承了InvocationHandler
那么将来通过controller调用某个service的某个加了@Transactional的方法,就会首先进入invoke方法进行拦截
invoke方法中会执行下面一段,chain就是根据method把所需要的拦截器拿出来,因为拦截器已经在之前的操作this.createAopProxy中设置进了成员属性advised,所以这里可以通过this.advised.getInterceptorsAndDynamicInterceptionAdvice拿出来,例如method加了@Transactional,那么chain中就会包含BeanFactoryTransactionAttributeSourceAdvisor#TransactionInterceptor。如果说chain是空的,那么就会直接通过反射调用原始bean的方法,那就没有事务。
下面调用的就是拦截器的invoke方法
那么其中的一个拦截器TransactionInterceptor的invoke方法就会被调用,就是开启事务的逻辑了,逻辑如下