preface

This paper mainly records the author’s learning path of Transaction Management, and readers can compare their own learning path to discuss and explore a better learning path.

The basic path

  1. Find the official documentation.
  2. Find the Overview page to learn about the capabilities the project provides, what can be achieved, the design philosophy, history, minimum requirements, and more.
  3. Find Quick Start, set up its environment quickly, and get a sense of the project.
  4. Find the module you want to know about
  5. Find the Introduction of a module, which usually contains a basic Introduction to the project. You will need to find the documentation of the basic concepts or terms used in the module.
  6. Usage scenarios, functions and features, and related ecosystems
  7. Understand core/shared/reusable modules
  8. Determine your learning objectives (questions, questions/curiosity) and read the source code in a point-by-point manner
  9. Refining distillation
  10. What problems can be solved in the context of the actual development/project, and what are the shortcomings/shortcomings of the original process
  11. Daily thinking, association, improvement

Next will expand according to the basic path, the source sequence diagram only draw the core point, specific readers need to debug themselves.

Spring Framework Overview

reference

Quick Start

portal

Modules you want to know about

Transaction Management

Usage scenarios and functions

The Spring Framework fully supports transactions, providing a consistent abstraction for transaction management. A consistent programming model across different transaction apis. Support for declarative transaction management. Perfect integration with Spring’s database access abstraction.

The core

By reading the previous article, using declarative transactions, You can get a general idea of Spring Framework is the core of a transaction strategy of abstract – PlatformTransactionManager, management, each thread’s resources and transaction synchronization – TransactionSychrnoizationManager, using AOP agents in the middle of the packaging suitable a bean BeanPostProcessor AbstractAutoProxyCreator, match PlatformTransactionManager realize drive business around TransactionInterceptor method.

Let’s use a simple transaction example (using mysql, Mybatis – Plus, spring-Boot) to draw a sequence diagram to see what the core classes do.

The sample

import lombok.SneakyThrows;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.AdviceMode;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@SpringBootApplication
@EnableTransactionManagement
@MapperScan(basePackages = {"com.whf.spring.dao"})
public class Application {
    @SneakyThrows
    public static void main(String[] args) { SpringApplication.run(Application.class, args); }}import com.whf.spring.service.business.TryService;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
@WebAppConfiguration
class ApplicationTests {
    @Autowired
    private TryService tryService;

    @Test
    void testTransaction(a) { tryService.test(); }}Copy the code
import com.whf.spring.annotation.SimpleAnnotation;
import com.whf.spring.service.UserService;
import com.whf.spring.service.business.TryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Scope
@Slf4j
public class TryServiceImpl implements TryService {
    @Autowired
    private UserService userService;

    @Override
    @SimpleAnnotation
    @Transactional(rollbackFor = Exception.class)
    public void test(a) {
        log.info("Performing business"); userService.test(); }}Copy the code
import com.whf.spring.dao.UserDao;
import com.whf.spring.entity.UserDo;
import com.whf.spring.service.UserService;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.service.impl.ServiceImpl;

@Service("userService")
public class UserServiceImpl extends ServiceImpl<UserDao.UserDo> implements UserService {
    @Override
    public void test(a) {
        this.selectById(1);
        throw newRuntimeException(); }}Copy the code

The general call is as follows:

Source sequence diagram

The order of the cores should be:

  • AbstractAutoProxyCreator creates the proxy
  • The transaction must go through the TransactionInterceptor
  • TransactionInterceptor invokes PlatformTransactionManger for transaction management
  • PlatformTransactionManger invokes TransactionSychrnoizationManager transaction resource synchronization

The source code for the core class is shown below, and some additional source sequence diagrams around the core are covered in other sections.

Create a proxy sequence diagram

As you can see, proxy generation occurs late in initialization, @Transactional is available on interfaces, @transactional only works on public methods, and ultimately uses cglib proxies instead of JDK dynamic proxies.

Call sequence diagram

The calls revolve around the TransactionInterceptor, and the around transaction business method does some processing, For example before gained TransactionAttributeSource method, to determine the specific TransactionManager, according to the transaction context and communication behavior to decide whether to create a new transaction, binding, unbundling.

Define learning objectives

Have a problem

  • EnableTransaction uses the default PROXY interface based PROXY. @transactonal can also be used

See below @ EnableTransactionManagement source section

  • So we’re going to learn rollbackFor every time, how do we write globally

Transaction annotations can be customized

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Transactional(rollbackFor = Exception.class)
public @interface DefaultTransactional {
}
Copy the code

Be curious

  • The influence of @ EnableTransactionManagement attribute?

See “@ EnableTransactionManagement source” section below

  • How do I inject a transaction-brokered bean?

