Spring事務是如何應用到你的業務場景中的?

初衷

平常開發中常常用到@Transaction註解,那你知道它是怎麼應用到你的業務代碼中的嗎?本篇文章將從如下兩個方面闡述Spring事務實現原理:java

  1. 解析並加載事務配置:本質上是解析xml文件將標籤加載成 BeanDefinition 對象;node

  2. 生成事務代理對象並運行:本質上是Spring AOP在事務這塊的應用,將業務Bean替換成事務代理對象(JdkDynamicAopProxy:JDK代理,CglibAopProxy:CGLIB代理);mysql

本文使用的源碼版本是Spring 4.3.18.RELEASE,使用的是XML開啓事務。spring

關鍵類

這裏列出幾個核心類,提早留個印象,後面會講解何時調用sql

  1. XmlBeanDefinitionReader 加載XML定義的Bean入口bootstrap

  2. TxNamespaceHandler 解析XML中的事務標籤: advice、annotation-driven等;緩存

  3. InfrastructureAdvisorAutoProxyCreator 該類實現了 BeanPostProcessor 接口(能夠在Bean初始化後進行替換),是生成事務代理類並替換的關鍵類;app

  4. AnnotationTransactionAttributeSource 用來解析業務方法使用註解 @Transaction 上的配置,提供給 TransactionInterceptor 使用;ide

  5. TransactionInterceptor 事務攔截類:真正處理事務的類,開啓、回滾事務,能夠理解成切面中的通知:作什麼;函數

  6. BeanFactoryTransactionAttributeSourceAdvisor 實現了Advisor接口,能夠理解爲切面:切點(TransactionAttributeSourcePointcut) + 通知(TransactionInterceptor)。

示例代碼:
	public class TransactionService {	
	    @Transactional(rollbackFor = Throwable.class)	    public void testTransaction(){
	        System.out.println("方法邏輯");
	    }
	}
     ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("config.xml");
     TransactionService transactionService = context.getBean(TransactionService.class);
     transactionService.testTransaction();
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:jee="http://www.springframework.org/schema/jee"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:task="http://www.springframework.org/schema/task"
       xsi:schemaLocation="
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.0.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd">
    <bean id="transactionService" class="com.yangwq.spring.transaction.TransactionService"/>

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://127.0.0.1:3306/blog"/>
        <property name="username" value="root"/>
        <property name="password" value="11"/>
    </bean>

    <!-- 定義事務管理器 -->
    <bean id="transactionManager"
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!--使用註釋事務 -->
    <tx:annotation-driven/></beans>
1. 解析並加載事務配置

加載的入口(同時也是Spring容器加載的核心代碼):

synchronized (this.startupShutdownMonitor) {			// Prepare this context for refreshing.
			prepareRefresh();			// 重點,這裏是Spring初始化默認的容器,在這一步會經過解析配置文件將定義的bean轉換爲 BeanDefinition,
			// 保存在 beanDefinitionMap 中
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);			try {				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);				// Initialize message source for this context.
				initMessageSource();				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();				// Initialize other special beans in specific context subclasses.
				onRefresh();				// Check for listener beans and register them.
				registerListeners();				// 重點,初始化全部非懶加載bean的方法,也能夠理解爲根據特定規則將 BeanDefinition 轉成 Bean對象的方法
				finishBeanFactoryInitialization(beanFactory);				// Last step: publish corresponding event.
				finishRefresh();
			}			catch (BeansException ex) {				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +							"cancelling refresh attempt: " + ex);
				}				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();				// Reset 'active' flag.
				cancelRefresh(ex);				// Propagate exception to caller.
				throw ex;
			}			finally {				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
			}
		}

事務配置的解析在上面的obtainFreshBeanFactory,因爲咱們使用的是ClassPathXmlApplicationContext 做爲容器,它的解析類爲:XmlBeanDefinitionReader;核心方法:

public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
		Assert.notNull(encodedResource, "EncodedResource must not be null");		if (logger.isInfoEnabled()) {
			logger.info("Loading XML bean definitions from " + encodedResource.getResource());
		}

		Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();		if (currentResources == null) {
			currentResources = new HashSet<EncodedResource>(4);			this.resourcesCurrentlyBeingLoaded.set(currentResources);
		}		if (!currentResources.add(encodedResource)) {			throw new BeanDefinitionStoreException(					"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
		}		try {			// 讀取 config.xml 文件
			InputStream inputStream = encodedResource.getResource().getInputStream();			try {
				InputSource inputSource = new InputSource(inputStream);				if (encodedResource.getEncoding() != null) {
					inputSource.setEncoding(encodedResource.getEncoding());
				}				// 開始加載 config.xml 文件中定義的bean,這裏只是加載成BeanDefinition,初始化在另外的方法
				return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
			}			finally {
				inputStream.close();
			}
		}		catch (IOException ex) {			throw new BeanDefinitionStoreException(					"IOException parsing XML document from " + encodedResource.getResource(), ex);
		}		finally {
			currentResources.remove(encodedResource);			if (currentResources.isEmpty()) {				this.resourcesCurrentlyBeingLoaded.remove();
			}
		}
	}	

