spring源码系列9:AOP源码解析之事务代理的创建

2022-06-28 10:57:17

回顾下AOP相关知识点:

  1. 静态代理与JDK动态代理与CGLIB动态代理
  2. Spring中的InstantiationAwareBeanPostProcessor和BeanPostProcessor的区别
  3. spring源码系列8:AOP源码解析之代理的创建

我们总结出AOP公式

  • JDK动态代理(Proxy+InvocationHandler)+advised
  • CGLB动态代理(Enhancer+MethodInterceptor)+advised

本质都是在内存中生成了新的字节码类。

这节我们看看事务是如何利用AOP实现的。

事务代理生成过程

一、@EnableTransactionManagement配置事务环境

@EnableTransactionManagement的@Import(TransactionManagementConfigurationSelector.class)引入TransactionManagementConfigurationSelector.class。此类

@Overrideprotected String[]selectImports(AdviceMode adviceMode){switch(adviceMode){case PROXY:returnnewString[]{AutoProxyRegistrar.class.getName(),
						ProxyTransactionManagementConfiguration.class.getName()};case ASPECTJ:returnnewString[]{
						TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME};default:return null;}}

PROXY:情况下,会注册两个类:

AutoProxyRegistrar:

实现了ImportBeanDefinitionRegistrar。其接口方法registerBeanDefinitions会向仓库注册Bean定义InfrastructureAdvisorAutoProxyCreator

InfrastructureAdvisorAutoProxyCreator继承了AbstractAdvisorAutoProxyCreator间接继承了AbstractAutoProxyCreator
在AOP代理生成那一节,我们讲过。AnnotationAwareAspectJAutoProxyCreator也是间接继承了AbstractAutoProxyCreator

AbstractAutoProxyCreator在AOP实现原理中做了大部分工作。

从这一点看,事务代理对象创建过程,与AOP代理对象过程是一样的,关键就在这个AbstractAutoProxyCreator类

ProxyTransactionManagementConfiguration

是一个@Configuration。有三个@Bean注解方法。

  • transactionAdvisor()
  • transactionAttributeSource()
  • transactionInterceptor()
@ConfigurationpublicclassProxyTransactionManagementConfigurationextendsAbstractTransactionManagementConfiguration{@Bean(name= TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)@Role(BeanDefinition.ROLE_INFRASTRUCTURE)public BeanFactoryTransactionAttributeSourceAdvisortransactionAdvisor(){
		BeanFactoryTransactionAttributeSourceAdvisor advisor=newBeanFactoryTransactionAttributeSourceAdvisor();
		advisor.setTransactionAttributeSource(transactionAttributeSource());
		advisor.setAdvice(transactionInterceptor());
		advisor.setOrder(this.enableTx.<Integer>getNumber("order"));return advisor;}@Bean@Role(BeanDefinition.ROLE_INFRASTRUCTURE)public TransactionAttributeSourcetransactionAttributeSource(){returnnewAnnotationTransactionAttributeSource();}@Bean@Role(BeanDefinition.ROLE_INFRASTRUCTURE)public TransactionInterceptortransactionInterceptor(){
		TransactionInterceptor interceptor=newTransactionInterceptor();
		interceptor.setTransactionAttributeSource(transactionAttributeSource());if(this.txManager!= null){
			interceptor.setTransactionManager(this.txManager);}return interceptor;}}

1.BeanFactoryTransactionAttributeSourceAdvisor
首先:transactionAdvisor()方法会向仓库中注册一个BeanFactoryTransactionAttributeSourceAdvisor。
在这里插入图片描述
从其继承关系上看,他是一个Advisor,并且还是PointcutAdvisor.关于Advisor,上节我们分析过他是封装了(Advice+Pointcut)

既然都有了Advisor了,那Advice和Pointcut在哪里呢?

BeanFactoryTransactionAttributeSourceAdvisor有一个pointcut 属性,会new 一个TransactionAttributeSourcePointcut。

privatefinal TransactionAttributeSourcePointcut pointcut=newTransactionAttributeSourcePointcut(){@Overrideprotected TransactionAttributeSourcegetTransactionAttributeSource(){return transactionAttributeSource;}};

在这里插入图片描述
从其继承关系,我们可以看出他其实就是一个Pointcut。

至此,就剩下Advice没有被发现。

2.TransactionAttributeSource
其次:transactionAttributeSource()会向仓库中注册一个AnnotationTransactionAttributeSource。这个AnnotationTransactionAttributeSource干嘛用的呢?

BeanFactoryTransactionAttributeSourceAdvisor.setTransactionAttributeSource(transactionAttributeSource())

属性值private TransactionAttributeSource transactionAttributeSource;privatefinal TransactionAttributeSourcePointcut pointcut=newTransactionAttributeSourcePointcut(){@Overrideprotected TransactionAttributeSourcegetTransactionAttributeSource(){return transactionAttributeSource;}};

