事务声明原理
# EnableTransactionManagement注解
类似AOP原理 (opens new window)从注解EnableTransactionManagement
入手
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
//当选择代理模式AdviceMode.PROXY时 用来指定是否直接使用CGLIB代理 true:直接使用CGLIB创建子类代理,false: 实现接口的可以使用JDK动态代理
boolean proxyTargetClass() default false;
//切面模式 AdviceMode.PROXY:代理模式,本地调用会出现拦截失效(类方法调用自己的另一个方法),AdviceMode.ASPECTJ本地调用不会拦截时效
AdviceMode mode() default AdviceMode.PROXY;
//当有多个切面方法时,事务的切面方法最后执行
int order() default Ordered.LOWEST_PRECEDENCE;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Import (opens new window)导入TransactionManagementConfigurationSelector
在加载BeanDefinition
的时候会调用ImportSelector.selectImports(AnnotationMetadata)
方法
TransactionManagementConfigurationSelector
的selectImports(AdviceMode adviceMode)
是一个重载方法,所以会先调到AdviceModeImportSelector.selectImports(AnnotationMetadata)
public final String[] selectImports(AnnotationMetadata importingClassMetadata) {
//获取AdviceModeImportSelector<A extends Annotation>的参数化类型 既A的类型EnableTransactionManagement
Class<?> annType = GenericTypeResolver.resolveTypeArgument(getClass(), AdviceModeImportSelector.class);
Assert.state(annType != null, "Unresolvable type argument for AdviceModeImportSelector");
//从元数据中获取属于EnableTransactionManagement的参数
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
if (attributes == null) {
throw new IllegalArgumentException(String.format(
"@%s is not present on importing class '%s' as expected",
annType.getSimpleName(), importingClassMetadata.getClassName()));
}
//获取增强模式
AdviceMode adviceMode = attributes.getEnum(getAdviceModeAttributeName());
//调用留给之类实现的方法
String[] imports = selectImports(adviceMode);
if (imports == null) {
throw new IllegalArgumentException("Unknown AdviceMode: " + adviceMode);
}
return imports;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
TransactionManagementConfigurationSelector.selectImports
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;
}
}
2
3
4
5
6
7
8
9
10
11
以代理模式为例,spring会对返回的AutoProxyRegistrar
和ProxyTransactionManagementConfiguration
继续执行Import
解析。
# 事务自动代理框架
在处理AutoProxyRegistrar
时,由于该类实现了ImportBeanDefinitionRegistrar
接口,在解析BeanDefinition时会调用registerBeanDefinitions
方法
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean candidateFound = false;
Set<String> annTypes = importingClassMetadata.getAnnotationTypes();
for (String annType : annTypes) {
//从元数据中获取属于EnableTransactionManagement的参数
AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
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;
}
}
}
}
//...
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
AopConfigUtils.registerAutoProxyCreatorIfNecessary
public static BeanDefinition registerAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}
2
3
4
注册一个自动代理类InfrastructureAdvisorAutoProxyCreator
这里对比一下 AOP原理 (opens new window)注册的BeanDefinition类型是AnnotationAwareAspectJAutoProxyCreator
,继承关系大致相同,都是用来实现自动代理功能。
那么会不会有两套代理框架,导致功能重复呢?
答案在registerOrEscalateApcAsRequired
方法中
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
//是否已经注册过org.springframework.aop.config.internalAutoProxyCreator的BeanDefinition
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
//注册过的话,比较优先级,保证只注册一个
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
//注册的BeanDefinition类名为org.springframework.aop.config.internalAutoProxyCreator
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
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
AopConfigUtils.findPriorityForClass
private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<>(3);
static {
// Set up the escalation list...
APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
}
private static int findPriorityForClass(@Nullable String className) {
for (int i = 0; i < APC_PRIORITY_LIST.size(); i++) {
Class<?> clazz = APC_PRIORITY_LIST.get(i);
if (clazz.getName().equals(className)) {
return i;
}
}
throw new IllegalArgumentException(
"Class name [" + className + "] is not a known auto-proxy creator class");
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
优先级InfrastructureAdvisorAutoProxyCreator
>AspectJAwareAdvisorAutoProxyCreator
>AnnotationAwareAspectJAutoProxyCreator
# 事务自动代理的切面
在处理ProxyTransactionManagementConfiguration
时,该类不是ImportSelector.class
类型也不是ImportBeanDefinitionRegistrar
类型,按配置类处理
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
//org.springframework.transaction.config.internalTransactionAdvisor 通知Bean
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {
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() {
//这里使用的是针对注解类型的事务配置Bean
return new AnnotationTransactionAttributeSource();
}
//拦截方法,传入事务配置,事务的通知方法,
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {
TransactionInterceptor interceptor = new TransactionInterceptor();
interceptor.setTransactionAttributeSource(transactionAttributeSource);
if (this.txManager != null) {
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
}
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
@Configuration
public abstract class AbstractTransactionManagementConfiguration implements ImportAware {
// ...
//实现ImportAware 的接口方法 主要作用是拿到`@EnableTransactionManagement`的配置
@Override
public void setImportMetadata(AnnotationMetadata importMetadata) {
this.enableTx = AnnotationAttributes.fromMap(
importMetadata.getAnnotationAttributes(EnableTransactionManagement.class.getName(), false));
if (this.enableTx == null) {
throw new IllegalArgumentException("@EnableTransactionManagement is not present on importing class " + importMetadata.getClassName());
}
}
//注入事务管理器
@Autowired(required = false)
void setConfigurers(Collection<TransactionManagementConfigurer> configurers) {
if (CollectionUtils.isEmpty(configurers)) {
return;
}
if (configurers.size() > 1) {
throw new IllegalStateException("Only one TransactionManagementConfigurer may exist");
}
TransactionManagementConfigurer configurer = configurers.iterator().next();
this.txManager = configurer.annotationDrivenTransactionManager();
}
//事务监听器
@Bean(name = TransactionManagementConfigUtils.TRANSACTIONAL_EVENT_LISTENER_FACTORY_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public static TransactionalEventListenerFactory transactionalEventListenerFactory() {
return new TransactionalEventListenerFactory();
}
}
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
可以看到通过导入ProxyTransactionManagementConfiguration
,会添加ProxyTransactionManagementConfiguration
,BeanFactoryTransactionAttributeSourceAdvisor
,TransactionAttributeSource
,TransactionInterceptor
,TransactionalEventListenerFactory
这些BeanDefinition
# 事务相关Bean实例化以及发挥作用的时机
- TransactionalEventListenerFactory
在通过注解加载BeanDefinition (opens new window)中提到Spring会向容器中添加
EventListenerMethodProcessor
,该Bean实现了BeanFactoryPostProcessor
, 所以在容器刷新第五步invokeBeanFactoryPostProcessors
时执行EventListenerMethodProcessor
的后置处理
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
this.beanFactory = beanFactory;
//获取EventListenerFactory类型的Bean
Map<String, EventListenerFactory> beans = beanFactory.getBeansOfType(EventListenerFactory.class, false, false);
List<EventListenerFactory> factories = new ArrayList<>(beans.values());
AnnotationAwareOrderComparator.sort(factories);
this.eventListenerFactories = factories;
}
2
3
4
5
6
7
8
TransactionalEventListenerFactory
实现了EventListenerFactory
,在这里注册到Bean容器。
InfrastructureAdvisorAutoProxyCreator 该类实现了
BeanPostProcessor
,在容器刷新的第六步registerBeanPostProcessors
注册到Bean容器。
在后续的Bean创建过程中,该类的后置处理方法被执行。TransactionAttributeSource,TransactionInterceptor 在其他Bean创建时,AOP框架开始发挥作用。
在Bean初始化后进行后置增强 (opens new window),获取切面通知,进入BeanFactoryTransactionAttributeSourceAdvisor
的创建流程。 由于该Bean的创建方法需要入参TransactionAttributeSource
和TransactionInterceptor
,会先实例化这两个Bean
public class AnnotationTransactionAttributeSource extends AbstractFallbackTransactionAttributeSource
implements Serializable {
// ...
public AnnotationTransactionAttributeSource() {
this(true);
}
public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {
this.publicMethodsOnly = publicMethodsOnly;
//if...
else {
this.annotationParsers = Collections.singleton(new SpringTransactionAnnotationParser());
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- BeanFactoryTransactionAttributeSourceAdvisor 获取切面通知时实例化改Bean
public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {
@Nullable
private TransactionAttributeSource transactionAttributeSource;
private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
@Override
@Nullable
protected TransactionAttributeSource getTransactionAttributeSource() {
return transactionAttributeSource;
}
};
}
2
3
4
5
6
7
8
9
10
11
12
13
内置切入点TransactionAttributeSourcePointcut
abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {
protected TransactionAttributeSourcePointcut() {
setClassFilter(new TransactionAttributeSourceClassFilter());
}
@Override
public boolean matches(Method method, Class<?> targetClass) {
TransactionAttributeSource tas = getTransactionAttributeSource();
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}
}
2
3
4
5
6
7
8
9
10
11
12
在获取所有的通知方法后,会校验当前创建的Bean是否需要代理
AbstractAdvisorAutoProxyCreator#findAdvisorsThatCanApply
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
2
3
4
5
6
7
8
9
10
11
最终到调用方法AopUtils#canApply
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<Class<?>> classes = new LinkedHashSet<>();
if (!Proxy.isProxyClass(targetClass)) {
classes.add(ClassUtils.getUserClass(targetClass));
}
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
for (Class<?> clazz : classes) {
//获取所有类方法,包括超类的方法
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;
}
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
# 切入点与类的校验
TransactionAttributeSourcePointcut
内置classFilter
是TransactionAttributeSourceClassFilter
,是TransactionAttributeSourcePointcut
的内部类
private class TransactionAttributeSourceClassFilter implements ClassFilter {
@Override
public boolean matches(Class<?> clazz) {
if (TransactionalProxy.class.isAssignableFrom(clazz) ||
TransactionManager.class.isAssignableFrom(clazz) ||
PersistenceExceptionTranslator.class.isAssignableFrom(clazz)) {
return false;
}
//因为是内部类,调用的是TransactionAttributeSourcePointcut.getTransactionAttributeSource方法,
//获取的是BeanFactoryTransactionAttributeSourceAdvisor.transactionAttributeSource 即AnnotationTransactionAttributeSource
TransactionAttributeSource tas = getTransactionAttributeSource();
return (tas == null || tas.isCandidateClass(clazz));
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
AnnotationTransactionAttributeSource.isCandidateClass
public boolean isCandidateClass(Class<?> targetClass) {
for (TransactionAnnotationParser parser : this.annotationParsers) {
if (parser.isCandidateClass(targetClass)) {
return true;
}
}
return false;
}
2
3
4
5
6
7
8
在创建TransactionAttributeSource
时已经从构造方法中可以看出annotationParsers
中存放的是SpringTransactionAnnotationParser
SpringTransactionAnnotationParser.isCandidateClass
public boolean isCandidateClass(Class<?> targetClass) {
return AnnotationUtils.isCandidateClass(targetClass, Transactional.class);
}
2
3
AnnotationUtils.isCandidateClass
用于判断指定类能否承载指定注解的候选类
public static boolean isCandidateClass(Class<?> clazz, String annotationName) {
//java.开头的注解可以用于任何类
if (annotationName.startsWith("java.")) {
return true;
}
//这个方法是return (type.getName().startsWith("java.") || type == Ordered.class);
//即JDK中的类、Ordered类不能承载注解
if (AnnotationsScanner.hasPlainJavaAnnotationsOnly(clazz)) {
return false;
}
return true;
}
2
3
4
5
6
7
8
9
10
11
12
所以能承载@Transactional
而不仅仅是使用该注解,切入点对类的校验都是通过的
# 切入点与类方法的匹配
TransactionAttributeSourcePointcut
间接实现MethodMatcher
接口
其实现的getMethodMatcher
方法是返回自身,然后调用自己的matches
方法
public boolean matches(Method method, Class<?> targetClass) {
TransactionAttributeSource tas = getTransactionAttributeSource();
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}
2
3
4
最终调到父类方法AbstractFallbackTransactionAttributeSource#getTransactionAttribute
该方法用于获取事务配置
public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
if (method.getDeclaringClass() == Object.class) {
return null;
}
//先从缓存中查,这部分省略...
//需要注意的是,没有事务配置的方法也需要缓存,和未处理过的方法作区分
else {
//获取事务配置
TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
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);
}
this.attributeCache.put(cacheKey, txAttr);
}
return txAttr;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
// 默认公共方法才生效
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;
}
//因为上文查的是叶类与超类的所有方法,当处理超类的方法时,需要找到对应目标类的具体方法
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
// 先从目标类的方法中找
TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
if (txAttr != null) {
return txAttr;
}
// 再看目标类上是否有事务配置
txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
if (specificMethod != method) {
// 如果方法是超类的方法,看看超类方法上是否有事务配置
txAttr = findTransactionAttribute(method);
if (txAttr != null) {
return txAttr;
}
// 再看看超类上是否有事务配置
txAttr = findTransactionAttribute(method.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
}
return null;
}
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
AopUtils.getMostSpecificMethod
的思路是根据方法签名(这里指的是编译器规定的方法签名,Java的方法签名是方法名和参数,编译器的方法签名还包括返回值),获取子类对应超类的方法,然后检查是否是桥接方法,如果是桥接方法,返回桥接方法指向的方法。关于桥接方法暂时看的是这篇博客 (opens new window),以后再做整理。
# 获取事务配置
findTransactionAttribute
方法调用到AnnotationTransactionAttributeSource#determineTransactionAttribute
方法
protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
for (TransactionAnnotationParser parser : this.annotationParsers) {
TransactionAttribute attr = parser.parseTransactionAnnotation(element);
if (attr != null) {
return attr;
}
}
return null;
}
2
3
4
5
6
7
8
9
上文提到过这个TransactionAnnotationParser
就是SpringTransactionAnnotationParser
protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
Propagation propagation = attributes.getEnum("propagation");
rbta.setPropagationBehavior(propagation.value());
Isolation isolation = attributes.getEnum("isolation");
rbta.setIsolationLevel(isolation.value());
rbta.setTimeout(attributes.getNumber("timeout").intValue());
rbta.setReadOnly(attributes.getBoolean("readOnly"));
rbta.setQualifier(attributes.getString("value"));
List<RollbackRuleAttribute> rollbackRules = new ArrayList<>();
for (Class<?> rbRule : attributes.getClassArray("rollbackFor")) {
rollbackRules.add(new RollbackRuleAttribute(rbRule));
}
for (String rbRule : attributes.getStringArray("rollbackForClassName")) {
rollbackRules.add(new RollbackRuleAttribute(rbRule));
}
for (Class<?> rbRule : attributes.getClassArray("noRollbackFor")) {
rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
}
for (String rbRule : attributes.getStringArray("noRollbackForClassName")) {
rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
}
rbta.setRollbackRules(rollbackRules);
return rbta;
}
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
到这里即完成了获取方法的事务属性配置的功能。有该配置的方法的类既是需要代理的类。