Spring事务管理(二):Spring生成事务代理增强类源码分析

以SpringBoot为例,看下SpringBoot是怎么做的。

看着代码很复杂,但是其实我们只关注跟事务相关的就行了,其他的只做了解,等事务的搞明白了,回过头来再研究其他的,事半功倍,我们还可以借助事务的初始化过程,来了解Spring内部加载是怎么实现的!!!

一、/META-INF/spring.factories

要想实现某个功能,首先要做的肯定是把bean加载到容器中,Spring通过spring.factories的方式可以加载一些特定的bean

关于事务的bean请看下图:

TransactionAutoConfiguration、JtaAutoConfiguration

二、TransactionAutoConfiguration

@Configuration
// 类路径下包含PlatformTransactionManager本类生效
@ConditionalOnClass({PlatformTransactionManager.class})
// 在以下四个类本加载后生效
@AutoConfigureAfter({JtaAutoConfiguration.class, HibernateJpaAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, Neo4jDataAutoConfiguration.class})
@EnableConfigurationProperties({TransactionProperties.class})
public class TransactionAutoConfiguration {

    // 内部类
    @Configuration
    @ConditionalOnBean({PlatformTransactionManager.class})
    @ConditionalOnMissingBean({AbstractTransactionManagementConfiguration.class})
    public static class EnableTransactionManagementConfiguration {

        @Configuration
        // 非常重要的事务注解,下一步要进入这个注解看
        @EnableTransactionManagement(proxyTargetClass = true)
        // matchIfMissing 为true,因为默认是没有配置的,所以spring默认走的是cglib代理
        @ConditionalOnProperty(prefix = "spring.aop",name = {"proxy-target-class"},
            havingValue = "true",
            matchIfMissing = true)
        public static class CglibAutoProxyConfiguration {
            ...
        }

        @Configuration
        // 非常重要的事务注解,下一步要进入这个注解看
        @EnableTransactionManagement(proxyTargetClass = false)
        @ConditionalOnProperty(prefix = "spring.aop",name = {"proxy-target-class"},
            havingValue = "false",
            matchIfMissing = false)
        public static class JdkDynamicAutoProxyConfiguration {
            ...
        }
    }

    @Configuration
    // 当能够唯一确定一个PlatformTransactionManager bean时才生效
    @ConditionalOnSingleCandidate(PlatformTransactionManager.class)
    public static class TransactionTemplateConfiguration {
        ...
    }    

}

三、@EnableTransactionManagement

到这里我们第一个问题已经有答案了,AdviceMode 默认使用的是PROXY,同一个类中方法调用,拦截器不会生效,所以我们在同一类中即使调用一个事务方法,方法拦截器不会生效,事务就不会生效。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({TransactionManagementConfigurationSelector.class})
public @interface EnableTransactionManagement {
    // proxyTargetClass = false表示是JDK动态代理支持接口代理。true表示是Cglib代理支持子类继承代理。
    boolean proxyTargetClass() default false;
    // 事务通知模式(切面织入方式),默认代理模式(同一个类中方法互相调用拦截器不会生效),可以选择增强型AspectJ
    AdviceMode mode() default AdviceMode.PROXY;

    // 连接点上有多个通知时,排序,默认最低。值越大优先级越低。
    int order() default 2147483647;
}

继续往下看:

这里通过@Import导入了TransactionManagementConfigurationSelector类

四、TransactionManagementConfigurationSelector

如上图所示,TransactionManagementConfigurationSelector继承自AdviceModeImportSelector实现了ImportSelector接口

  • 给容器中注册一个 InfrastructureAdvisorAutoProxyCreator 组件;利用后置处理器机制在对象创建以后,包装对象,返回一个代理对象(增强器),代理对象执行方法利用拦截器链进行调用
  • ProxyTransactionManagementConfiguration:就是一个配置类,定义了事务增强器。
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
    public TransactionManagementConfigurationSelector() {
    }

    protected String[] selectImports(AdviceMode adviceMode) {
        switch(adviceMode) {
        // 默认会走这里,载入了AutoProxyRegistrar、ProxyTransactionManagementConfiguration2个类
        case PROXY:
            return new String[]{AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()};
        case ASPECTJ:
            return new String[]{"org.springframework.transaction.aspectj.AspectJTransactionManagementConfiguration"};
        default:
            return null;
        }
    }
}

