21

【源码讲解】Spring事务是如何应用到你的业务场景中的?

 3 years ago
source link: http://www.cnblogs.com/winkin/p/13667568.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

初衷

日常开发中经常用到@Transaction注解,那你知道它是怎么应用到你的业务代码中的吗?本篇文章将从以下两个方面阐述Spring事务实现原理:

  1. 解析并加载事务配置:本质上是解析xml文件将标签加载成 BeanDefinition 对象;
  2. 生成事务代理对象并运行:本质上是Spring AOP在事务这块的应用,将业务Bean替换成事务代理对象(JdkDynamicAopProxy:JDK代理,CglibAopProxy:CGLIB代理);

本文使用的源码版本是Spring 4.3.18.RELEASE,使用的是XML开启事务。

关键类

这里列出几个核心类,提前留个印象,后面会讲解什么时候调用

  1. XmlBeanDefinitionReader 加载XML定义的Bean入口
  2. TxNamespaceHandler 解析XML中的事务标签: advice、annotation-driven等;
  3. InfrastructureAdvisorAutoProxyCreator 该类实现了 BeanPostProcessor 接口(可以在Bean初始化后进行替换),是生成事务代理类并替换的关键类;
  4. AnnotationTransactionAttributeSource 用来解析业务方法使用注解 @Transaction 上的配置,提供给 TransactionInterceptor 使用;
  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).isClassReloadable(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 = processReturnType(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代理都是要用到这个类去提交/回滚事务的。如有错误欢迎指出。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK