Spring事务源码:创建代理类

Posted jchen104

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring事务源码:创建代理类相关的知识,希望对你有一定的参考价值。

参考文章:

《Spring事务源码解析之tx:annotation-driven标签解析》

《Spring 源码解析—事务执行》

参考资料:

《Spring AOP源码:开启注解读取》

《Spring AOP源码2:查找增强器》

《Spring AOP源码3:实现代理》

        写在开头:本文为个人学习笔记,内容比较随意,夹杂个人理解,如有错误,欢迎指正。

前言

        本文我们介绍下Spring中的事务管理的源码,Spring的事务管理主要有申明式事务与编程式事务这两种,如果对这两种方式不了解的朋友可以先看下这篇文章(《Spring事务管理(详解+实例)》)然后再来深入源码分析。

       我们通过如下方式开启事务,由于申明式事务的注入方式式基于代理方式实现的,因此这里也建议先了解下AOP的源码,这部分我前文已经做了完整的介绍,因此下文将不会对AOP的功能做深入的解析,有需要的朋友可以看下我之前AOP的文章。

<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>

目录

前言

一、AnnotationDrivenBeanDefinitionParser

        1、TxNamespaceHandler

        2、AnnotationDrivenBeanDefinitionParser

二、、AopAutoProxyConfigurer

        1、注册自动代理创建器

        1.1、注册InfrastructureAdvisorAutoProxyCreator

         1.2、设置proxy-target-class和expose-proxy属性

        1.3、注册ComponentDefinition

        2、注册了事务管理器等Bean

        2.1、创建AnnotationTransactionAttributeSource

        2.2、创建TransactionInterceptor

        2.3、创建BeanFactoryTransactionAttributeSourceAdvisor

三、代理对象的创建

        1、InfrastructureAdvisorAutoProxyCreator

        2、canapply

        2.1、getMethodMatcher

        2.2、getTransactionAttribute 

        2.3、computeTransactionAttribute

        2.4、findTransactionAttribute

        2.5、parseTransactionAnnotation

补充

        事务仅对 public 方法有效


一、AnnotationDrivenBeanDefinitionParser

        在介绍IOC时我们讲过Spring通过spring.handlers配置文件处理自定义命名空间节点(《Spring IOC:parseCustomElement调用链》),从下面的配置中可以看出TX标签由TxNamespaceHandler类解析。

http\\://www.springframework.org/schema/tx=org.springframework.transaction.config.TxNamespaceHandler

        1、TxNamespaceHandler

        TxNamespaceHandler中的init方法针对不通的属性配置实例化不通的解析对象,这里我们使用了annotation-driven,因此实例化的对象为AnnotationDrivenBeanDefinitionParser。

	@Override
	public void init() 
		registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());
		registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
		registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());
	

        2、AnnotationDrivenBeanDefinitionParser

        下面就来到了AnnotationDrivenBeanDefinitionParser的parse方法,因为Spring事务管理也是基于创建代理类来实现的,因此和AOP一样首先需要创建代理创建器。

	@Override
	public BeanDefinition parse(Element element, ParserContext parserContext) 
		registerTransactionalEventListenerFactory(parserContext);
		String mode = element.getAttribute("mode");
        // 判断是否配置了mode属性且为aspectj,满足条件则走aop切面的方式管理事务
		if ("aspectj".equals(mode)) 
			registerTransactionAspect(element, parserContext);
		
		else 
            // 默认方式,配置自动代理创建器
			AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
		
		return null;
	