4.1、AutoProxyRegistrar

实现了ImportBeanDefinitionRegistrar接口,重写registerBeanDefinitions方法,源码如下:

最终调用的是:registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);源码自己看下,因为关联关系不大,就不展开了,这个方法的目的是注册InfrastructureAdvisorAutoProxyCreator的BeanDefinitio

public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
    private final Log logger = LogFactory.getLog(this.getClass());

    public AutoProxyRegistrar() {
    }

    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        boolean candidateFound = false;
        Set<String> annoTypes = importingClassMetadata.getAnnotationTypes();
        Iterator var5 = annoTypes.iterator();

        while(var5.hasNext()) {
            String annoType = (String)var5.next();
            AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annoType);
            if (candidate != null) {
                Object mode = candidate.get("mode");
                Object proxyTargetClass = candidate.get("proxyTargetClass");
                if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() && Boolean.class == proxyTargetClass.getClass()) {
                    candidateFound = true;
                    if (mode == AdviceMode.PROXY) {
                        // 默认代理模式,进入到这个方法
                        // 最终调用的是:registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);基础构建增强自动代理构造器
                        AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
                        if ((Boolean)proxyTargetClass) {
                            AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
                            return;
                        }
                    }
                }
            }
        }

        if (!candidateFound && this.logger.isWarnEnabled()) {
            String name = this.getClass().getSimpleName();
            this.logger.warn(String.format("%s was imported but no annotations were found having both 'mode' and 'proxyTargetClass' attributes of type AdviceMode and boolean respectively. This means that auto proxy creator registration and configuration may not have occurred as intended, and components may not be proxied as expected. Check to ensure that %s has been @Import'ed on the same class where these annotations are declared; otherwise remove the import of %s altogether.", name, name, name));
        }

    }
}

4.2、InfrastructureAdvisorAutoProxyCreator

Infrastructure:基础设施

看下类继承结构,这里需要首先了解下Spring容器的加载过程,了解BeanPostProcessor接口的作用

因为间接实现了InstantiationAwareBeanPostProcessorAbstractAutoProxyCreator(InfrastructureAdvisorAutoProxyCreator继承了它)重写了接口两个方法,对bean进行了一些操作:

  • postProcessBeforeInstantiation:实例化前
  • postProcessAfterInitialization:初始化后

4.3、AbstractAutoProxyCreator

public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
		implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {

   
    @Override
	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
		Object cacheKey = getCacheKey(beanClass, beanName);

		if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {
			// 如果已经存在直接返回
			if (this.advisedBeans.containsKey(cacheKey)) {
				return null;
			}
			//是否基础构件(基础构建不需要代理):Advice、Pointcut、Advisor、AopInfrastructureBean这四类都算基础构建
			if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
				//添加进advisedBeans ConcurrentHashMap<k=Object,v=Boolean>标记是否需要增强实现,
				// 这里基础构建bean不需要代理,都置为false,供后面postProcessAfterInitialization实例化后使用。
				this.advisedBeans.put(cacheKey, Boolean.FALSE);
				return null;
			}
		}

		// Create proxy here if we have a custom TargetSource.
		// Suppresses unnecessary default instantiation of the target bean:
		// The TargetSource will handle target instances in a custom fashion.

		// TargetSource是spring aop预留给我们用户自定义实例化的接口,
		// 如果存在TargetSource就不会默认实例化,而是按照用户自定义的方式实例化,咱们没有定义,不进入
		if (beanName != null) {
			TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
			if (targetSource != null) {
				this.targetSourcedBeans.add(beanName);
				Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
				Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
				this.proxyTypes.put(cacheKey, proxy.getClass());
				return proxy;
			}
		}

		return null;
	}

    @Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (this.earlyProxyReferences.remove(cacheKey) != bean) {
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}

    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		// 如果是用户自定义获取实例,不需要增强处理,直接返回
		if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
		// 查询map缓存,标记过false,不需要增强直接返回
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
		// 判断一遍springAOP基础构建类,标记过false,不需要增强直接返回
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}
		// 获取增强List<Advisor> advisors
		// Create proxy if we have advice.
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		if (specificInterceptors != DO_NOT_PROXY) {
			// 标记增强为TRUE,表示需要增强实现
			this.advisedBeans.put(cacheKey, Boolean.TRUE);
			// 生成增强代理类
            // 下一步进入这个方法
			Object proxy = createProxy(
					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}
		// 如果不存在增强,标记false,作为缓存,再次进入提高效率,第16行利用缓存先校验
		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}
}