doLoadBeanDefinitions 具體解析的方法是在org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#doRegisterBeanDefinitions 中進行,該方法以下

		protected void doRegisterBeanDefinitions(Element root) {		// Any nested <beans> elements will cause recursion in this method. In
		// order to propagate and preserve <beans> default-* attributes correctly,
		// keep track of the current (parent) delegate, which may be null. Create
		// the new (child) delegate with a reference to the parent for fallback purposes,
		// then ultimately reset this.delegate back to its original (parent) reference.
		// this behavior emulates a stack of delegates without actually necessitating one.
		BeanDefinitionParserDelegate parent = this.delegate;		this.delegate = createDelegate(getReaderContext(), root, parent);		if (this.delegate.isDefaultNamespace(root)) {
			String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);			if (StringUtils.hasText(profileSpec)) {
				String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
						profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);				if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {					if (logger.isInfoEnabled()) {
						logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +								"] not matching: " + getReaderContext().getResource());
					}					return;
				}
			}
		}

		preProcessXml(root);		// 真正解析config.xml文件
		parseBeanDefinitions(root, this.delegate);
		postProcessXml(root);		this.delegate = parent;
	}	
	protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {	    // 判斷根節點是否是默認的節點,實際經過判斷根節點的 namespaceURI 屬性是否是 http://www.springframework.org/schema/beans ,
	    // 咱們這裏的配置文件聲明的正好是這個屬性,因此返回的是true,注意bean標籤也是默認標籤
		if (delegate.isDefaultNamespace(root)) {			// 獲取子節點
			NodeList nl = root.getChildNodes();			for (int i = 0; i < nl.getLength(); i++) {
				Node node = nl.item(i);				// 判斷子節點是否是標籤
				if (node instanceof Element) {
					Element ele = (Element) node;					// bean標籤的解析
					if (delegate.isDefaultNamespace(ele)) {
						parseDefaultElement(ele, delegate);
					}					// 重點:tx標籤在這裏進行
					else {
						delegate.parseCustomElement(ele);
					}
				}
			}
		}		else {
			delegate.parseCustomElement(root);
		}
	}	// 解析非bean的標籤
	public BeanDefinition parseCustomElement(Element ele) {		return parseCustomElement(ele, null);
	}	// 解析非默認標籤方法
	public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
		String namespaceUri = getNamespaceURI(ele);		// 這裏是Spring使用了策略模式解析配置,經過namespaceUri匹配對應的處理類,也就是上面的關鍵類 TxNamespaceHandler,
		// 這裏的resolve運用了懶加載,在獲取映射關係handlerMappings屬性爲null時會從META-INF/spring.handlers 下面獲取映射關係,
		// 因爲IDEA debug的時候默認會調用getHandlerMappings方法,因此使用debug的時候會發現一開始就有值
		NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);		if (handler == null) {
			error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);			return null;
		}		// 獲取處處理類後,讓處理類開始解析配置
		return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
	}

TxNamespaceHandler 最終交給類 AnnotationDrivenBeanDefinitionParser 進行解析事務配置;