TransactionAttributeSourcePointcut的matche方法@Overridepublicbooleanmatches(Method method, Class<?> targetClass){if(targetClass!= null&& TransactionalProxy.class.isAssignableFrom(targetClass)){returnfalse;}
		TransactionAttributeSource tas=getTransactionAttributeSource();return(tas== null|| tas.getTransactionAttribute(method, targetClass)!= null);}

AnnotationTransactionAttributeSource对象会赋值给BeanFactoryTransactionAttributeSourceAdvisor的transactionAttributeSource属性。pointcut属性初始化时,new 一个TransactionAttributeSourcePointcut类并实现getTransactionAttributeSource()方法,getTransactionAttributeSource()方法正好返回了transactionAttributeSource属性。

也就是说TransactionAttributeSourcePointcut的getTransactionAttributeSource()方法返回的是AnnotationTransactionAttributeSource

3.TransactionInterceptor
最后:transactionInterceptor()方法,会向仓库中注册一个TransactionInterceptor类。在这里插入图片描述

TransactionInterceptor从继承关系看他是一个Advice. 也就是增强器,是对事务真正处理地方。

有了Advice+Pointcut。Advice+Pointcut = Advisor 。 Advisor+TargetSource = Advised

有了Advised ,这样spring事务不正是套用了AOP的基础吗。

二、代理的生成

在AOP源码分析那一节,我们讲过,postProcessAfterInitialization后置初始化方法中,wrapIfNecessary 满足条件,才创建代理。

@Overridepublic ObjectpostProcessAfterInitialization(Object bean, String beanName)throws BeansException{if(bean!= null){
        Object cacheKey=getCacheKey(bean.getClass(), beanName);if(!this.earlyProxyReferences.contains(cacheKey)){returnwrapIfNecessary(bean, beanName, cacheKey);}}return bean;}

而这个条件就是:getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); 能够获取适用于当前bean的Advisor

1.Advisor寻找

我们回顾上节:

getAdvicesAndAdvisorsForBean 经过AbstractAdvisorAutoProxyCreator.findEligibleAdvisors的调用,AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass)的调用,最终会调用AopUtils.canApply来判断某个Advisor是否适用于当前类。

我们来看看canApply方法

publicstaticbooleancanApply(Advisor advisor, Class<?> targetClass,boolean hasIntroductions){if(advisorinstanceofIntroductionAdvisor){return((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);}elseif(advisorinstanceofPointcutAdvisor){
			PointcutAdvisor pca=(PointcutAdvisor) advisor;returncanApply(pca.getPointcut(), targetClass, hasIntroductions);}else{// It doesn't have a pointcut so we assume it applies.returntrue;}}

上文提到,

  • BeanFactoryTransactionAttributeSourceAdvisor 是一个PointcutAdvisor类型的Advisor
  • BeanFactoryTransactionAttributeSourceAdvisor中new 一个TransactionAttributeSourcePointcut。

所以此处会走:
canApply(pca.getPointcut(), targetClass, hasIntroductions)分支。

pca.getPointcut()返回的是TransactionAttributeSourcePointcut

进一步分析重载方法canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions)

publicstaticbooleancanApply(Pointcut pc, Class<?> targetClass,boolean hasIntroductions){
		Assert.notNull(pc,"Pointcut must not be null");if(!pc.getClassFilter().matches(targetClass)){returnfalse;}

		MethodMatcher methodMatcher= pc.getMethodMatcher();if(methodMatcher== MethodMatcher.TRUE){// No need to iterate the methods if we're matching any method anyway...returntrue;}

		IntroductionAwareMethodMatcher introductionAwareMethodMatcher= null;if(methodMatcherinstanceofIntroductionAwareMethodMatcher){
			introductionAwareMethodMatcher=(IntroductionAwareMethodMatcher) methodMatcher;}

		Set<Class<?>> classes=newLinkedHashSet<Class<?>>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
		classes.add(targetClass);for(Class<?> clazz: classes){
			Method[] methods= ReflectionUtils.getAllDeclaredMethods(clazz);for(Method method: methods){if((introductionAwareMethodMatcher!= null&&
						introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions))||
						methodMatcher.matches(method, targetClass)){returntrue;}}}returnfalse;}
  • 先ClassFilter.matches 校验一次。TransactionAttributeSourcePointcut的父类StaticMethodMatcherPointcut.classFilter= ClassFilter.TRUE表示类检查全部通过
  • 再MethodMatcher.matches 方法进行校验
abstractclassTransactionAttributeSourcePointcutextendsStaticMethodMatcherPointcutimplementsSerializable{@Overridepublicbooleanmatches(Method method, Class<?> targetClass){if(targetClass!= null&& TransactionalProxy.class.isAssignableFrom(targetClass)){returnfalse;}
		TransactionAttributeSource tas=getTransactionAttributeSource();return(tas== null|| tas.getTransactionAttribute(method, targetClass)!= null);}}

matches方法会调用getTransactionAttributeSource()获取一个TransactionAttributeSource对象,通过TransactionAttributeSource.getTransactionAttribute(method, targetClass),来判断适应性。

关于getTransactionAttributeSource()上文讲过。会返回一个AnnotationTransactionAttributeSource实例对象。

也就是说:TransactionAttributeSourcePointcut 的 matches()方法是通过AnnotationTransactionAttributeSource.getTransactionAttribute(method, targetClass)来实现的

来看看getTransactionAttribute()方法

@Overridepublic TransactionAttributegetTransactionAttribute(Method method, Class<?> targetClass){if(method.getDeclaringClass()== Object.class){return null;}// First, see if we have a cached value.
		Object cacheKey=getCacheKey(method, targetClass);
		TransactionAttribute cached=this.attributeCache.get(cacheKey);if(cached!= null){// Value will either be canonical value indicating there is no transaction attribute,// or an actual transaction attribute.if(cached== NULL_TRANSACTION_ATTRIBUTE){return null;}else{return cached;}}else{// We need to work it out.
			TransactionAttribute txAttr=computeTransactionAttribute(method, targetClass);// Put it in the cache.if(txAttr== null){this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);}else{
				String methodIdentification= ClassUtils.getQualifiedMethodName(method, targetClass);if(txAttrinstanceofDefaultTransactionAttribute){((DefaultTransactionAttribute) txAttr).setDescriptor(methodIdentification);}if(logger.isDebugEnabled()){
					logger.debug("Adding transactional method '"+ methodIdentification+"' with attribute: "+ txAttr);}this.attributeCache.put(cacheKey, txAttr);}return txAttr;}}

这里用了一个缓存,但重点在这个TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);

