/**
* 找到的就是ProxyTransactionManagementConfiguration注册到容器中的BeanFactoryTransactionAttributeSourceAdvisor
*/public List<Advisor>findAdvisorBeans(){// Determine list of advisor bean names, if not cached already.
String[] advisorNames =this.cachedAdvisorBeanNames;if(advisorNames == null){// Do not initialize FactoryBeans here: We need to leave all regular beans// uninitialized to let the auto-proxy creator apply to them!
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Advisor.class,true,false);this.cachedAdvisorBeanNames = advisorNames;}if(advisorNames.length ==0){returnnewArrayList<>();}
List<Advisor> advisors =newArrayList<>();for(String name : advisorNames){if(isEligibleBean(name)){if(this.beanFactory.isCurrentlyInCreation(name)){if(logger.isTraceEnabled()){
logger.trace("Skipping currently created advisor '"+ name +"'");}}else{try{
advisors.add(this.beanFactory.getBean(name, Advisor.class));}catch(BeanCreationException ex){
Throwable rootCause = ex.getMostSpecificCause();if(rootCause instanceofBeanCurrentlyInCreationException){
BeanCreationException bce =(BeanCreationException) rootCause;
String bceBeanName = bce.getBeanName();if(bceBeanName != null &&this.beanFactory.isCurrentlyInCreation(bceBeanName)){if(logger.isTraceEnabled()){
logger.trace("Skipping advisor '"+ name +"' with dependency on currently created bean: "+ ex.getMessage());}// Ignore: indicates a reference back to the bean we're trying to advise.// We want to find advisors other than the currently created bean itself.continue;}}throw ex;}}}}return advisors;}
publicstaticbooleancanApply(Advisor advisor, Class<?> targetClass,boolean hasIntroductions){if(advisor instanceofIntroductionAdvisor){//BeanFactoryTransactionAttributeSourceAdvisor不是IntroductionAdvisor的子类return((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);}elseif(advisor instanceofPointcutAdvisor){//BeanFactoryTransactionAttributeSourceAdvisor是PointcutAdvisor的子类
PointcutAdvisor pca =(PointcutAdvisor) advisor;returncanApply(pca.getPointcut(), targetClass, hasIntroductions);//会执行该apply方法}else{// It doesn't have a pointcut so we assume it applies.returntrue;}}
publicstaticbooleancanApply(Pointcut pc, Class<?> targetClass,boolean hasIntroductions){
Assert.notNull(pc,"Pointcut must not be null");if(!pc.getClassFilter().matches(targetClass)){returnfalse;}
MethodMatcher methodMatcher = pc.getMethodMatcher();//methodMatcher就是BeanFactoryTransactionAttributeSourceAdvisorif(methodMatcher == MethodMatcher.TRUE){// No need to iterate the methods if we're matching any method anyway...returntrue;}
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;if(methodMatcher instanceofIntroductionAwareMethodMatcher){//BeanFactoryTransactionAttributeSourceAdvisor不是IntroductionAwareMethodMatcher的子类
introductionAwareMethodMatcher =(IntroductionAwareMethodMatcher) methodMatcher;}
Set<Class<?>> classes =newLinkedHashSet<>();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)){returntrue;}}}returnfalse;}
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{// 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 instanceofDefaultTransactionAttribute){
DefaultTransactionAttribute dta =(DefaultTransactionAttribute) txAttr;
dta.setDescriptor(methodIdentification);
dta.resolveAttributeStrings(this.embeddedValueResolver);}if(logger.isTraceEnabled()){
logger.trace("Adding transactional method '"+ methodIdentification +"' with attribute: "+ txAttr);}this.attributeCache.put(cacheKey, txAttr);}return txAttr;}}
protected TransactionAttribute computeTransactionAttribute(Method method,@Nullable Class<?> targetClass){// Don't allow no-public methods as required.if(allowPublicMethodsOnly()&&!Modifier.isPublic(method.getModifiers())){return null;}// 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);//方法上面查找@Transactional注解if(txAttr != null){return txAttr;}// Second try is the transaction attribute on the target class.
txAttr =findTransactionAttribute(specificMethod.getDeclaringClass());//在方法声明的类上查找@Transactional注解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;}
publicclassTransactionInterceptorextendsTransactionAspectSupportimplementsMethodInterceptor, Serializable {@Override@Nullablepublic Object invoke(MethodInvocation invocation)throws Throwable {// Work out the target class: may be {@code null}.// The TransactionAttributeSource should be passed the target class// as well as the method, which may be from an interface.
Class<?> targetClass =(invocation.getThis()!= null ? AopUtils.getTargetClass(invocation.getThis()): null);// Adapt to TransactionAspectSupport's invokeWithinTransaction...returninvokeWithinTransaction(invocation.getMethod(), targetClass,newCoroutinesInvocationCallback(){@Override@Nullablepublic Object proceedWithInvocation()throws Throwable {return invocation.proceed();}@Overridepublic Object getTarget(){return invocation.getThis();}@Overridepublic Object[]getArguments(){return invocation.getArguments();}});}}
protected Object invokeWithinTransaction(Method method,@Nullable Class<?> targetClass,final InvocationCallback invocation)throws Throwable {// If the transaction attribute is null, the method is non-transactional.
TransactionAttributeSource tas =getTransactionAttributeSource();final TransactionAttribute txAttr =(tas != null ? tas.getTransactionAttribute(method, targetClass): null);final TransactionManager tm =determineTransactionManager(txAttr);...省略了部分代码
PlatformTransactionManager ptm =asPlatformTransactionManager(tm);//强转为PlatformTransactionManagerfinal String joinpointIdentification =methodIdentification(method, targetClass, txAttr);if(txAttr == null ||!(ptm instanceofCallbackPreferringPlatformTransactionManager)){// Standard transaction demarcation with getTransaction and commit/rollback calls.
TransactionInfo txInfo =createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);//开启事务
Object retVal;try{// This is an around advice: Invoke the next interceptor in the chain.// This will normally result in a target object being invoked.
retVal = invocation.proceedWithInvocation();}catch(Throwable ex){// target invocation exceptioncompleteTransactionAfterThrowing(txInfo, ex);//回滚或者提交事务throw ex;}finally{cleanupTransactionInfo(txInfo);}if(retVal != null && vavrPresent && VavrDelegate.isVavrTry(retVal)){// Set rollback-only in case of Vavr failure matching our rollback rules...
TransactionStatus status = txInfo.getTransactionStatus();if(status != null && txAttr != null){
retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);}}commitTransactionAfterReturning(txInfo);//提交事务return retVal;}else{
Object result;final ThrowableHolder throwableHolder =newThrowableHolder();// It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.try{
result =((CallbackPreferringPlatformTransactionManager) ptm).execute(txAttr, status ->{
TransactionInfo txInfo =prepareTransactionInfo(ptm, txAttr, joinpointIdentification, status);try{
Object retVal = invocation.proceedWithInvocation();if(retVal != null && vavrPresent && VavrDelegate.isVavrTry(retVal)){// Set rollback-only in case of Vavr failure matching our rollback rules...
retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);}return retVal;}catch(Throwable ex){if(txAttr.rollbackOn(ex)){// A RuntimeException: will lead to a rollback.if(ex instanceofRuntimeException){throw(RuntimeException) ex;}else{thrownewThrowableHolderException(ex);}}else{// A normal return value: will lead to a commit.
throwableHolder.throwable = ex;return null;}}finally{cleanupTransactionInfo(txInfo);}});}catch(ThrowableHolderException ex){throw ex.getCause();}catch(TransactionSystemException ex2){if(throwableHolder.throwable != null){
logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
ex2.initApplicationException(throwableHolder.throwable);}throw ex2;}catch(Throwable ex2){if(throwableHolder.throwable != null){
logger.error("Application exception overridden by commit exception", throwableHolder.throwable);}throw ex2;}// Check result state: It might indicate a Throwable to rethrow.if(throwableHolder.throwable != null){throw throwableHolder.throwable;}return result;}}
@Nullableprotected TransactionManager determineTransactionManager(@Nullable TransactionAttribute txAttr){// Do not attempt to lookup tx manager if no tx attributes are setif(txAttr == null ||this.beanFactory == null){returngetTransactionManager();}
String qualifier = txAttr.getQualifier();if(StringUtils.hasText(qualifier)){returndetermineQualifiedTransactionManager(this.beanFactory, qualifier);}elseif(StringUtils.hasText(this.transactionManagerBeanName)){returndetermineQualifiedTransactionManager(this.beanFactory,this.transactionManagerBeanName);}else{//第一次会走这个else里面的逻辑
TransactionManager defaultTransactionManager =getTransactionManager();if(defaultTransactionManager == null){
defaultTransactionManager =this.transactionManagerCache.get(DEFAULT_TRANSACTION_MANAGER_KEY);if(defaultTransactionManager == null){//从容器中获取TransactionManager,也就是我们自己注册到容器中的TransactionManager
defaultTransactionManager =this.beanFactory.getBean(TransactionManager.class);this.transactionManagerCache.putIfAbsent(
DEFAULT_TRANSACTION_MANAGER_KEY, defaultTransactionManager);}}return defaultTransactionManager;}}
本文只是记录,非讲解,请勿参考@EnableTransactionManagement注解会向容器中注入ProxyTransactionManagementConfiguration和InfrastructureAdvisorAutoProxyCreator两个对象@Import(TransactionManagementConfigurationSelector.class)public @interface EnableTransactionManagement {}public class