public BeanDefinition parse(Element element, ParserContext parserContext) {		// 註冊一個事務工廠事件,容許咱們自定義監聽事務的提交等操做
		registerTransactionalEventListenerFactory(parserContext);
		String mode = element.getAttribute("mode");		// 若是使用的是 aspectj 方式,走這個方法
		if ("aspectj".equals(mode)) {			// mode="aspectj"
			registerTransactionAspect(element, parserContext);
		}		else {			// 默認使用的是代理模式 
			// mode="proxy"
			AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
		}		return null;
	}	
	/**
	 * Inner class to just introduce an AOP framework dependency when actually in proxy mode.
	 */
	private static class AopAutoProxyConfigurer {		public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {			// 重點,註冊 InfrastructureAdvisorAutoProxyCreator 的 BeanDefinition,這個是個關鍵類,代理業務bean的操做都靠它了
			AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);

			String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;			if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {
				Object eleSource = parserContext.extractSource(element);				// 重點,註冊一個全局的 TransactionAttributeSource 的BeanDefinition ,用於解析 @Transaction 定義的元數據
				RootBeanDefinition sourceDef = new RootBeanDefinition(						"org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");
				sourceDef.setSource(eleSource);
				sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
				String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);				// 重點,註冊 TransactionInterceptor 的BeanDefinition,這個就是事務真正執行的類,能夠理解爲是事務切面上的通知
				RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);
				interceptorDef.setSource(eleSource);
				interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
				registerTransactionManager(element, interceptorDef);
				interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
				String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);				// 重點,註冊 BeanFactoryTransactionAttributeSourceAdvisor 的BeanDefinition,能夠理解爲事務的切面,
				// 包含了切點(TransactionAttributeSourcePointcut) + 通知(TransactionInterceptor),保存在 ProxyFactory 中,用於生成代理對象
				RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);
				advisorDef.setSource(eleSource);
				advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
				advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
				advisorDef.getPropertyValues().add("adviceBeanName", interceptorName);				if (element.hasAttribute("order")) {
					advisorDef.getPropertyValues().add("order", element.getAttribute("order"));
				}
				parserContext.getRegistry().registerBeanDefinition(txAdvisorBeanName, advisorDef);

				CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);
				compositeDef.addNestedComponent(new BeanComponentDefinition(sourceDef, sourceName));
				compositeDef.addNestedComponent(new BeanComponentDefinition(interceptorDef, interceptorName));
				compositeDef.addNestedComponent(new BeanComponentDefinition(advisorDef, txAdvisorBeanName));
				parserContext.registerComponent(compositeDef);
			}
		}
	}

到這裏,事務配置的加載就結束了,上面的步驟只是將事務的關鍵類變成 BeanDefinition,實際上尚未生成Bean對象的,下面咱們看下BeanDefinition 是如何變成Bean的(這一個步驟不是Spring事務獨有的,是全部BeanDefinition 的共同邏輯),而後是如何生成業務bean代理對象並替換業務bean的。

2. 生成事務代理對象

入口在 1.解析並加載事務配置 列舉的finishBeanFactoryInitialization(beanFactory) 方法中:

	/**
	 * Finish the initialization of this context's bean factory,
	 * initializing all remaining singleton beans.
	 */
	protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {		// Initialize conversion service for this context.
		if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
				beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
			beanFactory.setConversionService(
					beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
		}		// Register a default embedded value resolver if no bean post-processor
		// (such as a PropertyPlaceholderConfigurer bean) registered any before:
		// at this point, primarily for resolution in annotation attribute values.
		if (!beanFactory.hasEmbeddedValueResolver()) {
			beanFactory.addEmbeddedValueResolver(new StringValueResolver() {				@Override
				public String resolveStringValue(String strVal) {					return getEnvironment().resolvePlaceholders(strVal);
				}
			});
		}		// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
		String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);		for (String weaverAwareName : weaverAwareNames) {
			getBean(weaverAwareName);
		}		// Stop using the temporary ClassLoader for type matching.
		beanFactory.setTempClassLoader(null);		// Allow for caching all bean definition metadata, not expecting further changes.
		beanFactory.freezeConfiguration();		// 重點,開始初始化全部非懶加載的bean
		beanFactory.preInstantiateSingletons();
	}

beanFactory.preInstantiateSingletons() 具體方法以下:

public void preInstantiateSingletons() throws BeansException {		if (this.logger.isDebugEnabled()) {			this.logger.debug("Pre-instantiating singletons in " + this);
		}		// Iterate over a copy to allow for init methods which in turn register new bean definitions.
		// While this may not be part of the regular factory bootstrap, it does otherwise work fine.將全部註冊的BeanDefinition 名稱保存到起來
		List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);		// Trigger initialization of all non-lazy singleton beans...
		for (String beanName : beanNames) {			// 獲取 BeanDefinition
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);			// bean定義不是抽象、懶加載並且是單例bean
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {				// 工廠bean特有邏輯,這不是咱們的關注點,咱們關注點是else的 getBean(beanName);
				if (isFactoryBean(beanName)) {					final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);					boolean isEagerInit;					if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
						isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {							@Override
							public Boolean run() {								return ((SmartFactoryBean<?>) factory).isEagerInit();
							}
						}, getAccessControlContext());
					}					else {
						isEagerInit = (factory instanceof SmartFactoryBean &&
								((SmartFactoryBean<?>) factory).isEagerInit());
					}					if (isEagerInit) {
						getBean(beanName);
					}
				}				else {					// 重點,將 BeanDefinition 建立成bean的核心方法,同時也是執行 BeanPostProcessor 的入口
					getBean(beanName);
				}
			}
		}		// Trigger post-initialization callback for all applicable beans...
		for (String beanName : beanNames) {
			Object singletonInstance = getSingleton(beanName);			if (singletonInstance instanceof SmartInitializingSingleton) {				final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged(new PrivilegedAction<Object>() {						@Override
						public Object run() {
							smartSingleton.afterSingletonsInstantiated();							return null;
						}
					}, getAccessControlContext());
				}				else {
					smartSingleton.afterSingletonsInstantiated();
				}
			}
		}
	}

