Spring-事务源码解析2

上一篇文章我们介绍了事务开启注解@EnableTransactionManagement源码解析《Spring-事务源码解析1》 里面提到了2个关键组件,这里我们分析下Spring如何利用这2个组件来给Bean创建代理对象。

本篇文件我们看下当一个类里面包含了@Transactional注解,Spring如何利用上面说的2个组件来实例化Bean,如何让这个Bean带有事务功能。

这里先看Spring非常经典的方法doCreateBean, 因为doCreateBean内容有点多,这里我也就贴我认为比较重要的一部分代码。

//假设我们的业务类AService带有@Transactional注解

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {

	........1、下面一块代码就是通过反射得到AService的实例对象,这个还只是通过反射拿到了普通的实例对象不是代理对象。
	BeanWrapper instanceWrapper = null;
	if (mbd.isSingleton()) {
		instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
	}
	if (instanceWrapper == null) {
		instanceWrapper = createBeanInstance(beanName, mbd, args);
	}
	Object bean = instanceWrapper.getWrappedInstance();
	........

	........2、把普通实例对象封装ObjectFactory对象存入三级缓存,这里我们先忽略。
	boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
	if (earlySingletonExposure) {
		addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
	}
	........


	........3、通过AService普通实例对象生成AService的代理对象,也利用了前面提到的2个组件,这里的代理对象就包含了事务功能。逻辑都在"初始化"
	Object exposedObject = bean;
	populateBean(beanName, mbd, instanceWrapper);//属性填充
	exposedObject = initializeBean(beanName, exposedObject, mbd);//初始化
	........

	........4、利用三级缓存解决依赖,这里先忽略。
	if (earlySingletonExposure) {
		Object earlySingletonReference = getSingleton(beanName, false);
		if (earlySingletonReference != null) {
			if (exposedObject == bean) {
				exposedObject = earlySingletonReference;
			}
		}
	}
	........

	return exposedObject;//返回AService的代理对象
}

下面我们看下Bean的初始化逻辑

AServcie的普通实例对象初始化。
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
	
	Object wrappedBean = bean;//这里Bean还只是AService的普通实例对象

	//执行所有后置处理器的Before方法,本次忽略
	wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);

	//如果AServcie实现了InitializingBean接口,执行inint方法,本次忽略
	invokeInitMethods(beanName, wrappedBean, mbd);

	//执行所有后置处理器的After方法,这里会生成AService的代理对象。
	wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

	return wrappedBean;
}

Spring里面包含了很多后置处理器,那么生成AService代理类的后置处理器,也就是我们前面提到的2个组件

1、AutoProxyRegistrar组件会往Spring容器中注册InfrastructureAdvisorAutoProxyCreator后置处理器
2、ProxyTransactionManagementConfiguration组件会往Spring容器中注册切面进去

在执行到InfrastructureAdvisorAutoProxyCreator后置处理器的After方法里面,主要是为通过调用wrapIfNecessary方法来创建AService代理对象。

@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
	if (bean != null) {
		........
		return wrapIfNecessary(bean, beanName, cacheKey); //生成AService的代理对象
	}
	return bean;
}

先说下执行流程,当请求进来的时候,会执行JdkDynamicAopProxy的invoke方法,这时会拿到方法的拦截器链,下面是获取目标方法的拦截器链

List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

然后执行拦截器链中的最开始的拦截器,后面一次遍历,但是此时的拦截器就只有一个就是TransactionInterceptor事务方法拦截器

进到TransactionInterceptor就会执行TransactionInterceptor的invoke方法,下面看下invoke的流程

1、先拿到事务管理器的事务类型:PROPAGATION_REQUIRED,ISOLATION_DEFAULT;
2、在拿到事务的管理器也就是DataSourceTransactionManager

