万物的起源,AutoConfiuration,这里是TransactionAutoConfiguration,有内部类EnableTransactionManagementConfiguration ,主要作用是引入了注解@EnableTransactionManagement,并确定使用哪种代理方式,jdk或cglib。
@Configuration
@ConditionalOnBean(PlatformTransactionManager.class)
@ConditionalOnMissingBean(AbstractTransactionManagementConfiguration.class)
public static class EnableTransactionManagementConfiguration {
@Configuration
// proxyTargetClass = false,使用jdk代理
@EnableTransactionManagement(proxyTargetClass = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = false)
// 使用jdk代理的条件是,需要在yaml文件中手动指定spring.aop.proxy-target-class=false
public static class JdkDynamicAutoProxyConfiguration {
}
@Configuration
@EnableTransactionManagement(proxyTargetClass = true)
// proxyTargetClass = true,使用cglib代理
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true)
// 使用cglib代理的条件是,需要在yaml文件中手动指定spring.aop.proxy-target-class=true。但是这里matchIfMissing=true,也就是不配置这条属性也会生效
public static class CglibAutoProxyConfiguration {
}
}
看一下注解@EnableTransactionManagement
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
// 重点是这个
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
// true使用cglib代理,false使用jdk代理
boolean proxyTargetClass() default false;
// 代理模式,使用Spring自带的编译器,或者是aspecj编译器
// aop和aspectj没有特别大的关系,只是借用了切点、切面的一些概念。aspectj单独有一套对于面向切面编程的实现
AdviceMode mode() default AdviceMode.PROXY;
// 有多个advisor的时候定义执行顺序
int order() default Ordered.LOWEST_PRECEDENCE;
}
TransactionManagementConfigurationSelector实现了ImportSelector接口,在初始化时会调用selectImports。
这是TransactionManagementConfigurationSelector的类图
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
/**
* Returns {@link ProxyTransactionManagementConfiguration} or
* {@code AspectJ(Jta)TransactionManagementConfiguration} for {@code PROXY}
* and {@code ASPECTJ} values of {@link EnableTransactionManagement#mode()},
* respectively.
*/
@Override
protected String[] selectImports(AdviceMode adviceMode) {
// 默认是PROXY
switch (adviceMode) {
case PROXY:
return new String[] {AutoProxyRegistrar.class.getName(),
ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
return new String[] {determineTransactionAspectClass()};
default:
return null;
}
}
private String determineTransactionAspectClass() {
// 还没找到javax.transaction.Transactional在哪个包下
return (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader()) ?
TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME :
TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME);
}
}
这里selectImports又会向容器中注册AutoProxyRegistrar和ProxyTransactionManagementConfiguration。AutoProxyRegistrar的贡献是向容器中注入了InfrastructureAdvisorAutoProxyCreator,InfrastructureAdvisorAutoProxyCreator是service对象生成代理的关键。
后续过程中发现,其实注册的并不是InfrastructureAdvisorAutoProxyCreator
而是AnnotationAwareAspectJAutoProxyCreator
因为优先级AnnotationAwareAspectJAutoProxyCreator高
但是这并不影响对Spring事务的分析
// AopConfigUtils 优先级列表
private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<>(3);
static {
// Set up the escalation list...
// 级别0
APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
// 级别1
APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
// 级别2
APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
}
AutoProxyRegistrar实现了ImportBeanDefinitionRegistrar,会调用其registerBeanDefinitions方法
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean candidateFound = false;
// 获取CglibAutoProxyConfiguration上的注解,Configuration、EnableTransactionManagement、ConditionalOnProperty
// 这里需要的是EnableTransactionManagement
Set<String> annoTypes = importingClassMetadata.getAnnotationTypes();
for (String annoType : annoTypes) {
// 获取注解EnableTransactionManagement的属性
AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annoType);
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;
// 如果使用Spring的默认增强模式
if (mode == AdviceMode.PROXY) {
// 实际是向容器中注册了bean,InfrastructureAdvisorAutoProxyCreator。具体过程省略了。
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
if ((Boolean) proxyTargetClass) {
// 给InfrastructureAdvisorAutoProxyCreator的beanDefinition增加属性,proxyTargetClass=true
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
return;
}
}
// 这里没有else了,AdviceMode.ASPECTJ是另外一套实现
}
}
if (!candidateFound && logger.isInfoEnabled()) {
String name = getClass().getSimpleName();
logger.info(String.format("%s was imported but no annotations were found " +
"having both 'mode' and 'proxyTargetClass' attributes of type " +
"AdviceMode and boolean respectively. This means that auto proxy " +
"creator registration and configuration may not have occurred as " +
"intended, and components may not be proxied as expected. Check to " +
"ensure that %s has been @Import'ed on the same class where these " +
"annotations are declared; otherwise remove the import of %s " +
"altogether.", name, name, name));
}
}
接着看看,ProxyTransactionManagementConfiguration,里面主要有3个类,
1、BeanFactoryTransactionAttributeSourceAdvisor,定义了切面逻辑TransactionInterceptor和切点TransactionAttributeSourcePointcut(虽然叫切点,但是不是我们常说的切点,只是包含了切点的匹配逻辑)
2、TransactionAttributeSource:包含3个事务注解解析器。SpringTransactionAnnotationParser解析@Transactional,JtaTransactionAnnotationParser解析javax.transaction.Transactional,Ejb3TransactionAnnotationParser解析javax.ejb.TransactionAttribute,
由于我们没有引入jta和ebj相关的jar,所以实际上只有一个解析器:SpringTransactionAnnotationParser
3、TransactionInterceptor:切面逻辑
@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() {
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;
}
}
这是TransactionAttributeSourcePointcut的类图
public interface Pointcut {
ClassFilter getClassFilter();
MethodMatcher getMethodMatcher();
Pointcut TRUE = TruePointcut.INSTANCE;
}
TransactionAttributeSourcePointcut实现了MethodMatcher接口和PointCut接口。
PointCut由ClassFilter和MethodMatcher构成,并提供一个TruePointcut的实例,当pointCut为TruePointcut时会忽略所有的匹配条件,
ClassFilter和MethodMatcher分别用于在不同的级别上匹配JointPoint,ClassFilter是类级别,MethodMatcher是方法级别。
TransactionAttributeSourcePointcut中重写了方法的匹配规则matches方法
org.springframework.transaction.interceptor.TransactionAttributeSourcePointcut#matches
@Override
public boolean matches(Method method, Class<?> targetClass) {
// 目标类不能是TransactionalProxy、PlatformTransactionManager、PersistenceExceptionTranslator或其子类
if (TransactionalProxy.class.isAssignableFrom(targetClass) ||
PlatformTransactionManager.class.isAssignableFrom(targetClass) ||
PersistenceExceptionTranslator.class.isAssignableFrom(targetClass)) {
return false;
}
// 返回的是AnnotationTransactionAttributeSource
TransactionAttributeSource tas = getTransactionAttributeSource();
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}
getTransactionAttributeSource()是抽象方法,在org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor中对其进行了重写,返回的是在ProxyTransactionManagementConfiguration中定义的AnnotationTransactionAttributeSource。
所以最终决定切点匹配的是AnnotationTransactionAttributeSource中的getTransactionAttribute方法返回值是否为空,为空表示方法不匹配,否则表示匹配,并会生成代理。
AnnotationTransactionAttributeSource继承自AbstractFallbackTransactionAttributeSource,getTransactionAttribute在父类AbstractFallbackTransactionAttributeSource中
org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource#getTransactionAttribute
@Override
@Nullable
public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
// 代理对象是Object,直接返回空
if (method.getDeclaringClass() == Object.class) {
return null;
}
// First, see if we have a cached value.
// 根据方法和目标类生成缓存Key,判断是否已经缓存过
Object cacheKey = getCacheKey(method, targetClass);
TransactionAttribute cached = this.attributeCache.get(cacheKey);
if (cached != null) {
// Value will either be canonical value indicating there is no transaction attribute,
// or an actual transaction attribute.
if (cached == NULL_TRANSACTION_ATTRIBUTE) {
return null;
}
else {
return cached;
}
}
else {
// 具体的获取事务属性的逻辑
// We need to work it out.
TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
// Put it in the cache.
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);
}
if (logger.isTraceEnabled()) {
logger.trace("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);
}
this.attributeCache.put(cacheKey, txAttr);
}
return txAttr;
}
}
org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource#computeTransactionAttribute
@Nullable
protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
// Don't allow no-public methods as required.
// publicMethodsOnly属性默认为true,如果当前方法不是public修饰,返回空
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;
}
// 如果method是接口中的方法,则获取子类中的方法
// The method may be on an interface, but we need attributes from the target class.
// If the target class is null, the method will be unchanged.
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
// First try is the method in the target class.
TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
if (txAttr != null) {
return txAttr;
}
// 方法上没有@Transactionl注解,尝试从类上获取
// Second try is the transaction attribute on the target class.
txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
if (specificMethod != method) {
// Fallback is to look at the original method.
txAttr = findTransactionAttribute(method);
if (txAttr != null) {
return txAttr;
}
// Last fallback is the class of the original method.
txAttr = findTransactionAttribute(method.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
}
return null;
}
org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#determineTransactionAttribute
这里this.annotationParsers就是上面提到的事务属性解析器,实际只有一个SpringTransactionAnnotationParser
@Nullable
protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
for (TransactionAnnotationParser annotationParser : this.annotationParsers) {
TransactionAttribute attr = annotationParser.parseTransactionAnnotation(element);
if (attr != null) {
return attr;
}
}
return null;
}
@Override
@Nullable
public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
// 获取方法上的@Transactionl注解属性
AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
element, Transactional.class, false, false);
if (attributes != null) {
return parseTransactionAnnotation(attributes);
}
else {
return null;
}
}
顺便再提一下DataSourceTransactionManagerAutoConfiguration,引入了事务管理器,类型是DataSourceTransactionManager
@Bean
@ConditionalOnMissingBean(PlatformTransactionManager.class)
public DataSourceTransactionManager transactionManager(
DataSourceProperties properties) {
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(
this.dataSource);
if (this.transactionManagerCustomizers != null) {
this.transactionManagerCustomizers.customize(transactionManager);
}
return transactionManager;
}