一、环境搭建
一、导入依赖
<!-- 数据源、数据库驱动、spring-jdbc模块-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.12.RELEASE</version>
</dependency>
<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.44</version>
</dependency>
二、编写配置
1、配置数据源、JdbcTemplate(Spring提供的简化数据库操作的工具)操作数据
2、@EnableTransactionManagement 开启基于注解的事务管理功能;
3、配置事务管理器来控制事务;
@Bean
public PlatformTransactionManager transactionManager()
4、给方法上标注 @Transactional 表示当前方法是一个事务方法;
@EnableTransactionManagement @ComponentScan("com.test") @Configuration public class TxConfig { //数据源 @Bean public DataSource dataSource() throws Exception{ ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setUser("root"); dataSource.setPassword("123456"); dataSource.setDriverClass("com.mysql.jdbc.Driver"); dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test"); return dataSource; } // @Bean public JdbcTemplate jdbcTemplate() throws Exception{ //Spring对@Configuration类会特殊处理;给容器中加组件的方法,多次调用都只是从容器中找组件 JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource()); return jdbcTemplate; } //注册事务管理器在容器中 @Bean public PlatformTransactionManager transactionManager() throws Exception{ return new DataSourceTransactionManager(dataSource()); } }
二、原理
一、@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; }1、mode(默认为 AdviceMode.PROXY):指定事务代理的模式。可以选择的值有 AdviceMode.PROXY 和 AdviceMode.ASPECTJ。默认是 AdviceMode.PROXY,表示使用基于代理的方式实现事务管理。如果选择 AdviceMode.ASPECTJ,表示使用基于AspectJ的方式实现事务管理。
2、proxyTargetClass(默认为
false
):用于确定代理是否应该使用目标类的类代理,而不是目标类实现的接口。如果设置为true
,代理将使用目标类的类代理(CGLIB代理),如果设置为false
,代理将使用目标类实现的接口代理(JDK动态代理)。当你在配置类上使用 @EnableTransactionManagement 注解时,Spring框架会自动扫描带有 @Transactional 注解的方法,并在这些方法周围织入事务管理的逻辑。如果一个带有 @Transactional 注解的方法执行过程中出现了异常,Spring会自动回滚事务。这个注解的作用是简化事务管理的配置和使用,提高开发效率。
TransactionManagementConfigurationSelector
注解中AdviceMode mode() default AdviceMode.PROXY;默认是PROXY类型,
所以,这个类会导入两个组件
AutoProxyRegistrar ProxyTransactionManagementConfiguration
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
/**
* Returns {@link ProxyTransactionManagementConfiguration} or
* {@code AspectJ(Jta)TransactionManagementConfiguration} for {@code PROXY}
* and {@code ASPECTJ} values of {@link EnableTransactionManagement#mode()},
* respectively.
*/
@Override
protected String[] selectImports(AdviceMode adviceMode) {
// @EnableTransactionaManagement注解默认就是Proxy
switch (adviceMode) {
case PROXY:
// 然后就要把这个数组里的类进行加载,到此为止@EnableTransactionManagement注解的事情也就完成了
return new String[] {AutoProxyRegistrar.class.getName(),
ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
return new String[] {determineTransactionAspectClass()};
default:
return null;
}
}
private String determineTransactionAspectClass() {
return (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader()) ?
TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME :
TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME);
}
}
一、AutoProxyRegistrar组件
1、AutoProxyRegistrar类实现了ImportBeanDefinitionRegistrar接口,它的作用是在Spring容器中注册自动代理创建器(AutoProxyCreator)
2、registerBeanDefinitions()方法是ImportBeanDefinitionRegistrar接口中的方法,它会在配置类(或使用)的初始化过程中被调用。该方法接收两个参数:
1)importingClassMetadata
:用于获取导入类的元数据,例如注解信息、类名等。
2)registry
:用于注册BeanDefinition的BeanDefinitionRegistry对象。
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
private final Log logger = LogFactory.getLog(getClass());
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean candidateFound = false;
Set<String> annTypes = importingClassMetadata.getAnnotationTypes();
// 获取配置类上的所有注解类型。然后遍历这些注解类型,尝试获取注解上的mode和proxyTargetClass属性值。
for (String annType : annTypes) {
AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
if (candidate == null) {
continue;
}
Object mode = candidate.get("mode");
Object proxyTargetClass = candidate.get("proxyTargetClass");
/**
如果找到了具有mode和proxyTargetClass属性的注解,并且它们的类型分别是AdviceMode和boolean,
则表示找到了候选的自动代理创建器。根据mode属性的值,如果是AdviceMode.PROXY,
则调用AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry)方法注册自动代理创建器。
如果proxyTargetClass属性为true,则调用AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry)方法,
强制自动代理创建器使用类代理模式。然后,方法返回,完成注册过程。
**/
if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
Boolean.class == proxyTargetClass.getClass()) {
candidateFound = true;
if (mode == AdviceMode.PROXY) {
// 主要是这一行
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
if ((Boolean) proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
return;
}
}
}
}
/**
如果在配置类上没有找到具有mode和proxyTargetClass属性的注解,
或者出现了其他异常情况,会打印一条警告日志,
提示可能没有按预期进行自动代理创建器的注册和配置。
**/
if (!candidateFound && logger.isInfoEnabled()) {
String name = getClass().getSimpleName();
logger.info(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));
}
}
}
AutoProxyRegistrar
类的registerBeanDefinitions()
方法通过检查配置类上的注解,决定是否注册自动代理创建器,并根据注解的属性值进行相应的配置。这样可以实现自动代理的功能,用于对标注了特定注解的组件进行代理。
InfrastructureAdvisorAutoProxyCreator:
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry)这个方法里面,其实是将InfrastructureAdvisorAutoProxyCreator生产Bean的定义信息注册到容器中。但其实还会存在一个覆盖的行为。
主要就是:利用后置处理器机制在对象创建以后,包装对象,返回一个代理对象(增强器),代理对象执行方法利用拦截器链进行调用;
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
1、
检查是否已经在
BeanDefinitionRegistry
中包含了名为AUTO_PROXY_CREATOR_BEAN_NAME
的BeanDefinition,其中AUTO_PROXY_CREATOR_BEAN_NAME
是自动代理创建器的名称2、
如果已经存在自动代理创建器的BeanDefinition,则进一步判断当前要注册的自动代理创建器的类是否与已存在的BeanDefinition的类相同。如果不同,说明有更高优先级的自动代理创建器已经注册,需要进行升级。
3、
通过比较自动代理创建器类的优先级,确定当前要注册的自动代理创建器的类是否具有更高的优先级。优先级通过
findPriorityForClass
方法进行判断。如果当前要注册的自动代理创建器的类优先级更高,则更新已存在的BeanDefinition的类为当前要注册的类。4、
通过比较自动代理创建器类的优先级,确定当前要注册的自动代理创建器的类是否具有更高的优先级。优先级通过
findPriorityForClass
方法进行判断。如果当前要注册的自动代理创建器的类优先级更高,则更新已存在的BeanDefinition的类为当前要注册的类。5、
如果不存在自动代理创建器的BeanDefinition,则创建一个
RootBeanDefinition
对象,该对象的类为当前要注册的自动代理创建器的类。6、
设置
RootBeanDefinition
的源对象为传入的source
参数,这个参数表示注册的来源。7、
为 RootBeanDefinition 设置属性值:
将其顺序(order)设置为 Ordered.HIGHEST_PRECEDENCE,以确保它在其他Bean之前被创建。
将 RootBeanDefinition 的角色(role)设置为 BeanDefinition.ROLE_INFRASTRUCTURE,表示它是一个基础架构角色的Bean。
将 RootBeanDefinition 注册到 BeanDefinitionRegistry 中,使用 AUTO_PROXY_CREATOR_BEAN_NAME 作为Bean的名称。
二、ProxyTransactionManagementConfiguration组件
用于配置事务管理的Spring配置类,它继承自
AbstractTransactionManagementConfiguration
,并使用了@Configuration
注解进行标记,表示这是一个配置类。
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)// 指定它们的角色为基础设施角色。这意味着它们是框架内部使用的组件,用于支持事务管理功能。
// 对切点进行增强,自然需要Advisor
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {
// 实例化advisor对象
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
// 引入第二个bean
advisor.setTransactionAttributeSource(transactionAttributeSource);
// 引入第三个bean
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();
}
// Advisor需要的拦截器
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {
TransactionInterceptor interceptor = new TransactionInterceptor();
interceptor.setTransactionAttributeSource(transactionAttributeSource);
if (this.txManager != null) {
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
}
1、transactionAdvisor():
1、
用于创建
BeanFactoryTransactionAttributeSourceAdvisor
对象,作为事务的Advisor(通知器),Advisor定义了在哪些切点上应用事务逻辑。2、
该方法接收两个参数:transactionAttributeSource(事务属性源)和 transactionInterceptor(事务拦截器)。它将这两个对象设置到创建的BeanFactoryTransactionAttributeSourceAdvisor 中,并根据需要设置Advisor的顺序
2、transactionAttributeSource()
用于创建
AnnotationTransactionAttributeSource
对象,作为管理事务属性的事务属性源。AnnotationTransactionAttributeSource
是一个基于注解的事务属性源,用于从标注了事务注解的方法获取事务属性信息。
3、transactionInterceptor()
用于创建 TransactionInterceptor 对象,作为事务的拦截器。TransactionInterceptor 是一个AOP拦截器,用于在方法调用前后应用事务逻辑。它接收一个 transactionAttributeSource 参数,用于获取事务属性信息。如果配置了 txManager(事务管理器),则将其设置到创建的 TransactionInterceptor 中。
三、执行流程
ProxyTransactionManagementConfiguration给容器中注册事务增强器
1:事务增强器要用事务注解的信息,AnnotationTransactionAttributeSource解析事务注解
2、事务拦截器:TransactionInterceptor;保存了事务属性信息,事务管理器,他是一个 MethodInterceptor。在目标方法执行的时候
执行拦截器链
事务拦截器
1)、先获取事务相关的属性
2)、再获取PlatformTransactionManager,如果事先没有添加指定任何transactionmanger,最终会从容器中按照类型获取一个PlatformTransactionManager;
3)、执行目标方法
如果异常,获取到事务管理器,利用事务管理回滚操作;
如果正常,利用事务管理器,提交事务
1、ProxyTransactionManagementConfiguration给容器中注册事务增强器
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME) @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() { BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor(); //事务增强器要用事务注解的信息,AnnotationTransactionAttributeSource解析事务注解 advisor.setTransactionAttributeSource(transactionAttributeSource()); // 事务拦截器 advisor.setAdvice(transactionInterceptor()); if (this.enableTx != null) { advisor.setOrder(this.enableTx.<Integer>getNumber("order")); } return advisor; }
2、transactionAttributeSource()
@Bean @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public TransactionAttributeSource transactionAttributeSource() { // 事务增强器要用事务注解的信息 return new AnnotationTransactionAttributeSource();
public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) { this.publicMethodsOnly = publicMethodsOnly; if (jta12Present || ejb3Present) { this.annotationParsers = new LinkedHashSet<>(4); this.annotationParsers.add(new SpringTransactionAnnotationParser()); if (jta12Present) { this.annotationParsers.add(new JtaTransactionAnnotationParser()); } if (ejb3Present) { this.annotationParsers.add(new Ejb3TransactionAnnotationParser()); } } else { // mysql 使用这个事务解析器 this.annotationParsers = Collections.singleton(new SpringTransactionAnnotationParser()); } }SpringTransactionAnnotationParser:主要解析各个事务属性
3、transactionInterceptor()
@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; }TransactionInterceptor:本质也是MethodInterceptor,和aop源码里的增强拦截器本质一样。
// transactionInterceptor里面执行invoke方法 @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); }
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
final InvocationCallback invocation) throws Throwable {
// If the transaction attribute is null, the method is non-transactional.
// 获取事务类型,是jta还是ejb的
TransactionAttributeSource tas = getTransactionAttributeSource();
// 获取事务属性
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
// 获取事务管理器
final PlatformTransactionManager tm = determineTransactionManager(txAttr);
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
// 如果有事务,就开启事务
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
// Standard transaction demarcation with getTransaction and commit/rollback calls.
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.
// 执行方法
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// target invocation exception
// 出现异常,回滚事务
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
// 清除事务信息{从当前线程中移除数据库连接、重置数据库连接、如果是新连接,则释放连接}
cleanupTransactionInfo(txInfo);
}
// 如果正常,将提交事务,返回对象
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;
}
}
}
determineTransactionManager:获取事务管理器
protected PlatformTransactionManager determineTransactionManager(@Nullable TransactionAttribute txAttr) { // Do not attempt to lookup tx manager if no tx attributes are set if (txAttr == null || this.beanFactory == null) { return getTransactionManager(); } String qualifier = txAttr.getQualifier(); // 如果事务注解@Transactional(transactionManager = "") 有值就通过名字获取 if (StringUtils.hasText(qualifier)) { return determineQualifiedTransactionManager(this.beanFactory, qualifier); } else if (StringUtils.hasText(this.transactionManagerBeanName)) { return determineQualifiedTransactionManager(this.beanFactory, this.transactionManagerBeanName); } else { // 没有就获取默认的 PlatformTransactionManager defaultTransactionManager = getTransactionManager(); if (defaultTransactionManager == null) { defaultTransactionManager = this.transactionManagerCache.get(DEFAULT_TRANSACTION_MANAGER_KEY); if (defaultTransactionManager == null) { defaultTransactionManager = this.beanFactory.getBean(PlatformTransactionManager.class); this.transactionManagerCache.putIfAbsent( DEFAULT_TRANSACTION_MANAGER_KEY, defaultTransactionManager); } } return defaultTransactionManager; } }private PlatformTransactionManager determineQualifiedTransactionManager(BeanFactory beanFactory, String qualifier) { PlatformTransactionManager txManager = this.transactionManagerCache.get(qualifier); if (txManager == null) { txManager = BeanFactoryAnnotationUtils.qualifiedBeanOfType( beanFactory, PlatformTransactionManager.class, qualifier); this.transactionManagerCache.putIfAbsent(qualifier, txManager); } return txManager; }