二、、AopAutoProxyConfigurer

        创建代理创建器的流程可以拆解成如下几个步骤,我们下面分别对其进行分析。

	private static class AopAutoProxyConfigurer 

		public static void configureAutoProxyCreator(Element element, ParserContext parserContext) 
			1、注册自动代理创建器
            2、注册了事务管理器等Bean			
		
	

        1、注册自动代理创建器

        configureAutoProxyCreator调用registerAutoProxyCreatorIfNecessary注册自动代理创建器

		public static void configureAutoProxyCreator(Element element, ParserContext parserContext) 
            // 1、创建代理创建器
			AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);
            2、注册了AnnotationTransactionAttributeSource、TransactionInterceptor和BeanFactoryTransactionAttributeSourceAdvisor			
		

        registerAutoProxyCreatorIfNecessary分为三个步骤

        (1)注册InfrastructureAdvisorAutoProxyCreator

        (2)设置proxy-target-class和expose-proxy属性

        (3)注册ComponentDefinition

	public static void registerAutoProxyCreatorIfNecessary(
			ParserContext parserContext, Element sourceElement) 
        // 向容器中注册InfrastructureAdvisorAutoProxyCreator
		BeanDefinition beanDefinition = AopConfigUtils.registerAutoProxyCreatorIfNecessary(
				parserContext.getRegistry(), parserContext.extractSource(sourceElement));
        // 设置proxy-target-class和expose-proxy配置
		useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
        // 注册ComponentDefinition
		registerComponentIfNecessary(beanDefinition, parserContext);
	

        1.1、注册InfrastructureAdvisorAutoProxyCreator

        很简单的方法,向容器中注册固定的BeanDefinition。

	public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) 
		return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
	

         1.2、设置proxy-target-class和expose-proxy属性

        解析标签中的proxy-target-class和expose-proxy属性值。proxy-target-class主要控制是使用Jdk代理还是Cglib代理实现,expose-proxy用于控制是否将生成的代理类的实例防御AopContext中,并且暴露给相关子类使用。

    public static final String PROXY_TARGET_CLASS_ATTRIBUTE = "proxy-target-class";
    private static final String EXPOSE_PROXY_ATTRIBUTE = "expose-proxy";

	private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, Element sourceElement) 
		if (sourceElement != null) 
			boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
			if (proxyTargetClass) 
				AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
			
			boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
			if (exposeProxy) 
				AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
			
		
	

        1.3、注册ComponentDefinition

	public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
			"org.springframework.aop.config.internalAutoProxyCreator";
	private static void registerComponentIfNecessary(BeanDefinition beanDefinition, ParserContext parserContext) 
		if (beanDefinition != null) 
			parserContext.registerComponent(
					new BeanComponentDefinition(beanDefinition, AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME));
		
	

        2、注册了事务管理器等Bean

	    public static final String TRANSACTION_ADVISOR_BEAN_NAME =
			"org.springframework.transaction.config.internalTransactionAdvisor";
		public static void configureAutoProxyCreator(Element element, ParserContext parserContext) 
			AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);
			//1、注册自动代理创建器
            AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);

            // 判断容器中有无internalTransactionAdvisor
			String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;
			if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) 
            //2、注册了事务管理器等Bean		
            创建AnnotationTransactionAttributeSource
            创建TransactionInterceptor
            创建BeanFactoryTransactionAttributeSourceAdvisor
                
			
		

        2.1、创建AnnotationTransactionAttributeSource

Object eleSource = parserContext.extractSource(element);
// 创建并注册AnnotationTransactionAttributeSource的BeanDefinition
RootBeanDefinition sourceDef = new RootBeanDefinition(
"org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");
sourceDef.setSource(eleSource);
sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);

        2.2、创建TransactionInterceptor

        这一步创建了TransactionInterceptor的BeanDefinition,并将上一步创建的AnnotationTransactionAttributeSource作为transactionAttributeSource属性注入了进去,这个属性后面创建代理类的时候将会用到。

        另外调用了registerTransactionManager创建了事务管理器。

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);

        registerTransactionManager创建了事务管理器,其实就是添加事务管理器的beanName。

	private static void registerTransactionManager(Element element, BeanDefinition def) 
		def.getPropertyValues().add("transactionManagerBeanName",
				TxNamespaceHandler.getTransactionManagerName(element));
	

         事务管理器的beanName在不指定transaction-manager属性的时候,会默认寻找id固定名为transactionManager的bean作为事务管理器。

    // TxNamespaceHandler.java
	static final String TRANSACTION_MANAGER_ATTRIBUTE = "transaction-manager";
	static final String DEFAULT_TRANSACTION_MANAGER_BEAN_NAME = "transactionManager";
	static String getTransactionManagerName(Element element) 
		return (element.hasAttribute(TRANSACTION_MANAGER_ATTRIBUTE) ?
				element.getAttribute(TRANSACTION_MANAGER_ATTRIBUTE) : DEFAULT_TRANSACTION_MANAGER_BEAN_NAME);
	

        2.3、创建BeanFactoryTransactionAttributeSourceAdvisor

        创建BeanFactoryTransactionAttributeSourceAdvisor的BeanDefinition,同时将前两个步骤中创建的AnnotationTransactionAttributeSource、TransactionInterceptor作为属性添加到当前Bean中,最后注册到容器中。

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")) 
	dvisorDef.getPropertyValues().add("order", element.getAttribute("order"));
	