protected TransactionAttributecomputeTransactionAttribute(Method method, Class<?> targetClass){// Don't allow no-public methods as required.// 非public方法事务不生效。if(allowPublicMethodsOnly()&&!Modifier.isPublic(method.getModifiers())){return null;}// Ignore CGLIB subclasses - introspect the actual user class.
		Class<?> userClass= ClassUtils.getUserClass(targetClass);// The method may be on an interface, but we need attributes from the target class.// If the target class is null, the method will be unchanged.// 获取真实的方法(有接口方法的,要获取实现类上的那个方法)
		Method specificMethod= ClassUtils.getMostSpecificMethod(method, userClass);// If we are dealing with method with generic parameters, find the original method.
		specificMethod= BridgeMethodResolver.findBridgedMethod(specificMethod);// First try is the method in the target class.//首先查看实现类方法上是否有@Transactional注解
		TransactionAttribute txAttr=findTransactionAttribute(specificMethod);if(txAttr!= null){return txAttr;}// Second try is the transaction attribute on the target class.//其次查看实现类方法所在类上是否有@Transactional注解
		txAttr=findTransactionAttribute(specificMethod.getDeclaringClass());if(txAttr!= null&& ClassUtils.isUserLevelMethod(method)){return txAttr;}if(specificMethod!= method){// Fallback is to look at the original method.//还不行去看接口方法上是否有@Transactional注解
			txAttr=findTransactionAttribute(method);if(txAttr!= null){return txAttr;}// Last fallback is the class of the original method.//最后看接口上是否有@Transactional注解
			txAttr=findTransactionAttribute(method.getDeclaringClass());if(txAttr!= null&& ClassUtils.isUserLevelMethod(method)){return txAttr;}}return null;}

由此:我们们也终于知道,@Transactional注解的查找顺序,实现类方法–》实现类–》接口方法–》接口
我们在这四个地方添加@Transactional注解都会使事务生效。

在这四个地方任一一个地方找到了@Transactional注解,说明BeanFactoryTransactionAttributeSourceAdvisor适用于当前类,getAdvicesAndAdvisorsForBean 的返回不为空。接下来就可以创建动态代理了。

2.代理的生成
// Create proxy if we have advice.
		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,newSingletonTargetSource(bean));this.proxyTypes.put(cacheKey, proxy.getClass());return proxy;}

createProxy()方法,在spring源码系列8:AOP源码解析之代理的创建一节我们一节分析过了。

最终的结果就是通过
CglibAopProxy. getProxy()返回代理对象
或者
JdkDynamicAopProxy. getProxy()返回代理对象

总结:

spring事务,就是在spring AOP基础上实现的。
通过定义一个适用于事务的Advisor(Advice+Pointcut)完美的套用AOP的东西,实现了事务。

我们看看这个公式:

  1. AOP = 动态代理+ Advised(Adisor+TargetSource);
  2. Adisor = Advice+Pointcut

试想,如果我们可不可以利用这个公式也能创建出一个类似事务的东西呢?

  • 作者:享学源码
  • 原文链接:https://blog.csdn.net/wuqinduo/article/details/102673622
    更新时间:2022-06-28 10:57:17