See the source code section “Injection of transaction proxy Beans” below

  • How are Spring declarative transactions implemented?

See the “Concrete Implementation of Spring declarative transactions” section below

  • For details on how Spring manages resources (creation, reuse, and cleanup), see the “How Spring Manages resources” section below

  • How to handle physical transactions and logical transactions, and how to handle different propagation

  • @ TransactionalEventListeners is how to achieve See below “@ TransactionalEventListeners is how to achieve” source code section

  • The sequence of the transaction Aspect and the commonly defined @Aspect can be found in the “Sequence of the transaction Aspect and the commonly defined @Aspect” section below

Learn the source code involved in the objective

@EnableTransactionManagement

Again, the code samples in the core are used

Attribute influence

Overall can see @ EnableTransactionManagement affect global APC to choose, can also affect the transactionAdvisor order, convenient handling multiple advisor.

Why not implement interface @transactonal can also be used

As to why the default AdviceMode @ EnableTransactionManagement PROXY, proxyTargetClass = false can not implement the interface using the @ Transactional because APC for AnnotationAw was finally chosen AreAspectJAutoProxyCreator.

Why not on the Application notes @ EnableTransactionManagement could also use the transaction

AdviceModeImportSelector#selectImports is not the same as AdviceModeImportSelector#selectImports. Do not add @ Configuration is TransactionAutoConfiguration springboot automatic assembly.

Injection of transaction proxy beans

Discovery is similar to normal injection. The injected tryService is a pre-proxied bean.

A concrete implementation of Spring declarative transactions

Combining the above create agent sequence diagram, call sequence diagrams, @ EnableTransactionManagement sequence diagram, we come under the general comb.

  1. First you need to use @ EnableTransactionManagement annotations on @ Configuration, both in the automatic assembly or in your own @ Configuration. This is equivalent to XML<tx:annotation-driven/>Configuration, which enables transaction behavior based on transaction annotations. At the same time the APC for AnnotationAwareAspectJAutoCreator configured to ProxyTransactionManagementConfiguration, transaction management.
  2. ProxyTransactionManagementConfiguration determines the advisor for BeanFactoryTransactionAttributeSourceAdvisor, advice for TransactionInterce Ptor resources AnnotationTransactionAttributeSource, transaction attribute. So you can use BeanFactoryTransactionAttributeSourceAdvisor generated affairs agent.
  3. Set up a TransactionManager TransactionInterceptor to manage affairs, TransactionSynchronizationManager TransactionManager will have access to resources for synchronization.

How does Spring manage resources

First to understand the object management is who, the following use JDK native write an execution SQL

Class.forName("com.mysql.jdbc.Driver"); // Load the driver
conn = DriverManager.getConnection(url); // Get the database connection
stmt = conn.createStatement(); // Create execution environment
stmt.execute(sql); // Execute SQL
Copy the code

It is mainly about Connection management, creating, reusing and cleaning connections. Concrete is TransactionManager and TransactionSynchronizationManager cooperation, specific can according to the above call sequence diagram to understand.

How do Spring handle physical transactions and logical transactions, and how do different propagation handle

Spring determines the behavior of the current transaction (such as suspending the current transaction to open a new one, or joining the current transaction) according to Propagation. Control physical transactions according to business logic. A physical transaction corresponds to a Connection, and a Connection may have multiple logical transactions.

Propag.propagation_nested Default Propagation. The default Propagation.REQUIRED is described in the above “Call sequence diagram”. You can also learn a thing or two about transaction rollback. The details are as follows:

You will not create a new transaction, PROPAGATION_NESTED will process an existing transaction, change the TransactionStatus attribute, especially savePoint, Finally, execute the “ROLLBACK TO SAVEPOINT” statement of the underlying data for local ROLLBACK (indicating that this propagation behavior requires the support of the underlying data), and then return TO the invokeWithTransaction. If the outer transaction does not want TO ROLLBACK, it can be caught directly.

@ TransactionalEventListeners is how to achieve

Is a kind of ApplicationEventMulticaster TransactionalEventListener registers into TransactionSynchronizationManager, TransactionSynchronizationManager can provide some affairs hook you release TransactionalEvent according to different stage of transaction execution.

The sequence between the transaction Aspect and the normally defined @Aspect Aspect

After the original bean initialization will call the BeanFactory applyBeanPostProcessorsAfterInitialization to see whether there is a suitable was agent, Find all through AnnotationAwareAspectJAutoProxyCreator interceptor (BeanFactoryTransactionAttributeSourceAdvisor , InstantiationModelAwarePointcutAdvisor, ExposeInvacationInterceptor) according to the order of the advisor to sort to generate an advisor with multiple agents.