getBean(beanName) 方法比較複雜,這裏只列舉出關鍵點:AbstractAutowireCapableBeanFactory 的 initializeBean方法,全部bean的建立都繞不開這個方法,這個方法是執行實現了 BeanPostProcessor 的bean的邏輯:

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged(new PrivilegedAction<Object>() {				@Override
				public Object run() {
					invokeAwareMethods(beanName, bean);					return null;
				}
			}, getAccessControlContext());
		}		else {
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;		if (mbd == null || !mbd.isSynthetic()) {			// 執行 BeanPostProcessor 的 postProcessBeforeInitialization 方法
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}		try {
			invokeInitMethods(beanName, wrappedBean, mbd);
		}		catch (Throwable ex) {			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}		if (mbd == null || !mbd.isSynthetic()) {			// 重點,InfrastructureAdvisorAutoProxyCreator 實現了BeanPostProcessor 接口,因此這裏會調用 InfrastructureAdvisorAutoProxyCreator 的postProcessBeforeInitialization 方法,
			// wrappedBean 是生成代理後對象,wrappedBean 會替換掉傳入的bean,若是當前bean須要事務,wrappedBean就是被JDK或者CGLIB代理後的bean
			wrappedBean = postProcessAfterInitialization(wrappedBean, beanName);
		}		return wrappedBean;
	}

