本文基于springboot(1.5以上)的事務(wù)管理的開篇,主要關(guān)于Transaction注解的生效過程
Transaction注解怎么生效
springboot開啟事務(wù)管理需要在啟動類加上@EnableTransactionManagement,EnableTransactionManagement使用@Import導(dǎo)入TransactionManagementConfigurationSelector類,TransactionManagementConfigurationSelector實(shí)現(xiàn)了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;
}
}
默認(rèn)情況下是proxy 模式,會導(dǎo)入AutoProxyRegistrar(將InfrastructureAdvisorAutoProxyCreator納入spring管理,但是后續(xù)會被高優(yōu)先級的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函數(shù)所在的Application類中加了EnableTransactionManagement注解
// 下面這個(gè)判斷就會成立,默認(rèn)情況下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是一個(gè)實(shí)現(xiàn)了ImportBeanDefinitionRegistrar接口的類, AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry)會將InfrastructureAdvisorAutoProxyCreator加入了spring管理,但是真正用來創(chuàng)建代理的是AnnotationAwareAspectJAutoProxyCreator類,看下面這張繼承關(guān)系圖,兩者都繼承了AbstractAdvisorAutoProxyCreator,主要功能是類似的,那么AnnotationAwareAspectJAutoProxyCreator又是什么時(shí)候引入spring容器的呢?

這里就要涉及springboot是怎么實(shí)現(xiàn)自動配置的了。@SpringBootApplication會引入@EnableAutoConfiguration,這個(gè)注解會使用@Import導(dǎo)入 EnableAutoConfigurationImportSelector,此類的父類AutoConfigurationImportSelector實(shí)現(xiàn)了ImportSelector,在selectImports方法中使用AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader)導(dǎo)入META-INF/spring-autoconfigure-metadata.properties,導(dǎo)入@EnableAspectJAutoProxy,而@EnableAspectJAutoProxy又使用@Import導(dǎo)入了AspectJAutoProxyRegistrar,在這個(gè)類的selectImports會注冊上AnnotationAwareAspectJAutoProxyCreator這個(gè)Bean,也就是說其實(shí)只要是springboot項(xiàng)目都會導(dǎo)入這個(gè)Bean,而由于在AopConfigUtils將AnnotationAwareAspectJAutoProxyCreator和InfrastructureAdvisorAutoProxyCreator做了排序,如果存在AnnotationAwareAspectJAutoProxyCreator,那么InfrastructureAdvisorAutoProxyCreator就不會生效。
那什么時(shí)候會為加了Transaction注解的方法或者類加上事務(wù)管理功能呢?
2.分析AnnotationAwareAspectJAutoProxyCreator
AnnotationAwareAspectJAutoProxyCreator實(shí)現(xiàn)了AbstractAutoProxyCreator抽象類,AbstractAutoProxyCreator又實(shí)現(xiàn)了BeanPostProcessor接口,熟悉spring IOC的都知道在每個(gè)Bean執(zhí)行完初始化方法后會執(zhí)行BeanPostProcessor接口的postProcessAfterInitialization方法,AbstractAutoProxyCreator的postProcessAfterInitialization就會判斷是否需要為當(dāng)前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方法會判斷是否需要為當(dāng)前正在創(chuàng)建的Bean創(chuàng)建一個(gè)代理的包裝類。
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注解這里就會返回?cái)r截器,返回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);
// 創(chuàng)建代理
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;
}
主要關(guān)注getAdvicesAndAdvisorsForBean方法,在AbstractAdvisorAutoProxyCreator類中,會調(diào)用findEligibleAdvisors方法查找符合要求的Advisor。
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 查找候選advisor
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 使用AopUtils.findAdvisorsThatCanApply判斷時(shí)候能應(yīng)用
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
findEligibleAdvisors方法會通過findCandidateAdvisors查找spring容器中所有存在的Advisor,findCandidateAdvisors掠過不分析,其實(shí)也很簡單,可以自己分析(主要調(diào)用的是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是為每個(gè)對象做的代理,事務(wù)是針對每個(gè)類的,這個(gè)不會成立
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;
}
// 主要是在這里看是否能夠應(yīng)用
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
調(diào)用當(dāng)前類的canApply方法判斷Advisor是否適合當(dāng)前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又是哪一個(gè)類的功能呢?
3.分析TransactionManagementConfigurationSelector
是否還記得之前的在TransactionManagementConfigurationSelector導(dǎo)入了兩個(gè)類,一個(gè)是AutoProxyRegistrar,我們已經(jīng)分析了,另一個(gè)就是ProxyTransactionManagementConfiguration,
在ProxyTransactionManagementConfiguration會創(chuàng)建BeanFactoryTransactionAttributeSourceAdvisor,AnnotationTransactionAttributeSource和TransactionInterceptor這三個(gè)bean。
此時(shí)BeanFactoryTransactionAttributeSourceAdvisor就派上了用場,BeanFactoryTransactionAttributeSourceAdvisor中維護(hù)了一個(gè)pointcut:TransactionAttributeSourcePointcut,canApply中返回的pointcut就是這個(gè)pointcut,那又是怎么判斷這個(gè)advisor是否適合當(dāng)前正在創(chuàng)建的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自己就是一個(gè)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) {
//獲取正在創(chuàng)建Bean的所有方法,introductionAwareMethodMatcher我們忽略,調(diào)用的是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;
}
會調(diào)用methodMatcher.matches來判斷當(dāng)前正在創(chuàng)建的Bean的每一個(gè)方法是否能應(yīng)用當(dāng)前Advisor,我們再來看這個(gè)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中創(chuàng)建的另一個(gè)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 {
// 通過這里計(jì)算是否存在Transaction注解,其他代碼是在做緩存,避免重復(fù)計(jì)算
// 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;
}
}
我們只看這個(gè)方法中的TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);這一行代碼,其他代碼是在做緩存,避免重復(fù)計(jì)算,computeTransactionAttribute會使用子類實(shí)現(xiàn)的findTransactionAttribute來查找注解,最終會調(diào)用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初始化時(shí)會添加SpringTransactionAnnotationParser,這里的parseTransactionAnnotation調(diào)用的就是SpringTransactionAnnotationParser的parseTransactionAnnotation方法。
public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
// 查找方法使用了@Transactional相關(guān)的屬性
AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
element, Transactional.class, false, false);
if (attributes != null) {
// 將所有注解屬性拼成一個(gè)RuleBasedTransactionAttribute返回
return parseTransactionAnnotation(attributes);
}
else {
return null;
}
}
如果存在Tranction注解,最終parseTransactionAnnotation會返回一個(gè)RuleBasedTransactionAttribute,里面包含了@Transaction的相關(guān)屬性比如傳播行為,隔離級別等,后面事務(wù)管理相關(guān)文章會分析這個(gè)類。
返回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注解這里就會返回?cái)r截器,返回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);
// 創(chuàng)建代理
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返回,接下來就進(jìn)入了創(chuàng)建代理的過程,我們知道一個(gè)Advisor中真正對方法調(diào)用起作用的是Advice,而BeanFactoryTransactionAttributeSourceAdvisor使用的Advice就是ProxyTransactionManagementConfiguration中創(chuàng)建的最后一個(gè)Bean:TransactionInterceptor。
創(chuàng)建完代理后返回postProcessAfterInitialization,spring就會用這個(gè)被代理的對象替換之前傳入的Bean,這樣就為添加了Transaction注解的Bean添加了代理,引入了事務(wù)管理功能。
下一篇文章我們再來看看TransactionInterceptor是怎么起作用的。
寫在最后
本篇文章是springboot事務(wù)管理的第一篇,鑒于本人才疏學(xué)淺,如有不對之處歡迎指正,包括文章的錯誤和分析的思路等等,大家一起進(jìn)步。