parserContext.getRegistry().registerBeanDefinition(txAdvisorBeanName, advisorDef);

        总结一下,这两部其实主要是注册了InfrastructureAdvisorAutoProxyCreator与BeanFactoryTransactionAttributeSourceAdvisor,可以从名字看出来一个是代理自动创建器,一个是增强器。

三、代理对象的创建

        1、InfrastructureAdvisorAutoProxyCreator

        InfrastructureAdvisorAutoProxyCreator类的继承关系如下图,可以发现其和我们之前介绍AOP时提到的AnnotationAwareAspectJAutoProxyCreator一样继承了AbstractAdvisorAutoProxyCreator。

          抽象类AbstractAdvisorAutoProxyCreator继承了BeanPostProcessor接口,因此在Bean实例化的时候会去为其创建代理对象。这部分内容如果不熟悉可以看下我之前的文章(《Spring IOC:bean的生命周期与@Autowire(3)》《Spring AOP源码2:查找增强器》

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException 
    if (bean != null) 
        // 如果是普通bean,则返回beanName,如果是FactoryBean,则返回加上前缀&的&beanName
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        // 判断当前bean是否需要被代理,如果需要则进行封装(earlyProxyReferences中缓存的是已经创建好的代理对象)
        if (!this.earlyProxyReferences.contains(cacheKey)) 
            return wrapIfNecessary(bean, beanName, cacheKey);
        
    
    return bean;

        2、canapply

        在创建代理类时,会先查找能够应用在当前bean上的增强器,这部分内容我们前文有过介绍就不赘述了,这里直接从如何判断是否适配的判断方法canapply来讲起。

public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) 
    // 判断引介增强是否匹配
    if (advisor instanceof IntroductionAdvisor) 
        return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
    
    else if (advisor instanceof PointcutAdvisor) 
        PointcutAdvisor pca = (PointcutAdvisor) advisor;
        /* 判断当前增强是否可以应用在当前bean上 */
        return canApply(pca.getPointcut(), targetClass, hasIntroductions);
    
    else 
        return true;
    

        这里的advisor就是我们的增强器BeanFactoryTransactionAttributeSourceAdvisor,而pca.getPointcut()就是获取其内部创建的TransactionAttributeSourcePointcut。

	@Override
	public Pointcut getPointcut() 
		return this.pointcut;
	

	private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() 
		@Override
		protected TransactionAttributeSource getTransactionAttributeSource() 
			return transactionAttributeSource;
		
	;

        该对象重写了getTransactionAttributeSource方法,获取的就是BeanFactoryTransactionAttributeSourceAdvisor在注册时添加的transactionAttributeSource属性,其实现类为AnnotationTransactionAttributeSource。 

        // configureAutoProxyCreator方法
        RootBeanDefinition sourceDef = new RootBeanDefinition(
            "org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");
        sourceDef.setSource(eleSource);
        sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
        String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);
        advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));

        继续往下深入,调用pc.getMethodMatcher()获取方法匹配器,这里的pc就是上文中的TransactionAttributeSourcePointcut类。

    public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) 
		Assert.notNull(pc, "Pointcut must not be null");
        // 获取当前Advisor的CalssFilter,并且调用其matches()方法判断当前切点表达式是否与目标bean匹配,
        // 这里ClassFilter指代的切点表达式主要是当前切面类上使用的@Aspect注解中所指代的切点表达式
		if (!pc.getClassFilter().matches(targetClass)) 
			return false;
		
 
        // 判断如果当前Advisor所指代的方法的切点表达式如果是对任意方法都放行,则直接返回
		MethodMatcher methodMatcher = pc.getMethodMatcher();
		if (methodMatcher == MethodMatcher.TRUE) 
			// No need to iterate the methods if we're matching any method anyway...
			return true;
		
 
		IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
		if (methodMatcher instanceof IntroductionAwareMethodMatcher) 
			introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
		
 
        // 获取目标类的所有接口
		Set<Class<?>> classes = new LinkedHashSet<Class<?>>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
		classes.add(targetClass);
        // 遍历目标类上的接口方法
		for (Class<?> clazz : classes) 
			Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
			for (Method method : methods) 
                // 使用matches判断能否作用于该方法上
				if ((introductionAwareMethodMatcher != null &&
						introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
						methodMatcher.matches(method, targetClass)) 
					return true;
				
			
		
 
		return false;
	

        2.1、getMethodMatcher

        TransactionAttributeSourcePointcut的getMethodMatcher方法是在它的父类StaticMethodMatcherPointcut中实现的。

public final MethodMatcher getMethodMatcher() 
    return this;

        该方法直接返回了this,也就是下面methodMatcher.matches方法就是调用TransactionAttributeSourcePointcut的matches方法。getTransactionAttributeSource即我们之前说过的AnnotationTransactionAttributeSource,getTransactionAttribute则是调用的其父类AbstractFallbackTransactionAttributeSource的方法。

public boolean matches(Method method, Class<?> targetClass) 
    if (TransactionalProxy.class.isAssignableFrom(targetClass)) 
        return false;
    
    TransactionAttributeSource tas = getTransactionAttributeSource();
    return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);

        2.2、getTransactionAttribute 

         getTransactionAttribute中判断有无缓存,如果缓存不存在则调用computeTransactionAttribute方法查找事务属性,获取后进行缓存。

