8.2-spring 事务-声明式事务(@Transactional原理)
在 8.1-spring 事务-声明式事务(使用) 一文中我们了解到 spring 通过 @Transactional 注解实现事务的操作,开发者只需要关注具体业务,而事务操作是通过 spring aop 实现的,即给使用了 @Transactional 注解的类生成代理类,然后执行具体的事务操作。生成代理类后执行事务的方式和 jdbc 提供的编程式事务方式类似,可以通过 jdbc 提供的事务 这篇文章查看详情。
何时生成代理类
spring 通过 AOP 生成代理类,了解 AOP 知识之前需要了解 IOC 相关知识点。IOC 即将对象的创建和销毁交给容器管理,简单点讲可以分为以下步骤:
- 解析bean
- 注册bean
- 实例化bean
而 AOP 创建代理类是在实例化bean后对原有bean进行加强,一般通过 BeanPostProcessor 的后置方法 postProcessAfterInstantiation 实现。
① 解析bean并注册 BeanPostProcessor 和切点通知类
1) spring/springboot 通过 ConfigurationClassPostProcessor.parse 解析 .class 文件,查找包含 @Component、@Service 等类似注解的类,将这些类注册到容器,同时查找包含 @Import 注解的类,这里以事务注解 EnableTransactionManagement 举例:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({TransactionManagementConfigurationSelector.class})
public @interface EnableTransactionManagement {
boolean proxyTargetClass() default false;
AdviceMode mode() default AdviceMode.PROXY;
int order() default Integer.MAX_VALUE;
}
解析 @Import 具体方法在 ConfigurationClassParser 类 doProcessConfigurationClass 方法中
// Process any @Import annotations
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
2)找到 @Import 注解的值并实例化,这里是 TransactionManagementConfigurationSelector:
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
public TransactionManagementConfigurationSelector() {
}
protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:
return new String[]{AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
return new String[]{this.determineTransactionAspectClass()};
default:
return null;
}
}
private String determineTransactionAspectClass() {
return ClassUtils.isPresent("javax.transaction.Transactional", this.getClass().getClassLoader()) ? "org.springframework.transaction.aspectj.AspectJJtaTransactionManagementConfiguration" : "org.springframework.transaction.aspectj.AspectJTransactionManagementConfiguration";
}
}
该代码也在 processImports 方法中,实例化后调用 selectImports 方法:

3)调用 selectImports 方法后获取列名称返回值,这里是 AutoProxyRegistrar 和 ProxyTransactionManagementConfiguration ,再次调用 processImports 方法,
实例化 org.springframework.context.annotation.AutoProxyRegistrar(实例化后后面会用到)

解析 ProxyTransactionManagementConfiguration (后续会将里面的bean注册到容器中)
ProxyTransactionManagementConfiguration:
package org.springframework.transaction.annotation;
@Configuration(
proxyBeanMethods = false
)
@Role(2)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
public ProxyTransactionManagementConfiguration() {
}
@Bean(
name = {"org.springframework.transaction.config.internalTransactionAdvisor"}
)
@Role(2)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
advisor.setTransactionAttributeSource(transactionAttributeSource);
advisor.setAdvice(transactionInterceptor);
if (this.enableTx != null) {
advisor.setOrder((Integer)this.enableTx.getNumber("order"));
}
return advisor;
}
@Bean
@Role(2)
public TransactionAttributeSource transactionAttributeSource() {
return new AnnotationTransactionAttributeSource();
}
@Bean
@Role(2)
public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {
TransactionInterceptor interceptor = new TransactionInterceptor();
interceptor.setTransactionAttributeSource(transactionAttributeSource);
if (this.txManager != null) {
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
}
4)注册上述bean到容器
调用的是ConfigurationClassPostProcessor 类 processConfigBeanDefinitions 方法里面的 this.reader.loadBeanDefinitions(configClasses); 方法,在这个方法里会调用 AutoProxyRegistrar 的 registerBeanDefinitions 方法


这里会注册 一个 InfrastructureAdvisorAutoProxyCreator 类到容器中:
public class InfrastructureAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator {
@Nullable
private ConfigurableListableBeanFactory beanFactory;
public InfrastructureAdvisorAutoProxyCreator() {
}
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
super.initBeanFactory(beanFactory);
this.beanFactory = beanFactory;
}
protected boolean isEligibleAdvisorBean(String beanName) {
return this.beanFactory != null && this.beanFactory.containsBeanDefinition(beanName) && this.beanFactory.getBeanDefinition(beanName).getRole() == 2;
}
}
它是一个 BeanPostProcessor 类型

② 使用 BeanPostProcessor(InfrastructureAdvisorAutoProxyCreator) 生成代理类
1) 上述 bean 注册完成后会随着 IOC 容器实例化,包括 InfrastructureAdvisorAutoProxyCreator(BeanPostProcessor,在此类 postProcessAfterInstantiation 方法生成代理类对象),BeanFactoryTransactionAttributeSourceAdvisor (@Transactional 切点和通知),TransactionInterceptor (通知的具体实现方式,即拦截后的处理操作)
2)生成代理类对象
调用 AbstractAutoProxyCreator类的 postProcessAfterInitialization 方法,
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
// 调用此方法
return this.wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
} else if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
} else if (!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) {
// 在这里会判断当前类 UserService 符不符合 @Transactional 切点,
// 由于 UserService 加了事务注解,所以 specificInterceptors 不为空,即会创建 UserService 的代理对象
Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 在此创建代理对象
Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
}
在 getAdvicesAndAdvisorsForBean 方法中会调用 TransactionAttributeSourcePointcut 类的 matches 方法判断被代理类的方法有没有加@Transactional注解,即是否符合事务的切点
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
List<Advisor> advisors = this.findEligibleAdvisors(beanClass, beanName);
return advisors.isEmpty() ? DO_NOT_PROXY : advisors.toArray();
}

使用事务
调用加了spring事务的方法时,spring会调用切点通知的方法,这里是 TransactionInterceptor 类的 invoke 方法
package org.springframework.transaction.interceptor;
。。。。 省略 。。。。
public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {
。。。。 省略 。。。。
@Nullable
public Object invoke(final MethodInvocation invocation) throws Throwable {
Class<?> targetClass = invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null;
return this.invokeWithinTransaction(invocation.getMethod(), targetClass, new TransactionAspectSupport.CoroutinesInvocationCallback() {
@Nullable
public Object proceedWithInvocation() throws Throwable {
return invocation.proceed();
}
public Object getTarget() {
return invocation.getThis();
}
public Object[] getArguments() {
return invocation.getArguments();
}
});
}
。。。。 省略 。。。。
}
执行事务的具体操作在其父类 TransactionAspectSupport invokeWithinTransaction 方法中
上述讲解只是列出了一些关键性的步骤,如果需要了解各个细节需要对 IOC 容器非常熟悉,强烈建议自行阅读源码,也可以通过SpringBoot源码解析(1.4)-自动装配原理(总结) 这篇文章了解

被折叠的 条评论
为什么被折叠?