InfrastructureAdvisorAutoProxyCreator 的 postProcessAfterInitialization 定義在父類:AbstractAutoProxyCreator,AbstractAutoProxyCreator這個類同時是Spring AOP處理的入口,並非說事務處理獨有的,具體實現以下:

	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(), beanName);			if (!this.earlyProxyReferences.contains(cacheKey)) {				// 重點,AOP生成代理對象的入口,這裏也會生成事務代理對象
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}		return bean;
	}	
	// 從Spring容器中獲取全部切面bean,並判斷是否在切面中,若是是的話生成一個代理對象,怎麼代理由具體的切面定義
	protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {		if (beanName != null && this.targetSourcedBeans.contains(beanName)) {			return bean;
		}		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {			return bean;
		}		// 這裏就是用來判斷當前bean 能不能代理
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {			this.advisedBeans.put(cacheKey, Boolean.FALSE);			return bean;
		}		// 首先查找切面Bean,對於本篇文章就是咱們上面定義的 BeanFactoryTransactionAttributeSourceAdvisor 的 BeanDefinition,注意:實際應用場景確定不只只有一個切面的。
		// spring如今只有BeanDefinition,這個方法先經過獲取切面 beanNames ,而後再調用上面的 getBean 方法生成 BeanFactoryTransactionAttributeSourceAdvisor bean對象
		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());			// 返回代理後的bean
			return proxy;
		}		this.advisedBeans.put(cacheKey, Boolean.FALSE);		// 不代理,返回原始bean
		return bean;
	}	
	// 獲取切面bean,先經過獲取切面BeanNames ,而後經過獲取bean
	protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
		List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);		if (advisors.isEmpty()) {			return DO_NOT_PROXY;
		}		return advisors.toArray();
	}	
	protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {		// 這個方法就是獲取切面bean,首先從容器中獲取實現了 Advisor 的beanNames,而後經過beanName再獲取Bean,
		// 對於本篇文章只定義了一個事務切面,因此這裏返回的結果是 BeanFactoryTransactionAttributeSourceAdvisor Bean對象
		List<Advisor> candidateAdvisors = findCandidateAdvisors();		// 判斷當前bean是否能被切面應用,判斷規則在下面有說明
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
		extendAdvisors(eligibleAdvisors);		if (!eligibleAdvisors.isEmpty()) {
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}		return eligibleAdvisors;
	}	
	// findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName) 具體實現邏輯在org.springframework.aop.support.AopUtils#findAdvisorsThatCanApply 
	public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {		if (candidateAdvisors.isEmpty()) {			return candidateAdvisors;
		}
		List<Advisor> eligibleAdvisors = new LinkedList<Advisor>();		for (Advisor candidate : candidateAdvisors) {			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;
	}	
	//  請注意,這個方法是AOP通用判斷是否能應用切面的方法,不是事務處理獨有的
	public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
		Assert.notNull(pc, "Pointcut must not be null");		// 首先判斷類能不能匹配上,匹配不上就返回false, BeanFactoryTransactionAttributeSourceAdvisor 的切點類:
		// TransactionAttributeSourcePointcut,默認ClassFilter 返回true,因此這裏不會進if
		if (!pc.getClassFilter().matches(targetClass)) {			return false;
		}		// 而後判斷方法匹配,TransactionAttributeSourcePointcut 經過繼承關係能夠看到不是 MethodMatcher.TRUE,因此不會進if
		MethodMatcher methodMatcher = pc.getMethodMatcher();		if (methodMatcher == MethodMatcher.TRUE) {			// No need to iterate the methods if we're matching any method anyway...
			return true;
		}		// 判斷是否是引介方法匹配,什麼是引介加強:爲目標類追加方法,屬於類的加強,
		// 而 PointcutAdvisor 屬於攔截目標類的方法並加強,TransactionAttributeSourcePointcut  是 PointcutAdvisor 的子類,不屬於引介加強
		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) {
			Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);			for (Method method : methods) {				// 對於事務而言,判斷條件重點在 TransactionAttributeSourcePointcut 的 matches 方法
				if ((introductionAwareMethodMatcher != null &&
						introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
						methodMatcher.matches(method, targetClass)) {					return true;
				}
			}
		}		return false;
	} 	// TransactionAttributeSourcePointcut 的 matches 方法核心邏輯在 SpringTransactionAnnotationParser#parseTransactionAnnotation(java.lang.reflect.AnnotatedElement)
	// 注意:只會判斷 public 的方法,判斷有沒有 Transactional 註解;判斷的順序爲:先判斷方法上面有沒有,再判斷類上面有沒有。
	// 判斷核心就是看方法或類上面有沒有 Transactional 註解,有這個註解就解析這個註解的元數據
	public TransactionAttribute parseTransactionAnnotation(AnnotatedElement ae) {
		AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ae, Transactional.class);		if (attributes != null) {			return parseTransactionAnnotation(attributes);
		}		else {			return null;
		}
	}	// 解析 Transactional  註解元數據
	protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
		RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
		Propagation propagation = attributes.getEnum("propagation");
		rbta.setPropagationBehavior(propagation.value());
		Isolation isolation = attributes.getEnum("isolation");
		rbta.setIsolationLevel(isolation.value());
		rbta.setTimeout(attributes.getNumber("timeout").intValue());
		rbta.setReadOnly(attributes.getBoolean("readOnly"));
		rbta.setQualifier(attributes.getString("value"));
		ArrayList<RollbackRuleAttribute> rollBackRules = new ArrayList<RollbackRuleAttribute>();
		Class<?>[] rbf = attributes.getClassArray("rollbackFor");		for (Class<?> rbRule : rbf) {
			RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);
			rollBackRules.add(rule);
		}
		String[] rbfc = attributes.getStringArray("rollbackForClassName");		for (String rbRule : rbfc) {
			RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);
			rollBackRules.add(rule);
		}
		Class<?>[] nrbf = attributes.getClassArray("noRollbackFor");		for (Class<?> rbRule : nrbf) {
			NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);
			rollBackRules.add(rule);
		}
		String[] nrbfc = attributes.getStringArray("noRollbackForClassName");		for (String rbRule : nrbfc) {
			NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);
			rollBackRules.add(rule);
		}
		rbta.getRollbackRules().addAll(rollBackRules);		return rbta;
	}	// 以上就是 findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName) 的邏輯

	// 下面回到wrapIfNecessary方法,若是當前bean須要生成代理對象,會調用下面的這個方法
	protected Object createProxy(
			Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {		if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
			AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
		}		// 建立代理工廠,用於建立代理bean
		ProxyFactory proxyFactory = new ProxyFactory();
		proxyFactory.copyFrom(this);		// 判斷是否配置了代理目標類,配置了這個選項會所有使用cglib代理
		if (!proxyFactory.isProxyTargetClass()) {			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}			else {
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}		// 把全部的切面類放入 ProxyFactory
		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		proxyFactory.addAdvisors(advisors);
		proxyFactory.setTargetSource(targetSource);
		customizeProxyFactory(proxyFactory);

		proxyFactory.setFrozen(this.freezeProxy);		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}		
		// 開始建立代理bean
		return proxyFactory.getProxy(getProxyClassLoader());
	}

