本文基于springboot(1.5以上)的事务管理的开篇,主要关于Transaction注解的生效过程
Transaction注解怎么生效
springboot开启事务管理需要在启动类加上@EnableTransactionManagement,EnableTransactionManagement使用@Import导入TransactionManagementConfigurationSelector类,TransactionManagementConfigurationSelector实现了ImportSelector接口
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;
}
}
默认情况下是proxy 模式,会导入AutoProxyRegistrar(将InfrastructureAdvisorAutoProxyCreator纳入spring管理,但是后续会被高优先级的AnnotationAwareAspectJAutoProxyCreator替代)和ProxyTransactionManagementConfiguration。
1.先分析AutoProxyRegistrar
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean candidateFound = false;
Set<String> annoTypes = importingClassMetadata.getAnnotationTypes();
for (String annoType : annoTypes) {
AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annoType);
if (candidate == null) {
continue;
}
// springboot中如果在main函数所在的Application类中加了EnableTransactionManagement注解
// 下面这个判断就会成立,默认情况下mode是proxy,就会使用AopConfigUtils
// 将InfrastructureAdvisorAutoProxyCreator加入spring容器
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;
}
}
}
}
}
AutoProxyRegistrar是一个实现了ImportBeanDefinitionRegistrar接口的类, AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry)会将InfrastructureAdvisorAutoProxyCreator加入了spring管理,但是真正用来创建代理的是AnnotationAwareAspectJAutoProxyCreator类,看下面这张继承关系图,两者都继承了AbstractAdvisorAutoProxyCreator,主要功能是类似的,那么AnnotationAwareAspectJAutoProxyCreator又是什么时候引入spring容器的呢?
这里就要涉及springboot是怎么实现自动配置的了。@SpringBootApplication会引入@EnableAutoConfiguration,这个注解会使用@Import导入 EnableAutoConfigurationImportSelector,此类的父类AutoConfigurationImportSelector实现了ImportSelector,在selectImports方法中使用AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader)导入META-INF/spring-autoconfigure-metadata.properties,导入@EnableAspectJAutoProxy,而@EnableAspectJAutoProxy又使用@Import导入了AspectJAutoProxyRegistrar,在这个类的selectImports会注册上AnnotationAwareAspectJAutoProxyCreator这个Bean,也就是说其实只要是springboot项目都会导入这个Bean,而由于在AopConfigUtils将AnnotationAwareAspectJAutoProxyCreator和InfrastructureAdvisorAutoProxyCreator做了排序,如果存在AnnotationAwareAspectJAutoProxyCreator,那么InfrastructureAdvisorAutoProxyCreator就不会生效。
那什么时候会为加了Transaction注解的方法或者类加上事务管理功能呢?
2.分析AnnotationAwareAspectJAutoProxyCreator
AnnotationAwareAspectJAutoProxyCreator实现了AbstractAutoProxyCreator抽象类,AbstractAutoProxyCreator又实现了BeanPostProcessor接口,熟悉spring IOC的都知道在每个Bean执行完初始化方法后会执行BeanPostProcessor接口的postProcessAfterInitialization方法,AbstractAutoProxyCreator的postProcessAfterInitialization就会判断是否需要为当前Bean生成代理,那是怎么做的呢?
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
// Transaction注解就会在这里生成代理类
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
AbstractAutoProxyCreator的postProcessAfterInitialization方法会判断是否需要为当前正在创建的Bean创建一个代理的包装类。
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// 如果使用了Transaction注解这里就会返回拦截器,返回BeanFactoryTransactionAttributeSourceAdvisor
// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 创建代理
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
主要关注getAdvicesAndAdvisorsForBean方法,在AbstractAdvisorAutoProxyCreator类中,会调用findEligibleAdvisors方法查找符合要求的Advisor。
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 查找候选advisor
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 使用AopUtils.findAdvisorsThatCanApply判断时候能应用
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
findEligibleAdvisors方法会通过findCandidateAdvisors查找spring容器中所有存在的Advisor,findCandidateAdvisors掠过不分析,其实也很简单,可以自己分析(主要调用的是AnnotationAwareAspectJAutoProxyCreator的findCandidateAdvisors)。主要分析findAdvisorsThatCanApply方法。
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new ArrayList<>();
for (Advisor candidate : candidateAdvisors) {
// IntroductionAdvisor是为每个对象做的代理,事务是针对每个类的,这个不会成立
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
// 主要是在这里看是否能够应用
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
调用当前类的canApply方法判断Advisor是否适合当前Bean。
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
else if (advisor instanceof PointcutAdvisor) {
// 走到这里
PointcutAdvisor pca = (PointcutAdvisor) advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
// It doesn't have a pointcut so we assume it applies.
return true;
}
}
那么这里的PointcutAdvisor又是哪一个类的功能呢?
3.分析TransactionManagementConfigurationSelector
是否还记得之前的在TransactionManagementConfigurationSelector导入了两个类,一个是AutoProxyRegistrar,我们已经分析了,另一个就是ProxyTransactionManagementConfiguration,
在ProxyTransactionManagementConfiguration会创建BeanFactoryTransactionAttributeSourceAdvisor,AnnotationTransactionAttributeSource和TransactionInterceptor这三个bean。
此时BeanFactoryTransactionAttributeSourceAdvisor就派上了用场,BeanFactoryTransactionAttributeSourceAdvisor中维护了一个pointcut:TransactionAttributeSourcePointcut,canApply中返回的pointcut就是这个pointcut,那又是怎么判断这个advisor是否适合当前正在创建的Bean呢?
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;
}
// 这里返回TransactionAttributeSourcePointcut自己就是一个MethodMatcher,这里返回的是自己
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<Class<?>>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
classes.add(targetClass);
for (Class<?> clazz : classes) {
//获取正在创建Bean的所有方法,introductionAwareMethodMatcher我们忽略,调用的是methodMatcher.matches来判断匹配
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;
}
会调用methodMatcher.matches来判断当前正在创建的Bean的每一个方法是否能应用当前Advisor,我们再来看这个matches方法:
public boolean matches(Method method, Class<?> targetClass) {
if (TransactionalProxy.class.isAssignableFrom(targetClass)) {
return false;
}
TransactionAttributeSource tas = getTransactionAttributeSource();
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}
而getTransactionAttributeSource()方法中返回的就是ProxyTransactionManagementConfiguration中创建的另一个Bean:AnnotationTransactionAttributeSource,让我们再来看AnnotationTransactionAttributeSource的getTransactionAttribute方法,AnnotationTransactionAttributeSource继承了AbstractFallbackTransactionAttributeSource,真正使用的是AbstractFallbackTransactionAttributeSource的getTransactionAttribute方法。
public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
if (method.getDeclaringClass() == Object.class) {
return null;
}
// First, see if we have a cached value.
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 {
// 通过这里计算是否存在Transaction注解,其他代码是在做缓存,避免重复计算
// 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;
}
}
我们只看这个方法中的TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);这一行代码,其他代码是在做缓存,避免重复计算,computeTransactionAttribute会使用子类实现的findTransactionAttribute来查找注解,最终会调用determineTransactionAttribute来查找注解。
protected TransactionAttribute determineTransactionAttribute(AnnotatedElement ae) {
if (ae.getAnnotations().length > 0) {
for (TransactionAnnotationParser annotationParser : this.annotationParsers) {
TransactionAttribute attr = annotationParser.parseTransactionAnnotation(ae);
if (attr != null) {
return attr;
}
}
}
return null;
}
AnnotationTransactionAttributeSource初始化时会添加SpringTransactionAnnotationParser,这里的parseTransactionAnnotation调用的就是SpringTransactionAnnotationParser的parseTransactionAnnotation方法。
public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
// 查找方法使用了@Transactional相关的属性
AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
element, Transactional.class, false, false);
if (attributes != null) {
// 将所有注解属性拼成一个RuleBasedTransactionAttribute返回
return parseTransactionAnnotation(attributes);
}
else {
return null;
}
}
如果存在Tranction注解,最终parseTransactionAnnotation会返回一个RuleBasedTransactionAttribute,里面包含了@Transaction的相关属性比如传播行为,隔离级别等,后面事务管理相关文章会分析这个类。
返回RuleBasedTransactionAttribute后,canApply方法就会返回true,让我们再回到wrapIfNecessary方法。
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// 如果使用了Transaction注解这里就会返回拦截器,返回BeanFactoryTransactionAttributeSourceAdvisor
// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 创建代理
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
canApply返回true后,getAdvicesAndAdvisorsForBean就会将BeanFactoryTransactionAttributeSourceAdvisor作为符合要求的Advisor返回,接下来就进入了创建代理的过程,我们知道一个Advisor中真正对方法调用起作用的是Advice,而BeanFactoryTransactionAttributeSourceAdvisor使用的Advice就是ProxyTransactionManagementConfiguration中创建的最后一个Bean:TransactionInterceptor。
创建完代理后返回postProcessAfterInitialization,spring就会用这个被代理的对象替换之前传入的Bean,这样就为添加了Transaction注解的Bean添加了代理,引入了事务管理功能。
下一篇文章我们再来看看TransactionInterceptor是怎么起作用的。
写在最后
本篇文章是springboot事务管理的第一篇,鉴于本人才疏学浅,如有不对之处欢迎指正,包括文章的错误和分析的思路等等,大家一起进步。