開啓事務註解EnableTransactionManagement,該註解往容器中導入了導入TransactionManagementConfigurationSelector組件。該組件有個方法,在容器刷新的時候會被調用。(此處不講解爲何會被調用,重點講解Transaction註解)
protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:java
return new String[] {AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()}; case ASPECTJ: return new String[] {
TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME};
default:
return null;
}
}
EnableTransactionManagement默認是AdviceMode mode() default AdviceMode.PROXY;因此
AutoProxyRegistrar和ProxyTransactionManagementConfiguration會被加載到容器中。
AutoProxyRegistrar功能是往容器中註冊了InfrastructureAdvisorAutoProxyCreator是個BeanPostProcessor後置處理器。
ProxyTransactionManagementConfiguration利用@Bean註解往容器中添加多個bean。(BeanFactoryTransactionAttributeSourceAdvisor是個Advisor和前面Aop中@Before同樣都是通知方法,可是此處的是手動導入的,Aop是本身自動生成的)。
在bean生成完成之後會調用後置處理器初始化。會去查找bean有沒有合適的通知方法。因此重點是在找通知方法,找到了合適的就會生成代理對象。
//簡單的分析一下流程
AbstractAutowireCapableBeanFactory#initializeBean() ->
AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization() ->
AbstractAutoProxyCreator#postProcessAfterInitialization() ->
AbstractAutoProxyCreator#wrapIfNecessary()->
AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean()
/**
* 尋找可用的通知方法
*/
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
//尋找全部的Advisors,會去容器遍歷全部類型爲Advisor的bean,
//BeanFactoryTransactionAttributeSourceAdvisor就是咱們手動導入的Advisor
List<Advisor> candidateAdvisors = findCandidateAdvisors();
//在全部的Advisors,看是否有beanClass匹配的
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
//找到全部的Advisors,剩下就是是否有匹配的findAdvisorsThatCanApply()方法//最終走到TransactionAttributeSourcePointcut#matches//->AbstractFallbackTransactionAttributeSource#computeTransactionAttribute
`
javaprotected TransactionAttribute computeTransactionAttribute(Method method, Class<?> targetClass) {
//判斷方法修飾符是否是Public,allowPublicMethodsOnly()默認是true的
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;
}
// 這裏面就是判斷方法上有沒有Transactional註解,有進行解析操做並返回。
TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
if (txAttr != null) {
return txAttr;
}
//代碼每貼全,爲了少點沒用的東西。。。。
那要是找了合適的通知方法,就生成代理對象,並設置回調函數。設置回調函數是CglibAopProxy.DynamicAdvisedInterceptor的intercept方法,該方法有個getInterceptorsAndDynamicInterceptionAdvice獲取合適的攔截器。(事務的攔截器是TransactionInterceptor)
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
//獲取目標對象,不是代理對象
target = getTarget();
if (target != null) {
targetClass = target.getClass();
}
//獲取方法合適的攔截器
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
//沒有合適的攔截器而且方法的修飾符是Public
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
//會調用目標方法
retVal = methodProxy.invoke(target, argsToUse);
}
else {
/*
* 1.有合適的攔截器:跟單網www.gendan5.com會去執行攔截器TransactionInterceptor#invoke(),
* 事務的提交,回滾等一系列操做都在裏面。具體是調去了
* TransactionAspectSupport#invokeWithinTransaction()方法
* 2.沒有合適的攔截器而且方法的修飾符不是Public:這裏面也會去調目標方法
* (這裏簡單能夠走進去看一下)
*/
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
app