@Override
public Object invoke(final MethodInvocation invocation) throws Throwable {
      //目标类      
      Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
      //执行切面方法和目标方法
      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 {

      //1、事务隔离级别
      final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
      //2、事务管理器DataSourceTransactionManager
      final PlatformTransactionManager tm = determineTransactionManager(txAttr);


      //生成事务txInfo,里面包含本次事务状态,隔离级别,事务处理器,当本次事务执行完后需要关闭本次事务
      TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
      
      try {
      		//执行进入下一个链,此时只有一个也就是目标方法
            retVal = invocation.proceedWithInvocation();
      }
      catch (Throwable ex) {
            //更改txInfo里面的状态
            completeTransactionAfterThrowing(txInfo, ex);
            throw ex;
      }
      finally {
            cleanupTransactionInfo(txInfo);
      }
      commitTransactionAfterReturning(txInfo);//根据状态是否commit
      return retVal;
}

五、疑问

1、带有@Transaction注解的Bean实例化的时候,怎么如果判断该Bean带有@Transaction方法

1、InfrastructureAdvisorAutoProxyCreator#postProcessAfterInitialization
—>2、BeanFactoryTransactionAttributeSourceAdvisor
—>3、AnnotationTransactionAttributeSource
—>4、SpringTransactionAnnotationParser判断@Transaction

最终通过SpringTransactionAnnotationParser来判断Bean的方法是否带有@Transaction注解

拓展:
InfrastructureAdvisorAutoProxyCreator里面有个advisedBeans属性,在Bean的创建过程会判断Bean里面 是否是带有事务注解@Transaction的方法,如果有就会被加到advisedBeans里面去。

private final Map<Object, Boolean> advisedBeans = new ConcurrentHashMap<Object, Boolean>(256);

注意:
1、BeanFactoryTransactionAttributeSourceAdvisor事务增强器在advisedBeans是false的形式存在
2、transactionInterceptor也是false

2、带有@Transaction注解的代理Bean在哪个流程被创建

在执行BeanPostProcess处理器链的时候,由InfrastructureAdvisorAutoProxyCreator#postProcessAfterInitialization方法执行创建,该方法会调用wrapIfNecessary方法完成代理创建

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
	  .......
      //这里是拿到BeanFactoryTransactionAttributeSourceAdvisor也就是“事务增强器”
      Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
      if (specificInterceptors != DO_NOT_PROXY) {
            this.advisedBeans.put(cacheKey, Boolean.TRUE);//key就是带有@Transaction的BeanName
            Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
            return proxy;//返回代理对象
      }
      return bean;
}

3、如何创建@Transaction注解的Bean
默认是使用JDK动态代理

1、先创建ProxyFactory对象,设置属性
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTargetSource(目标对象LLServcieImpl);
proxyFactory.setInterfaces(目标接口LLServcie);
proxyFactory.addAdvisor(事务增强器BeanFactoryTransactionAttributeSourceAdvisor);
proxyFactory.getProxy(getProxyClassLoader())//调用下面的代码
//2、生成动态代理对象
proxiedInterfaces=AopProxyUtils.completeProxiedInterfaces(事务增强器, true);
//设置代理对象要实现接口和InvocationHandler对象
Proxy.newProxyInstance(classLoader, proxiedInterfaces, JdkDynamicAopProxy);

其中proxiedInterfaces包含接口

0 = {Class@3511} “interface cn.tedu.sample2.util.LLServcie”
1 = {Class@3676} “interface org.springframework.aop.SpringProxy”
2 = {Class@5780} “interface org.springframework.aop.framework.Advised”
3 = {Class@3897} “interface org.springframework.core.DecoratingProxy”

4、InfrastructureAdvisorAutoProxyCreator类的作用

1、postProcessBeforeInstantiation方法主要是针对所有要创建的Bean,判断存到advisedBeans里面是false还是true
2、postProcessAfterInitialization方法,处理带有@Transcation的Bean,创建代理Bean

六、总结

1、先通过@EnableTransactionManagement引入TransactionManagementConfigurationSelector
2、通过TransactionManagementConfigurationSelector,导入AutoProxyRegistrar,ProxyTransactionManagementConfiguration
3、AutoProxyRegistrar会向容器中注册InfrastructureAdvisorAutoProxyCreator
4、ProxyTransactionManagementConfiguration会向容器定义三个Bean:事务增强器、@Transaction注解解析器、事务方法拦截器
5、执行Bean的后置处理器时,通过InfrastructureAdvisorAutoProxyCreator的postProcessAfterInitialization方法创建代理对象
6、创建代理对象时,通过事务增强器BeanFactoryTransactionAttributeSourceAdvisor来得到代理类要实现的接口SpringProxy、Advised、DecoratingProxy,最终生成代理对象

7、当请求进来时,先进入JdkDynamicAopProxy的invoke方法
8、invoke里面会调用TransactionInterceptor的invoke方法,里面会调用invokeWithinTransaction方法
9、invokeWithinTransaction里面会在调用目标方法前开启事务,catch失败设置状态,然后finally根据状态来确认是否commit

Spring-事务源码解析2_第1张图片

你可能感兴趣的:(Spring整理后,事务管理器,事务解析器,事务拦截器,事务增强器,spring,Transaction,源码)