Transaction源码
1.准备
pom文件
<dependencies>
<!-- context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<!-- mysql -->
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.34</version>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
主配置
@Configuration
// 开启事务
@EnableTransactionManagement
@ComponentScan(value = "com.tca.spring.framework.learning.tx")
public class TxConfig {
/**
* 数据源
* @return
* @throws PropertyVetoException
*/
@Bean
public DataSource dataSource() throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser("root");
dataSource.setPassword("AI@123ai");
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://172.16.19.28:3306/testjdbc");
return dataSource;
}
/**
* jdbcTemplate
* @param dataSource
* @return
*/
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
return jdbcTemplate;
}
/**
* 事务管理器
* @return
* @throws PropertyVetoException
*/
@Bean
public PlatformTransactionManager platformTransactionManager() throws PropertyVetoException {
return new DataSourceTransactionManager(dataSource());
}
}
dao
@Component
@Slf4j
public class InfoMapper {
@Autowired
private JdbcTemplate jdbcTemplate;
private Random random = new Random(100);
@Transactional(rollbackFor = Exception.class)
public void insert() {
String id = UUID.randomUUID().toString().substring(0, 5);
jdbcTemplate.update("INSERT INTO info VALUES (?, ?, ?)", random.nextInt(100), 30, id);
int i = 10/0;
log.info("插入成功");
}
}
启动类
public class TxStarter {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(TxConfig.class);
InfoMapper infoMapper = applicationContext.getBean(InfoMapper.class);
infoMapper.insert();
}
}
2.@EnableTransactionManagement解析
2.1 @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 2147483647;
}
2.2 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";
}
}
2.3 ProxyTransactionManagementConfiguration
@Configuration
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());
if (this.enableTx != null) {
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;
}
}
问题: @EnableTransactionManagement何时被扫描,有什么作用?
从@spring源码解析以及@Aop源码解析我们知道:
1.spring容器启动调用refresh()方法, refresh()方法中会调用invokeBeanFactoryPostProcessors(beanFactory), 这个方法会创建并实例化一个十分重要的类 ——
ConfigurationClassPostProcessor, 这个类实现了BeanDefinitionRegistryPostProcessor接口, 和BeanDefinitionRegistryPostProcessor接口的父接口BeanFactoryPostProcessor, 这个类的主要作用是解析主配置类, 扫描对应的bean, 创建对应bean的BeanDefinition放到beanFactory的beanDefinitionMap中
2.ConfigurationClassPostProcessor进行类扫描并创建bd时, 会递归地解析主配置类上的注解, 将@import注解中配置的类加载到容器中并创建bd, 此外, 如果@Import类中的配置类实现了ImportSelector接口, 会调用其String[] selectImports(AnnotationMetadata importingClassMetadata)方法, 将返回的beanName, 创建对应的bd放到beanFactory的beanDefinitionMap中
3.可以看到EnableTransactionManagement中有注解: @Import({TransactionManagementConfigurationSelector.class}), 注解中配置的类: TransactionManagementConfigurationSelector 实现了 ImportSelector接口, 回调用其selectImports方法, @EnableTransactionManagement的mode()属性默认为:PROXY, 因此会返回 AutoProxyRegistrar 和 ProxyTransactionManagementConfiguration
4.继续解析这两个bean:
AutoProxyRegistrar: 当前类实现了ImportBeanDefinitionRegistrar, 即它是用来向容器中注册bean的, 调用其registerBeanDefinitions()方法, 向容器中注册了: (org.springframework.aop.config.internalAutoProxyCreator, InfrastructureAdvisorAutoProxyCreator)
ProxyTransactionManagementConfiguration:从源码可以看到, 它是一个配置类(有@Configuration注解), 不仅注册了它本身, 还注册了三个bean: BeanFactoryTransactionAttributeSourceAdvisor, TransactionAttributeSource, TransactionInterceptor
总结
@EnableTransactionManagement这个注解, 本质上就是在spring容器中注册了4个bean:
第一个: InfrastructureAdvisorAutoProxyCreator, 它实现了Aop代理的接口, 跟@Aop源码解析中, @EnableAspectJAutoProxy的作用相似, @EnableAspectJAutoProxy是向容器中注入了一个bean --> AnnotationAwareAspectJAutoProxyCreator, 这个bean实现了Aop代理, 它是一个BeanPostProcessor, bean的后置处理器; 同样的InfrastructureAdvisorAutoProxyCreator, 这个bean也实现了Aop代理, 也是一个BeanPostProcessor, 后置处理器; 而且他们都是AbstractAutoProxyCreator的子类, 也是完成完成aop代理的核心组件!!!
第二个: BeanFactoryTransactionAttributeSourceAdvisor
第三个: TransactionAttributeSource
第四个: TransactionInterceptor
第二个引用了第三个和第四个, 所以第二个类是核心, 他是具体的增强器, 它类似于Aop中的@Advice注解的配置类, 用于解析哪些类需要进行代理, 以及作为具体的增强器和拦截器, 在方法的执行过程中进行拦截!!!
3.InfrastructureAdvisorAutoProxyCreator
3.1 结构图
可以看到,InfrastructureAdvisorAutoProxyCreator类实现了BeanPostProcessor接口
3.2 作用
以上, InfrastructureAdvisorAutoProxyCreator实现了BeanPostProcessor接口, 根据@Spring源码分析我们知道, 在bean的创建过程中, 我们先后使用8次BeanPostProcessor对其进行加强, 分别是:
1.第一次: 在创建bean之前, 使用【实现了InstantiationAwareBeanPostProcessor】的BeanPostProcessor来生成bean的代理对象, 如果有生成, 则直接返回
2.第二次: 如果第一次使用的过程中没有生成代理对象, 在实例化bean对象时, 使用BeanPostProcessor【SmartInstantiationAwareBeanPostProcessor】用于推断使用特殊的构造器来反射创建bean实例
3.第三次: 在实例化bean对象之后, 调用BeanPostProcessor【MergedBeanDefinitionPostProcessor】, 在@Autowired和@Resource文章解析中, 第三次使用BeanPostProcessor, 有一部分作用是寻找属性字段注入点, 将普通bean的metadata放到injectionMetadataCache缓存中的, 方便后面的属性注入
4.第四次: 如果支持循环依赖, 创建对应bean对应的ObjectFactory, 并将其放入到三级缓存中!!!用以解决循环依赖问题, 创建的ObjectFactory第四次使用BeanPostProcessor【SmartInstantiationAwareBeanPostProcessor】
5.第五、六次: 实例化完成后, 注入bean的相关属性时, 这里会第五次和第六次使用BeanPostProcessor【InstantiationAwareBeanPostProcessor】, 判断是否需要属性注入, 并完成注入
6.第七、八次: 在属性注入之后, 执行初始化方法前后, 会先后调用BeanPostProcessor, 完成AOP
以上, 在实例化bean之前, 第一次使用bdp, 生成代理对象; 如果代理对象没有生成, 在普通bean实例化时, 第二次使用bdp进行构造器推断, 实例化后第三次、第四次使用dbp, 属性注入时第五次、第六次使用bdp, 在初始化方法前后完成第七次、第八次使用bdp
接下来查看InfrastructureAdvisorAutoProxyCreator 如何在这八次加强分别起了什么作用
3.2.1 第一次
第一次,使用的是InstantiationAwareBeanPostProcessor, 判断是否直接生成代理对象,InfrastructureAdvisorAutoProxyCreator 继承了 AbstractAutoProxyCreator 类实现了 InstantiationAwareBeanPostProcessor接口,调用了其postProcessBeforeInstantiation(Class<?>, String)方法,这里以InfoMapper为例
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
// 1.cacheKey == logService
Object cacheKey = getCacheKey(beanClass, beanName);
// 2.进入
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
// 判断advisedBeans中有没有, 如果有, 直接返回 null, advisedBeans中存储的是所有需要增强的bean
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
// 判断当前bean是否基础类型Advice、Pointcut、Advisor、AopInfrastructureBean,或是否切面(@Aspect), 跳过
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
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.
// 3.从beanFactory中获取目标对象, 这里为null
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
// 4.跳过
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
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;
}
总结
这里没有生成代理对象, 走正常的bean的生命周期, 这个过程和@aop源码一样
3.2.2 第二次
第二次, 使用的是SmartInstantiationAwareBeanPostProcessor,用于推断实例化bean时所采用的构造器,InfrastructureAdvisorAutoProxyCreator 继承了 AbstractAutoProxyCreator 类实现了 SmartInstantiationAwareBeanPostProcessor 接口,调用了其determineCandidateConstructors(Class<?>, String)方法,该方法返回null,其不参与构造器推断
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) {
return null;
}
总结
这里不参与构造器的推断, 这个过程和@aop源码一样
3.2.3 第三次
第三次,使用的是MergedBeanDefinitionPostProcessor,用于提前找到属性注入点,InfrastructureAdvisorAutoProxyCreator 没有直接或间接实现MergedBeanDefinitionPostProcessor接口,所以这里跳过
总结
这里跳过
3.2.4 第四次
第四次,使用的是SmartInstantiationAwareBeanPostProcessor,用于:如果在支持循环依赖的前提下,会将实例化的bean对象,创建对应的三次缓存对象singletonFactory对象,该对象的方法getEarlyBeanReference方法中第四次使用了BeanPostProcessor,用于提前暴露实例化但未初始化的bean,getEarlyBeanReference方法何时调用?
总结
用于支持循环依赖。如果a依赖b, b也依赖a, 即a和b存在相互依赖。一般情况下:
1.创建a时, 首先使用反射实例化a, 判断如果支持循环依赖, 将a的的工厂对象(重写getBean方法, 这个方法中第四次使用了PostProcessor)放入到三级缓存中
2.调用populateBean方法判断是否需要属性注入并完成属性注入, 在对a进行属性注入时, 使用AutowiredAnnotationPostProcessor, 从容器中获取b对象进行注入, 但此时容器中b并没有实例化, 这里进入到b的创建工作
3.创建b时, 首先也是使用反射实例化b, 判断如果支持循环依赖, 将b的的工厂对象(重写getBean方法, 这个方法中第四次使用了PostProcessor)放入到三级缓存中
4.调用populateBean方法判断是否需要属性注入并完成属性注入, 在对b进行属性注入时, 使用AutowiredAnnotationPostProcessor, 从容器中获取a对象进行注入, 一级缓存中获取不到, 从二级缓存中获取, 二级缓存中获取不到, 从三级缓存中获取, 三级缓存中使用a的工厂对象获取时, 会第四次使用BeanPostProcessor, 获取到a后(此时的a是刚刚实例化的a, 并没有初始化完成!), 移除三级缓存, 放入到二级缓存中。后面继续完成b的初始化
5.此时b初始化完成, 将b注入到a中, 可以继续进行a的初始化操作
3.2.5 第五次
第五次,使用的是InstantiationAwareBeanPostProcessor,用于判断bean是否需要属性注入,InfrastructureAdvisorAutoProxyCreator 继承了 AbstractAutoProxyCreator 类实现了 InstantiationAwareBeanPostProcessor 接口,调用了其postProcessAfterInstantiation(Object, String)方法,该方法返回true,表示不会阻断属性注入
public boolean postProcessAfterInstantiation(Object bean, String beanName) {
return true;
}
总结
这里不会阻断属性注入,即不会影响属性注入
3.2.6 第六次
第六次,使用的是InstantiationAwareBeanPostProcessor,用于bean的属性注入,InfrastructureAdvisorAutoProxyCreator 继承了 AbstractAutoProxyCreator 类实现了 InstantiationAwareBeanPostProcessor 接口,调用了其postProcessProperties(PropertyValues, Object, String)方法,该方法没有作任何处理
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
return pvs;
}
总结
这里是空实现, 不会参与属性注入
3.2.7 第七次
第七次,使用的是BeanPostProcessor,在bean属性注入之后,执行初始化方法之前,对bean进行aop操作,InfrastructureAdvisorAutoProxyCreator 继承了 AbstractAutoProxyCreator 类实现了 BeanPostProcessor 接口,调用了其 postProcessBeforeInitialization(Object, String)方法,该方法没有作任何处理
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
总结
这里是空实现, 不参与bean的初始化方法之前的aop
3.2.8 第八次
第八次,使用的是BeanPostProcessor,在执行初始化方法之后,对bean进行aop操作,InfrastructureAdvisorAutoProxyCreator 继承了 AbstractAutoProxyCreator 类实现了 BeanPostProcessor 接口,调用了其 postProcessBeforeInitialization(Object, String)方法,生成代理对象
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
// 1.cacheKey == "infoMapper"
Object cacheKey = getCacheKey(bean.getClass(), beanName);
// 2.earlyProxyReferences中不包含infoMapper, 所以这里为true, 进入
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
// 3.生成代理对象
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
AbstractAutoProxyCreator#wrapIfNecessary(Object bean, String beanName, Object cacheKey)
/* 生成代理对象
* bean --> infoMapper
* beanName --> infoMapper
* cacheKey --> infoMapper(String)
*/
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 1.这里 targetSourcedBeans 不包含 infoMapper, 跳过
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// 2.这里 advisedBeans 中不包含 infoMapper, 跳过
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
// 3.下面两个条件都不满足, 为false, 跳过
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
// 4.获取增强器, 这里获取1个: BeanFactoryTransactionAttributeSourceAdvisor
// 这个advisor是 ProxyTransactionManagementConfiguration中配置的
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
// 5.将(infoMapper, True)存储到 advisedBeans
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 6.创建代理对象
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
// 7.将(infoMapper, 和代理对象对应的Class)存储到 proxyTypes
this.proxyTypes.put(cacheKey, proxy.getClass());
// 8.返回代理对象
return proxy;
}
// 9.这里跳过
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
AbstractAutoProxyCreator#createProxy(Class<?> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource)
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);
// 如果不是代理目标类
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);
customizeProxyFactory(proxyFactory);//空方法
// 用于控制代理工厂是否还允许再次添加通知,默认为false(表示不允许)
proxyFactory.setFrozen(this.freezeProxy);
// 默认false, 已经前置过滤了匹配的增强Advisor
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// 代理工厂获取代理对象的核心方法, 这里返回代理对象
return proxyFactory.getProxy(getProxyClassLoader());
}
总结
1.判断是否需要进行代理
2.获取当前bean的所有增强器(通知方法), 找到能在当前bean使用的增强器(找到哪些通知方法需要切入到当前bean), 并排序
3.如果当前bean需要增强, 创建当前bean的代理对象:
获取所有增强器(通知方法), 保存到ProxyFactory中, 使用JdkDynamicAopProxy或者ObjenesisCglibAopProxy创建代理对象
4.方法执行
4.1 获取拦截器
调用infoMapper#insert方法进入CglibAopProxy#intercept方法
@Override
@Nullable
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Object target = null;
TargetSource targetSource = this.advised.getTargetSource();
try {
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// 1.获取目标方法的拦截器链!这里只能获取到一个 --> TransactionInterceptor
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
// Check whether we only have one InvokerInterceptor: that is,
// no real advice, but just reflective invocation of the target.
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
// We can skip creating a MethodInvocation: just invoke the target directly.
// Note that the final invoker must be an InvokerInterceptor, so we know
// it does nothing but a reflective operation on the target, and no hot
// swapping or fancy proxying.
// 2.如果没有拦截器链, 直接执行目标方法
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = methodProxy.invoke(target, argsToUse);
}
else {
// We need to create a method invocation...
// 3.如果有拦截器链, 创建CglibMethodInvocation对象, 并执行, 见@4.2 方法执行
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
4.2 方法执行
方法执行的过程就是拦截器执行的过程
ReflectiveMethodInvocation#proceed()
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
// 当执行到最后一个拦截器时, 进入
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
// 获取下一个拦截器
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
}
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
这里只有一个拦截器 --> TransactionInterceptor
TransactionInterceptor#invoke(MethodInvocation invocation)
@Override
@Nullable
public Object invoke(MethodInvocation invocation) throws Throwable {
// Work out the target class: may be {@code null}.
// The TransactionAttributeSource should be passed the target class
// as well as the method, which may be from an interface.
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
// Adapt to TransactionAspectSupport's invokeWithinTransaction...
return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
}
TransactionAspectSupport#invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
final InvocationCallback invocation)
/**
* General delegate for around-advice-based subclasses, delegating to several other template
* methods on this class. Able to handle {@link CallbackPreferringPlatformTransactionManager}
* as well as regular {@link PlatformTransactionManager} implementations.
* @param method the Method being invoked
* @param targetClass the target class that we're invoking the method on
* @param invocation the callback to use for proceeding with the target invocation
* @return the return value of the method, if any
* @throws Throwable propagated from the target invocation
*/
@Nullable
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
final InvocationCallback invocation) throws Throwable {
// 1.获取TransactionAttributeSource, 这个在@2.3 总结中提到, 已经注册到容器中
TransactionAttributeSource tas = getTransactionAttributeSource();
// 2.获取TransactionAttribute, 由TransactionAttributeSource中获取
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
// 3.获取PlatformTransactionManager, 这个如果@Transactional中由配置, 使用配置的, 否则使用我们向容器中注册了的 PlatformTransactionManager
final PlatformTransactionManager tm = determineTransactionManager(txAttr);
// 4.获取连接点
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
// 5.!(tm instanceof CallbackPreferringPlatformTransactionManager) 为true, 进入
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
// Standard transaction demarcation with getTransaction and commit/rollback calls.
// 6.开启事务
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
Object retVal;
try {
// This is an around advice: Invoke the next interceptor in the chain.
// This will normally result in a target object being invoked.
// 7.执行目标对象的目标方法
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// target invocation exception
// 8.目标对象的目标方法如果出现异常, 判断异常类型, 判断是否需要回滚操作并回滚
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
// 9.清除事务信息
cleanupTransactionInfo(txInfo);
}
// 10.进行事务提交
commitTransactionAfterReturning(txInfo);
return retVal;
}
else {
final ThrowableHolder throwableHolder = new ThrowableHolder();
// It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
try {
Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr, status -> {
TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
try {
return invocation.proceedWithInvocation();
}
catch (Throwable ex) {
if (txAttr.rollbackOn(ex)) {
// A RuntimeException: will lead to a rollback.
if (ex instanceof RuntimeException) {
throw (RuntimeException) ex;
}
else {
throw new ThrowableHolderException(ex);
}
}
else {
// A normal return value: will lead to a commit.
throwableHolder.throwable = ex;
return null;
}
}
finally {
cleanupTransactionInfo(txInfo);
}
});
// Check result state: It might indicate a Throwable to rethrow.
if (throwableHolder.throwable != null) {
throw throwableHolder.throwable;
}
return result;
}
catch (ThrowableHolderException ex) {
throw ex.getCause();
}
catch (TransactionSystemException ex2) {
if (throwableHolder.throwable != null) {
logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
ex2.initApplicationException(throwableHolder.throwable);
}
throw ex2;
}
catch (Throwable ex2) {
if (throwableHolder.throwable != null) {
logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
}
throw ex2;
}
}
}
总结
综上, 一共只有一个拦截器需要执行, 即TransactionInterceptor事务拦截器, 这个拦截器类似于环绕通知@Around:
1.开启事务
2.执行目标对象的目标方法
3.如果执行失败, 判断是否需要回滚并进行回滚操作
4.如果执行正常, 则提交事务
5.Transactional失效
5.1 方法未用public修饰
解答
第八次使用BeanPostProcessor时,会调用AbstractAutoProxyCreator#wrapIfNecessary(Object bean, String beanName, Object cacheKey)
/* 生成代理对象
* bean --> infoMapper
* beanName --> infoMapper
* cacheKey --> infoMapper(String)
*/
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
...省略...
// 1.获取增强器
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
// 2.增强器不为空, 创建代理对象并返回
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
// 3.返回之前的对象
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
如果我们InfoMapper中的@Transtractional方法没有使用public修饰符,那么这里不会获取到增强器,不会生成InfoMapper的代理对象,这里看下getAdvicesAndAdvisorsForBean方法
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
继续看findEligibleAdvisors方法
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 1.从容器中获取所有的增强器, 这里获取到事务增强器: BeanFactoryTransactionAttributeSourceAdvisor
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 2.判断这个增强器是否可以应用在InfoMapper上
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
继续看findAdvisorsThatCanApply方法
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
// 进入
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
继续追findAdvisorsThatCanApply
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new ArrayList<>();
for (Advisor candidate : candidateAdvisors) {
// 1.candidate instanceof IntroductionAdvisor --> false, 跳过
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
// 2.hasIntroductions == false
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
for (Advisor candidate : candidateAdvisors) {
// 3.false
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
// 4.进入
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
继续追canApply
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
// 1.跳过
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
// 2.进入
else if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
// It doesn't have a pointcut so we assume it applies.
return true;
}
}
继续追canApply
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
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<>();
if (!Proxy.isProxyClass(targetClass)) {
classes.add(ClassUtils.getUserClass(targetClass));
}
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
// 1.这里的classes只包含InfoMapper
for (Class<?> clazz : classes) {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
// 2.获取所有的方法, 进行匹配, 只要有一个方法可以匹配, 则判断为true, 即增强器需要应用在bean上, 创建代理对象
for (Method method : methods) {
if (introductionAwareMethodMatcher != null ?
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
// introductionAwareMethodMatcher == null, 进入该方法
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
matches
@Override
public boolean matches(Method method, Class<?> targetClass) {
// 1.跳过
if (TransactionalProxy.class.isAssignableFrom(targetClass) ||
PlatformTransactionManager.class.isAssignableFrom(targetClass) ||
PersistenceExceptionTranslator.class.isAssignableFrom(targetClass)) {
return false;
}
TransactionAttributeSource tas = getTransactionAttributeSource();
// 2.进入, 根据下面判断 tas.getTransactionAttribute(method, targetClass) == null,
// 这里 tas!= null, tas.getTransactionAttribute(method, targetClass) == null, 返回false, 即非public方法不会生成代理对象
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}
getTransactionAttribute
public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
// 1.跳过
if (method.getDeclaringClass() == Object.class) {
return null;
}
Object cacheKey = getCacheKey(method, targetClass);
TransactionAttribute cached = this.attributeCache.get(cacheKey);
// 2.跳过
if (cached != null) {
if (cached == NULL_TRANSACTION_ATTRIBUTE) {
return null;
}
else {
return cached;
}
}
else {
// 3.进入
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 (txAttr instanceof DefaultTransactionAttribute) {
((DefaultTransactionAttribute) txAttr).setDescriptor(methodIdentification);
}
if (logger.isTraceEnabled()) {
logger.trace("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);
}
this.attributeCache.put(cacheKey, txAttr);
}
// 3.如果这里没有public修饰, txAttr == null
return txAttr;
}
}
computeTransactionAttribute
@Nullable
protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
// allowPublicMethodsOnly() == true, 如果方法没有用public修饰符, 则返回null
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;
}
...省略...
}
综上, 可以得出结论: 方法未用public修饰, @Transactional不起作用
5.2 内部调用事务方法
解答
外部调用法方法时, 判断这个方法没有用@Transactional注解时, 会获取不到增强器对应的拦截器,直接调用目标对象的方法,当调用目标对象的方法时,如果目标方法内部的方法有@Transactional时,也会失效,因为目标方法调用内部方法都是通过this来调用的,这里的this是目标对象,而不是代理对象,所以不会被拦截
评论