public TransactionAttribute getTransactionAttribute(Method method, Class<?> targetClass) 
    if (method.getDeclaringClass() == Object.class) 
        return null;
    
    // 先查询缓存
    Object cacheKey = getCacheKey(method, targetClass);
    Object cached = this.attributeCache.get(cacheKey);
    if (cached != null) 
        if (cached == NULL_TRANSACTION_ATTRIBUTE) 
            return null;
        
        else 
            return (TransactionAttribute) cached;
        
    
    else 
        // 获取事务属性 
        TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
        // 事务属性不存在
        if (txAttr == null) 
            this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
        
        else 
            String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass);
            if (txAttr instanceof DefaultTransactionAttribute) 
                ((DefaultTransactionAttribute) txAttr).setDescriptor(methodIdentification);
            
            if (logger.isDebugEnabled()) 
                logger.debug("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);
            
            // 将解析好的事务属性存入缓存
            this.attributeCache.put(cacheKey, txAttr);
        
        return txAttr;
    

        2.3、computeTransactionAttribute

         computeTransactionAttribute方法会依次从方法上和类上查找事务申明,使用的是findTransactionAttribute方法。

        这里注意下第一行的内容,只对public的方法可继续往下走,这就解释了为什么事务只在public方法上生效。

protected TransactionAttribute computeTransactionAttribute(Method method, Class<?> targetClass) 
    if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) 
        return null;
    
    Class<?> userClass = ClassUtils.getUserClass(targetClass);
    // method为接口中的方法,specificMethod为具体类中的方法
    Method specificMethod = ClassUtils.getMostSpecificMethod(method, userClass);
    specificMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
    // 查看方法中是否存在事务声明 
    TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
    if (txAttr != null) 
        return txAttr;
    
    // 查看方法所在类中是否存在事务声明 
    txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
    if (txAttr != null && ClassUtils.isUserLevelMethod(method)) 
        return txAttr;
    
    if (specificMethod != method) 
        // 查看接口方法中是否存在事务声明
        txAttr = findTransactionAttribute(method);
        if (txAttr != null) 
            return txAttr;
        
        // 查看接口类中是否存在事务声明
        txAttr = findTransactionAttribute(method.getDeclaringClass());
        if (txAttr != null && ClassUtils.isUserLevelMethod(method)) 
            return txAttr;
        
    
    return null;

        2.4、findTransactionAttribute

        findTransactionAttribute方法遍历所有的事务注解解析器,判断哪一个能用来进行解析,这里默认使用的是Spring的事务注解解析器SpringTransactionAnnotationParser。

protected TransactionAttribute findTransactionAttribute(Method method) 
    return determineTransactionAttribute(method);