proxyFactory.getProxy(getProxyClassLoader()) 方法實現:

	public Object getProxy(ClassLoader classLoader) {		return createAopProxy().getProxy(classLoader);
	}	
	// createAopProxy方法邏輯,config 其實就是上面的 proxyFactory 對象,這個對象包含了目標對象以及切面類:
	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {		// optimize:代理是否應該執行優化,通常用不上
		// proxyTargetClass:這個屬性爲treu時,無論目標類是否是實現的接口,都使用cglib代理
		// hasNoUserSuppliedProxyInterfaces:是否只使用了Spring支持的代理接口,若是用戶自定義了代理接口不能進行cglib代理
		if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
			Class<?> targetClass = config.getTargetClass();			if (targetClass == null) {				throw new AopConfigException("TargetSource cannot determine target class: " +						"Either an interface or a target is required for proxy creation.");
			}			// 若是目標類是接口或者已經被jdk代理過了,使用jdk代理
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {				return new JdkDynamicAopProxy(config);
			}			// 其餘狀況使用CGLIB代理
			return new ObjenesisCglibAopProxy(config);
		}		// 使用JDK代理
		else {			return new JdkDynamicAopProxy(config);
		}
	}	// ObjenesisCglibAopProxy 的 getProxy(classLoader) 方法,cglib是使用Enhancer建立代理對象的 :
	public Object getProxy(ClassLoader classLoader) {		if (logger.isDebugEnabled()) {
			logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
		}		try {			// 獲取目標類
			Class<?> rootClass = this.advised.getTargetClass();
			Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");			// 代理類的父類,默認是目標類
			Class<?> proxySuperClass = rootClass;			// 若是目標類以及是cglib代理類,
			if (ClassUtils.isCglibProxyClass(rootClass)) {				// 取cglib代理類的父類做爲代理類的父類
				proxySuperClass = rootClass.getSuperclass();				// 獲取代理類的接口追加到當前類的接口集合中
				Class<?>[] additionalInterfaces = rootClass.getInterfaces();				for (Class<?> additionalInterface : additionalInterfaces) {					this.advised.addInterface(additionalInterface);
				}
			}			// 驗證目標類是否能被代理,僅僅是打印日誌,不作其餘處理
			validateClassIfNecessary(proxySuperClass, classLoader);			// 使用Enhancer 來構造cglib代理對象
			Enhancer enhancer = createEnhancer();			if (classLoader != null) {
				enhancer.setClassLoader(classLoader);				if (classLoader instanceof SmartClassLoader &&
						((SmartClassLoader) classLoader).isCla***eloadable(proxySuperClass)) {
					enhancer.setUseCache(false);
				}
			}
			enhancer.setSuperclass(proxySuperClass);
			enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
			enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
			enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));			// 重點,設置回調的類,很重要的一個類 DynamicAdvisedInterceptor,這個類就是應用AOP 通知的地方,對於本篇文章就是應用TransactionInterceptor
			Callback[] callbacks = getCallbacks(rootClass);
			Class<?>[] types = new Class<?>[callbacks.length];			for (int x = 0; x < types.length; x++) {
				types[x] = callbacks[x].getClass();
			}			// fixedInterceptorMap only populated at this point, after getCallbacks call above
			enhancer.setCallbackFilter(new ProxyCallbackFilter(					this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
			enhancer.setCallbackTypes(types);			// 建立代理類的字節碼,並建立實例,實例設置回調
			return createProxyClassAndInstance(enhancer, callbacks);
		}		catch (CodeGenerationException ex) {			throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +					": Common causes of this problem include using a final class or a non-visible class",
					ex);
		}		catch (IllegalArgumentException ex) {			throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +					": Common causes of this problem include using a final class or a non-visible class",
					ex);
		}		catch (Throwable ex) {			// TargetSource.getTarget() failed
			throw new AopConfigException("Unexpected AOP exception", ex);
		}
	}	
// JdkDynamicAopProxy  的 getProxy(classLoader) 方法:public Object getProxy(ClassLoader classLoader) {		if (logger.isDebugEnabled()) {
			logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
		}
		Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
		findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);		return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
	}

