Как включить поддержку транзакций
импортировать зависимости
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
После добавления зависимости класс автоматической настройки автоматически настроит объект класса с поддержкой транзакций.
@Configuration
// 引入 spring-boot-starter-jdbc 之后,类路径才存在 PlatformTransactionManager,配置生效
@ConditionalOnClass(PlatformTransactionManager.class)
@AutoConfigureAfter({ JtaAutoConfiguration.class, HibernateJpaAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class, Neo4jDataAutoConfiguration.class })
@EnableConfigurationProperties(TransactionProperties.class)
public class TransactionAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public TransactionManagerCustomizers platformTransactionManagerCustomizers(
ObjectProvider<PlatformTransactionManagerCustomizer<?>> customizers) {
return new TransactionManagerCustomizers(customizers.orderedStream().collect(Collectors.toList()));
}
@Configuration
@ConditionalOnSingleCandidate(PlatformTransactionManager.class)
public static class TransactionTemplateConfiguration {
private final PlatformTransactionManager transactionManager;
public TransactionTemplateConfiguration(PlatformTransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
@Bean
@ConditionalOnMissingBean(TransactionOperations.class)
public TransactionTemplate transactionTemplate() {
return new TransactionTemplate(this.transactionManager);
}
}
@Configuration
@ConditionalOnBean(PlatformTransactionManager.class)
@ConditionalOnMissingBean(AbstractTransactionManagementConfiguration.class)
public static class EnableTransactionManagementConfiguration {
// 启用事务
@Configuration
@EnableTransactionManagement(proxyTargetClass = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false",
matchIfMissing = false)
public static class JdkDynamicAutoProxyConfiguration {
}
// 启用事务。没有配置 spring.aop.proxy-target-class 时,默认使用的 proxyTargetClass = true。使用CGLIB来生成代理
@Configuration
@EnableTransactionManagement(proxyTargetClass = true)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
matchIfMissing = true)
public static class CglibAutoProxyConfiguration {
}
}
}
загрузка конфигурации
Классы автоматической конфигурации при введении зависимостейTransactionAutoConfigurationэффективный. Его реализация в свою очередь введет следующую конфигурацию
- AutoProxyRegistrar: класс реализации ImportBeanDefinitionRegistrar, который вызывает свой метод registerBeanDefinitions, когда контейнер начинает вводить более подробную конфигурацию.
- InfrastructureAdvisorAutoProxyCreator не вступает в силу из-за более низкого приоритета, чем AnnotationAwareAspectJAutoProxyCreator
- ProxyTransactionManagementConfiguration @Configuration помеченный класс конфигурации
- BeanFactoryTransactionAttributeSourceAdvisor
- Внутренний атрибут поинтвута: TransactionAttributeSourcePointcut.
- AnnotationTransactionAttributeSource считывает значение атрибута @Transactional и предоставляет его в структуру транзакций Spring.
- TransactionInterceptor
- TransactionalEventListenerFactory
- BeanFactoryTransactionAttributeSourceAdvisor
Как построить прокси-класс с транзакциями
Схема структуры классов BeanFactoryTransactionAttributeSourceAdvisor, AnnotationTransactionAttributeSource и TransactionInterceptor.
Прежде всего, необходимо уяснить несколько понятий:
- ClassFilter и MethodMatcher совместно реализуют возможность «решать, следует ли перехватывать метод».
- Pointcut, объединяющий ClassFilter и MethodMatcher, используется для определения необходимости улучшения метода класса.
- Advice — класс тегов с расширенными возможностями.
- Advisor, класс, который содержит советы и возможности pointcut в АОП.
Последовательность строительного процесса
Прокси-объект создается с помощью AnnotationAwareAspectJAutoProxyCreator.Принцип заключается в том, что при инициализации контейнера IOC компонент инициализации вызывает метод BeanPostProcessor.postProcessAfterInitialization. То есть в это время выполняется генерация прокси-объекта.
В процессе генерации он будет искать советник в контейнере IOC.После включения управления транзакциями по умолчанию есть BeanFactoryTransactionAttributeSourceAdvisor, а через ProxyFactory будет создан прокси-объект: CglibAopProxy или JdkDynamicAopProxy.Реализация прокси-объекта такова. на основе атрибута spring.aop.proxy-target-class и определяется, является ли проксируемый класс интерфейсом. По умолчанию используется CglibAopProxy.
Врезаться в поток выполнения управления транзакциями
откат транзакции
фиксация транзакции
Классы, связанные с процессами управления транзакциями:
- TransactionAttribute - DelegatingTransactionAttribute
- PlatformTransactionManager - DataSourceTransactionManager
- TransactionStatus
- TransactionInfo
- ConnectionHolder
Во всем процессе управления транзакциями функция фиксации и отката в основном реализуется через TransactionInterceptor в зависимости от того, является ли исключение аномальным или нет. DataSourceTransactionManager инкапсулирует фасадный интерфейс двух операций фиксации и отката для вызова TransactionInterceptor Внутри DataSourceTransactionManager он инкапсулирует TransactionStatus, а TransactionObject, содержащийся в TransactionStatus, может получить текущий используемый объект соединения через свой ConnectionHolder, а затем выполнить фиксацию или откат;
Кроме того, Spring также предоставляет TransactionSynchronization в качестве синхронизатора транзакций, который вызывает синхронизатор в момент времени «перед фиксацией, перед откатом, после фиксации, после отката и выполнения отката (или фиксации) завершения».
Использование заключается в следующем
@Transactional(rollbackFor = Exception.class)
@Override
public Author save(Author author) {
jdbcTemplate.update("insert into author(name) values (?)", author.getName());
// 注册事务同步器,在事务提交后进行回调
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
@Override
public void afterCommit() {
System.out.println("after commit...");
}
});
return author;
}