protected TransactionAttribute findTransactionAttribute(Class<?> clazz) 
    return determineTransactionAttribute(clazz);


protected TransactionAttribute determineTransactionAttribute(AnnotatedElement ae) 
    if (ae.getAnnotations().length > 0) 
        // 遍历事务注解解析器
        for (TransactionAnnotationParser annotationParser : this.annotationParsers) 
            // 解析事务注解
            TransactionAttribute attr = annotationParser.parseTransactionAnnotation(ae);
            if (attr != null) 
                return attr;
            
        
    
    return null;


        this.annotationParsers是在AnnotationTransactionAttributeSource类初始化的时候初始化的

public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) 
    this.publicMethodsOnly = publicMethodsOnly;
    this.annotationParsers = new LinkedHashSet<TransactionAnnotationParser>(2);
    // 添加Spring事务注解解析器
    this.annotationParsers.add(new SpringTransactionAnnotationParser());
    // 添加JTA事务注解解析器
    if (jta12Present)  
        this.annotationParsers.add(new JtaTransactionAnnotationParser());
    
    // 添加EJB事务注解解析器
    if (ejb3Present) 
        this.annotationParsers.add(new Ejb3TransactionAnnotationParser());
    


        2.5、parseTransactionAnnotation

        annotationParser.parseTransactionAnnotation调用了SpringTransactionAnnotationParser的parseTransactionAnnotation方法,内部又调用了parseTransactionAnnotation。

public TransactionAttribute parseTransactionAnnotation(AnnotatedElement ae) 
    AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ae, Transactional.class);
    if (attributes != null) 
        // 解析事务注解属性
        return parseTransactionAnnotation(attributes);
    
    else 
        return null;
    

         parseTransactionAnnotation方法则解析了解析注解@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;

        到这里,我们就找除了适配于当前Bean的增强,结合之前AOP的内容,整个步骤结束后会生成该Bean的代理类,在方法执行时调用的事务的生效正是由代理类来完成的,具体的事务控制我们将在下文讲解。

补充

        事务仅对 public 方法有效

        在本文内容的computeTransactionAttribute方法中,第一行在读取注解上的属性方法中,会优先判断方法是否是 public,如果不是 public,就不会读取事务配置信息。

        因此@Transactional注解只能在public方法上生效。

如何知道使用的对象是spring的代理类

摘要:在项目中,涉及到同一个类中一个方法调用另外一个方法,并且两个方法的事务不相关,
这里面涉及到一个事务切换的问题,一般的方法没问题,根据通过aop注解在方法上通过加注解标识,
答案是:通过spring aop类里面的AopContext类获取当前类的代理对象,
这样就能切换对应的事务管理器了,具体做法如下:

(1).在applicationContext.xml文件中配置如下:

[html] view plain copy
<!-- 开启暴露Aop代理到ThreadLocal支持 -->
<aop:aspectj-autoproxy expose-proxy="true"/>

(2).在需要切换的地方获取代理对象,再调用对应的方法,如下:

[java] view plain copy
((类名) AopContext.currentProxy()).方法();

(3).注意,这里需要被代理对象使用的方法必须是public类型的方法,不然获取不到代理对象,会报下面的错误:

[java] view plain copy
java.lang.IllegalStateException: Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available.
开启暴露AOP代理即可.

因为开启事务和事务回滚,实际这个过程是aop代理帮忙完成的,当调用一个方法时,它会先检查时候有事务,有则开启事务,
当调用本类的方法是,它并没有将其视为proxy调用,而是方法的直接调用,所以也就没有检查该方法是否含有事务这个过程,
那么本地方法调用的事务也就无效了。
参考技术A 在application.yml中有以下配置
spring:
aop:
#auto: true #默认为true,可省略
proxy-target-class: true # 默认为false即JDK动态代理,我们一般要设为true,使用CGLIB代理
这种方式只能将代理模式修改为了CGLIG,但是不能设置暴露cglib代理的目标对象。

以上是关于Spring事务源码:创建代理类的主要内容,如果未能解决你的问题,请参考以下文章

Spring AOP源码剖析

Spring AOP源码剖析

如何知道使用的对象是spring的代理类

Spring事务常见的坑

61 张图,剖析 Spring 事务,就是要钻到底!

Spring事务源码