經過2. 生成事務代理對象,此時建立的bean就是以及被JDK或者CGLIB代理的類,這一步是Spring AOP通用的處理邏輯,那具體是怎麼運行的呢?

JDK動態代理運行:

	// 本質是調用org.springframework.aop.framework.JdkDynamicAopProxy#invoke方法
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		MethodInvocation invocation;
		Object oldProxy = null;		boolean setProxyContext = false;

		TargetSource targetSource = this.advised.targetSource;
		Class<?> targetClass = null;
		Object target = null;		try {			if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {				// The target does not implement the equals(Object) method itself.
				return equals(args[0]);
			}			else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {				// The target does not implement the hashCode() method itself.
				return hashCode();
			}			else if (method.getDeclaringClass() == DecoratingProxy.class) {				// There is only getDecoratedClass() declared -> dispatch to proxy config.
				return AopProxyUtils.ultimateTargetClass(this.advised);
			}			else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
					method.getDeclaringClass().isAssignableFrom(Advised.class)) {				// Service invocations on ProxyConfig with the proxy config...
				return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
			}

			Object retVal;			if (this.advised.exposeProxy) {				// Make invocation available if necessary.
				oldProxy = AopContext.setCurrentProxy(proxy);
				setProxyContext = true;
			}			// May be null. Get as late as possible to minimize the time we "own" the target,
			// in case it comes from a pool.
			target = targetSource.getTarget();			if (target != null) {
				targetClass = target.getClass();
			}			// 獲取方法的攔截器鏈,對於本篇文章就是關鍵類:BeanFactoryTransactionAttributeSourceAdvisor
			List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);			// Check whether we have any advice. If we don't, we can fallback on direct
			// reflective invocation of the target, and avoid creating a MethodInvocation.
			if (chain.isEmpty()) {				// We can skip creating a MethodInvocation: just invoke the target directly
				// Note that the final invoker must be an InvokerInterceptor so we know it does
				// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
				Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
				retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
			}			else {				// 將全部參數:代理對象,目標對象,方法,參數,攔截器鏈封裝到一個ReflectiveMethodInvocation對象中
				invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);				// 而後調用ReflectiveMethodInvocation的proceed方法,會執行攔截器
				retVal = invocation.proceed();
			}			// Massage return value if necessary.
			Class<?> returnType = method.getReturnType();			if (retVal != null && retVal == target &&
					returnType != Object.class && returnType.isInstance(proxy) &&
					!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {				// Special case: it returned "this" and the return type of the method
				// is type-compatible. Note that we can't help if the target sets
				// a reference to itself in another returned object.
				retVal = proxy;
			}			else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {				throw new AopInvocationException(						"Null return value from advice does not match primitive return type for: " + method);
			}			return retVal;
		}		finally {			if (target != null && !targetSource.isStatic()) {				// Must have come from TargetSource.
				targetSource.releaseTarget(target);
			}			if (setProxyContext) {				// Restore old proxy.
				AopContext.setCurrentProxy(oldProxy);
			}
		}
	}

org.springframework.aop.framework.ReflectiveMethodInvocation#proceed 方法:

	public Object proceed() throws Throwable {		// 全部攔截器調用完成,通常狀況是沒有匹配到任意的攔截器,這裏會執行目標類自己的方法
		if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {			return invokeJoinpoint();
		}		
		// 獲取攔截器鏈中的第一個攔截器
		Object interceptorOrInterceptionAdvice =				this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);		// 通知器或通知是動態匹配方法攔截器類型,對於本篇文章,interceptorOrInterceptionAdvice 是TransactionInterceptor對象,
		// 全部走的是else,直接執行TransactionInterceptor的invoke方法
		if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {			// 動態匹配方法攔截器
			InterceptorAndDynamicMethodMatcher dm =
					(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;			// 匹配成功就執行對應的攔截器
			if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {				return dm.interceptor.invoke(this);
			}			else {				// 若是不匹配,就跳過此攔截器,遞歸執行下一個攔截器
				return proceed();
			}
		}		else {			// 若是是一個interceptor,直接調用這個interceptor對應的方法
			return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
		}
	}