4.4 createProxy  

 

protected Object createProxy(
			Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
		// 如果是ConfigurableListableBeanFactory接口(咱们DefaultListableBeanFactory就是该接口的实现类)则,
		// 暴露目标类
		if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
			//给beanFactory->beanDefinition定义一个属性:k=AutoProxyUtils.originalTargetClass,v=需要被代理的bean class
			AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
		}

		ProxyFactory proxyFactory = new ProxyFactory();
		// 复制本类的一些属性
		proxyFactory.copyFrom(this);
		//如果不是代理目标类(JDK动态代理的意思)
		if (!proxyFactory.isProxyTargetClass()) {
			//如果beanFactory定义了代理目标类(CGLIB)
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {
				//否则设置代理接口(JDK)
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}
		//把拦截器包装成增强(通知)
		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		proxyFactory.addAdvisors(advisors);
		proxyFactory.setTargetSource(targetSource);
		//空方法,留给子类拓展用,典型的spring的风格,喜欢处处留后路
		customizeProxyFactory(proxyFactory);

		proxyFactory.setFrozen(this.freezeProxy);
		//用于控制代理工厂是否还允许再次添加通知,默认为false(表示不允许)
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}
		//代理工厂获取代理对象的核心方法
		return proxyFactory.getProxy(getProxyClassLoader());
	}

五、看到这里,大家可能对createProxy  有些疑问,我们还没有定义Advisor呀,Advisor是哪来的?

我们再回到第四步看一下,之前4.1,4.2,4.3,4.4看的全都是AutoProxyRegistrar源码,下边分析下ProxyTransactionManagementConfiguration是干嘛的。

第一个方法就是定义事务增强器的,返回的BeanFactoryTransactionAttributeSourceAdvisor对象其实是间接实现了Advisor接口的,大家可以看下类图。

最终,加载了一个事务的Advisor,这个里边配置了Advice:TransactionInterceptor,真正方法执行时会拦截到,下一章再讨论。

@Configuration
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
	/**
	 * //定义事务增强器
	 */
	@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
		BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
		advisor.setTransactionAttributeSource(transactionAttributeSource());
        // 这里的定义了事务拦截器,下一章我们会重点探讨这个类
		advisor.setAdvice(transactionInterceptor());
		advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
		return advisor;
	}
	/**
	 * //定义基于注解的事务属性资源
	 */
	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public TransactionAttributeSource transactionAttributeSource() {
		return new AnnotationTransactionAttributeSource();
	}

	/**
	 * //定义事务拦截器
	 */
	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public TransactionInterceptor transactionInterceptor() {
		TransactionInterceptor interceptor = new TransactionInterceptor();
		interceptor.setTransactionAttributeSource(transactionAttributeSource());
		if (this.txManager != null) {
			interceptor.setTransactionManager(this.txManager);
		}
		return interceptor;
	}

}

六、总结

到这里,Spring如何生成事务增强代理类的已经完了,代码有点长,如果第一遍没看明白的,可以多看两遍,哈哈,希望各位大佬指出错误之处。

  1. SpringBoot通过spring.factories文件引入TransactionAutoConfiguration
  2. TransactionAutoConfiguration默认设置CglibAutoProxyConfiguration 做代理,开启了@EnableTransactionManagement注解
  3. @EnableTransactionManagement注解引入了TransactionManagementConfigurationSelector
  4. TransactionManagementConfigurationSelector加载了:
    1. AutoProxyRegistrar:用于注册自动代理生成器(InfrastructureAdvisorAutoProxyCreator)
    2. ProxyTransactionManagementConfiguration:配置引入了事务的增强器
  5. 在Spring初始化的时候,InfrastructureAdvisorAutoProxyCreator在bean的实例化前和初始化后,执行生成事务增强代理的逻辑,生成事务增强器
  6. 配置了Advice:TransactionInterceptor,真正方法执行时会拦截到,下一章再讨论。

七、结束

 

 

 

 

 

 

 

  1.  
  2.  
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值