警告
本文最后更新于 2020-12-03,文中内容可能已过时。
spring源码系列文章,示例代码的中文注释,均是 copy 自 https://gitee.com/wlizhi/spring-framework 。
链接中源码是作者从 github 下载,并以自身理解对核心流程及主要节点做了详细的中文注释。
事务以xml配置方式使用时,xml是怎么解析,并将事务功能注册到容器中的?注解方式启动时,是怎么扫描注解将事务功能注册到容器中的?本文给出了详细的解析。
1 Xml方式
xml方式开启事务注解,是使用 <tx:annotation-driven/>
标签。根据 SPI 加载的规律,找到 spring-tx
包下的 spring.handlers
文件。
内容如下:
1
http\://www.springframework.org/schema/tx=org.springframework.transaction.config.TxNamespaceHandler
在 TxNamespaceHandler.init() 中,注册了事务相关标签的解析支持。
init() 源码如下:
1
2
3
4
5
6
7
8
9
10
public class TxNamespaceHandler extends NamespaceHandlerSupport {
public void init () {
// advice通知方法有关的,<tx:advice /> <tx:attributes /> <tx:method /> 标签支持在这里。
registerBeanDefinitionParser ( "advice" , new TxAdviceBeanDefinitionParser ());
// <tx:annotation-driven /> 解析支持
registerBeanDefinitionParser ( "annotation-driven" , new AnnotationDrivenBeanDefinitionParser ());
// 可以不看。
registerBeanDefinitionParser ( "jta-transaction-manager" , new JtaTransactionManagerBeanDefinitionParser ());
}
}
着重看 <tx:annotation-driven />
标签的解析类,<tx:advice />
解析支持原理类似。
直接来到方法 parse():
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
public BeanDefinition parse ( Element element , ParserContext parserContext ) {
// 当前方法注册了InfrastructureAdvisorAutoProxyCreator Infrastructure-->基础设施,优先级最低。
// 注意:区分@Aspect以及<aop:aspectj-autoproxy/>:两者注册的是AnnotationAwareAspectJAutoProxyCreator,最终按照优先级来确定使用哪个的。
// 注册事务事件监听器,@TransactionalEventListener注解的支持。可以不看。
registerTransactionalEventListenerFactory ( parserContext );
String mode = element . getAttribute ( "mode" );
// 根据mode的值,来确定注册哪种类型的事务支持。这个不常用,可以不看。着重看else里面的内容。
if ( "aspectj" . equals ( mode )) {
// mode="aspectj"
registerTransactionAspect ( element , parserContext );
if ( ClassUtils . isPresent ( "javax.transaction.Transactional" , getClass (). getClassLoader ())) {
registerJtaTransactionAspect ( element , parserContext );
}
}
else {
// TODO 默认值是proxy,主要看这个。
// mode="proxy"
AopAutoProxyConfigurer . configureAutoProxyCreator ( element , parserContext );
}
return null ;
}
}
代码第一行注册了事务的事件监听,可以不看。
实际开发中,mode 属性基本不会配置,直接略过。默认值是 proxy。也就是说,会走到else代码块中。重点看 configureAutoProxyCreator()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
private static class AopAutoProxyConfigurer {
public static void configureAutoProxyCreator ( Element element , ParserContext parserContext ) {
// TODO 注册Advisor
AopNamespaceUtils . registerAutoProxyCreatorIfNecessary ( parserContext , element );
// 这里是一个常量,事务Advisor,等后面实例化时,如果匹配到方法,Advisor会封装到代理对象的执行链里面。
String txAdvisorBeanName = TransactionManagementConfigUtils . TRANSACTION_ADVISOR_BEAN_NAME ;
if ( ! parserContext . getRegistry (). containsBeanDefinition ( txAdvisorBeanName )) {
Object eleSource = parserContext . extractSource ( element );
// 创建AnnotationTransactionAttributeSource的BeanDefinition,这是一个策略接口的实现。用于获取事务注解的属性值。
// Create the TransactionAttributeSource definition.
RootBeanDefinition sourceDef = new RootBeanDefinition (
"org.springframework.transaction.annotation.AnnotationTransactionAttributeSource" );
sourceDef . setSource ( eleSource );
sourceDef . setRole ( BeanDefinition . ROLE_INFRASTRUCTURE );
String sourceName = parserContext . getReaderContext (). registerWithGeneratedName ( sourceDef );
// 创建对应的MethodInterceptor,这是事务的方法拦截器,最终在生成代理的时候,会缓存到AdvisedSupport中,第一次调用执行生成执行链的时候,
// 如果匹配对应的方法,就会将方法名-MethodInterceptor的映射关系存储到执行链。同样是缓存到AdvisedSupport中。
// Create the TransactionInterceptor definition.
RootBeanDefinition interceptorDef = new RootBeanDefinition ( TransactionInterceptor . class );
interceptorDef . setSource ( eleSource );
interceptorDef . setRole ( BeanDefinition . ROLE_INFRASTRUCTURE );
// 注意,这里只注入了一个名字,PlatformTransactionManager需要我们手动注入到容器,在创建TransactionInterceptor时,会通过getBean()来获取
registerTransactionManager ( element , interceptorDef );
interceptorDef . getPropertyValues (). add ( "transactionAttributeSource" , new RuntimeBeanReference ( sourceName ));
String interceptorName = parserContext . getReaderContext (). registerWithGeneratedName ( interceptorDef );
// 创建BeanFactoryTransactionAttributeSourceAdvisor的BeanDefinition,并注册到registry中。当bean在实例化,
// 查找容器中所有的增强方法时,会对所有的@Aspect封装成Advisor并实例化,以及直接注入进来的Advisor提前实例化,缓存到AdvisedSupport中。
// 从接口层面说,这里创建一个Advisor。
// Create the TransactionAttributeSourceAdvisor definition.
RootBeanDefinition advisorDef = new RootBeanDefinition ( BeanFactoryTransactionAttributeSourceAdvisor . class );
advisorDef . setSource ( eleSource );
advisorDef . setRole ( BeanDefinition . ROLE_INFRASTRUCTURE );
advisorDef . getPropertyValues (). add ( "transactionAttributeSource" , new RuntimeBeanReference ( sourceName ));
advisorDef . getPropertyValues (). add ( "adviceBeanName" , interceptorName );
if ( element . hasAttribute ( "order" )) {
advisorDef . getPropertyValues (). add ( "order" , element . getAttribute ( "order" ));
}
parserContext . getRegistry (). registerBeanDefinition ( txAdvisorBeanName , advisorDef );
// 剩余源码省略 ...
}
}
}
从上面源码中可以看到,分别注册了 TransactionAttributeSource
、MethodInterceptor(也是Advice)
、Advisor
的BeanDefinition对象,其中后面两个是利用AOP模块功能生成动态代理的关键接口。
而 TransactionAttributeSource
是对事务属性解析的支持。
这些动作是在解析标签的时候做的,然后经历 BeanFactoryPostProcessor 的后置方法执行、以及 BeanPostProcessor 的注册之后,最终执行到将BeanDefinition中封装的类信息实例化时,会创建上面源码中注册的三个实例。
而在创建实例、依赖注入、执行完bean的初始化方法后,最终会执行到 BeanPostProcessor.postProcessAfterInitialization(),而 AbstractAutoProxyCreator(也是一个BeanPostProcessor) 的子类(激活了自动代理功能),
会搜集beanDefinitions中所有的Advisor类型的beanDefinition,对其实例化,封装到AdvisedSupport中,如果对象需要被代理,则会将AdvisedSupport封装到代理对象中。最终在调用代理对象方法的时候,会生成代理方法的执行链。
由于 TransactionInterceptor 实现了 InitializingBean。在bean实例化完成后,会调用 afterPropertiesSet(),来看一下这个方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public abstract class TransactionAspectSupport implements BeanFactoryAware , InitializingBean {
@Override
public void afterPropertiesSet () {
// 开启事务支持,那么PlatformTransactionManager和TransactionAttributeSource这两个实例是必须有的,否则启动就会抛出异常。
if ( getTransactionManager () == null && this . beanFactory == null ) {
throw new IllegalStateException (
"Set the 'transactionManager' property or make sure to run within a BeanFactory " +
"containing a PlatformTransactionManager bean!" );
}
if ( getTransactionAttributeSource () == null ) {
throw new IllegalStateException (
"Either 'transactionAttributeSource' or 'transactionAttributes' is required: " +
"If there are no transactional methods, then don't use a transaction aspect." );
}
}
}
从源码中可以看到,如果开启了事务功能,PlatformTransactionManager、TransactionAttributeSource是必不可少的,否则容器启动就会抛出异常。
而在上面源码中,TransactionAttributeSource已经设置了,而PlatformTransactionManager只注册了一个beanName,
这需要我们指定注入到ioc容器中。例如传统spring项目中使用的 DataSourceTransactionManager 就是使用bean标签注入的。
题外话:之所以 springboot 中我们不用创建 PlatformTransactionManager,是因为 auto-configuration 模块,使用 SPI 的方式,导入了 DataSourceTransactionManagerAutoConfiguration。
从下面代码就可以看出,TransactionInterceptor中仅仅注册了一个PlatformTransactionManager的beanName:
1
2
3
4
5
6
class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
private static void registerTransactionManager ( Element element , BeanDefinition def ) {
def . getPropertyValues (). add ( "transactionManagerBeanName" ,
TxNamespaceHandler . getTransactionManagerName ( element ));
}
}
2 注解方式
在使用注解方式激活@Transaction支持时,使用的是@EnableTransactionManagement,在这个注解声明中可以看到,使用了@Import导入TransactionManagementConfigurationSelector。
源码如下:
1
2
3
4
5
6
7
8
@Target ( ElementType . TYPE )
@Retention ( RetentionPolicy . RUNTIME )
@Documented
// TODO 重点:事务注册入口类
@Import ( TransactionManagementConfigurationSelector . class )
public @interface EnableTransactionManagement {
// 省略...
}
在spring容器启动时,就会加载TransactionManagementConfigurationSelector,调用 selectImports(),在这个方法中,就添加了两个类的支持。
selectImports() 源码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector < EnableTransactionManagement > {
@Override
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 ;
}
}
}
从上面源码中可以看到,共添加了两个类,主要看 ProxyTransactionManagementConfiguration 这个类。
在这个类中,定义了三个方法,使用@Bean,向容器中注入了BeanFactoryTransactionAttributeSourceAdvisor、TransactionInterceptor、AnnotationTransactionAttributeSource。这三个分别是Advisor、Advice(MethodInterceptor)、TransactionAttributeSource的实现类。
源码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
@Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
@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 . < Integer > getNumber ( "order" ));
}
return advisor ;
}
@Bean
@Role ( BeanDefinition . ROLE_INFRASTRUCTURE )
public TransactionAttributeSource transactionAttributeSource () {
// TODO 事务属性解析类
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 ;
}
}
xml方式注入中,也是像容器中注入了这几个类。同样创建的流程也都是一样的。
接着看一下 AnnotationTransactionAttributeSource,在创建实例的时候,封装了对@Transactional的支持。
来到构造方法源码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class AnnotationTransactionAttributeSource extends AbstractFallbackTransactionAttributeSource
implements Serializable {
// 步骤一
public AnnotationTransactionAttributeSource () {
this ( true );
}
// 步骤二
public AnnotationTransactionAttributeSource ( boolean publicMethodsOnly ) {
// 这里注入了注解解析类。 SpringTransactionAnnotationParser,解析时就用到的这个类中的方法
this . publicMethodsOnly = publicMethodsOnly ;
if ( jta12Present || ejb3Present ) {
this . annotationParsers = new LinkedHashSet <> ( 4 );
// TODO 重点看这里
this . annotationParsers . add ( new SpringTransactionAnnotationParser ());
if ( jta12Present ) {
this . annotationParsers . add ( new JtaTransactionAnnotationParser ());
}
if ( ejb3Present ) {
this . annotationParsers . add ( new Ejb3TransactionAnnotationParser ());
}
}
else {
this . annotationParsers = Collections . singleton ( new SpringTransactionAnnotationParser ());
}
}
}
在构造方法中,封装了SpringTransactionAnnotationParser对象。
这个类是对@Transactional注解的支持,在bean实例化完成之后,调用代理方法执行时,首先会生成执行链,然后按照索引顺序递归调用执行链。
在调用到事务的节点时,会获取事务属性对象,通过事务属性来被代理方法中@Transactional注解中配置的属性值。以此来判断是否开启事务、以及设置事务隔离级别、传播行为等属性值。
SpringTransactionAnnotationParser中具体有哪些方法,执行了哪些行为,在声明式事务执行流程源码分析中会详细列出。