CGLIB代理運行:

	// 其實就是建立代理對象時設置的回調類DynamicAdvisedInterceptor
	private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {		private final AdvisedSupport advised;		public DynamicAdvisedInterceptor(AdvisedSupport advised) {			this.advised = advised;
		}		// 主要是這個方法執行攔截,處理邏輯大體和JDK動態代理差很少,都是獲取攔截器鏈,
		// 而後構建ReflectiveMethodInvocation的子類CglibMethodInvocation對象,
		// 執行ReflectiveMethodInvocation的proceed方法
		@Override
		public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
			Object oldProxy = null;			boolean setProxyContext = false;
			Class<?> targetClass = null;
			Object target = null;			try {				if (this.advised.exposeProxy) {					// Make invocation available if necessary.
					oldProxy = AopContext.setCurrentProxy(proxy);
					setProxyContext = true;
				}				// May be null. Get as late as possible to minimize the time we
				// "own" the target, in case it comes from a pool...
				target = getTarget();				if (target != null) {
					targetClass = target.getClass();
				}				// 獲取方法的攔截器鏈,對於本篇文章就是關鍵類:BeanFactoryTransactionAttributeSourceAdvisor
				List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
				Object retVal;				// Check whether we only have one InvokerInterceptor: that is,
				// no real advice, but just reflective invocation of the target.
				if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {					// We can skip creating a MethodInvocation: just invoke the target directly.
					// Note that the final invoker must be an InvokerInterceptor, so we know
					// it does nothing but a reflective operation on the target, and no hot
					// swapping or fancy proxying.
					Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
					retVal = methodProxy.invoke(target, argsToUse);
				}				else {					// 將參數封裝成CglibMethodInvocation對象並執行proceed方法,CglibMethodInvocation 實際上是ReflectiveMethodInvocation的子類,能夠理解爲ReflectiveMethodInvocation是模板類,CglibMethodInvocation經過重寫了部分方法,proceed是兩種代理處理的共同邏輯
					retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
				}
				retVal = proce***eturnType(proxy, target, method, retVal);				return retVal;
			}			finally {				if (target != null) {
					releaseTarget(target);
				}				if (setProxyContext) {					// Restore old proxy.
					AopContext.setCurrentProxy(oldProxy);
				}
			}
		}		@Override
		public boolean equals(Object other) {			return (this == other ||
					(other instanceof DynamicAdvisedInterceptor &&							this.advised.equals(((DynamicAdvisedInterceptor) other).advised)));
		}		/**
		 * CGLIB uses this to drive proxy creation.
		 */
		@Override
		public int hashCode() {			return this.advised.hashCode();
		}		protected Object getTarget() throws Exception {			return this.advised.getTargetSource().getTarget();
		}		protected void releaseTarget(Object target) throws Exception {			this.advised.getTargetSource().releaseTarget(target);
		}
	}

事務的最終執行類 TransactionInterceptor 的invoke 方法:

	public Object invoke(final 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...
		return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {			@Override
			public Object proceedWithInvocation() throws Throwable {				// 事務執行完畢後調用鏈繼續向下執行
				return invocation.proceed();
			}
		});
	}	protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation)
			throws Throwable {		// 獲取當前方法的事務屬性
		final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);		// 獲取事務管理器
		final PlatformTransactionManager tm = determineTransactionManager(txAttr);		// 方法名
		final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);		// 若是方法沒有事務或者事務管理器不屬於CallbackPreferringPlatformTransactionManager,CallbackPreferringPlatformTransactionManager須要回調函數來實現事務流程,而咱們經常使用的DataSourceTransactionManager就不是CallbackPreferringPlatformTransactionManager
		if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {			// 建立TransactionInfo事務對象,事務的管理都是經過TransactionInfo對象來完成,這裏建立事務會使用到Spring的事務隔離級別,具體的邏輯能夠自行查看
			TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
			Object retVal = null;			try {				// 攔截器鏈繼續向下執行
				retVal = invocation.proceedWithInvocation();
			}			catch (Throwable ex) {				// 拋出異常時提交或者回滾事務
				completeTransactionAfterThrowing(txInfo, ex);				throw ex;
			}			finally {				// 重置TransactionInfo 的 ThreadLocal
				cleanupTransactionInfo(txInfo);
			}			// 提交/回滾事務
			commitTransactionAfterReturning(txInfo);			return retVal;
		}		// else使用的是CallbackPreferringPlatformTransactionManager,
		else {			// .......略
		}
	}
總結

以上就是事務應用到業務場景中的原理,能夠簡單理解:Spring事務是在Spring AOP的基礎上開發的,關注關鍵類:TransactionInterceptor 的實現就好了,不論是JDK動態代理仍是CGLIB代理都是要用到這個類去提交/回滾事務的。若有錯誤歡迎指出。

歡迎收藏點贊關注!共同進步~ :)更多技術乾貨可關注【Java爛豬皮】公衆號

相關文章
相關標籤/搜索