Spring annotation-driven (declarative transaction): simple use, original code analysis, AutoProxyRegistrar, ProxyTransactionManagementConfiguration

Simple to use

Configuration class

package jane.tx;

import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.Transactional;
import com.mchange.v2.c3p0.ComboPooledDataSource;
/*
 * 声明式事务:
 * 环境搭建:
 * 1.导入相关的依赖:数据源,数据库驱动,spring-jdbc模块
 * 2.配置数据源,JdbcTemplate操作数据
 * 3.给方法上标注@Transactional,表示当前是一个事务方法
 * 4.@EnableTransactionManagement开启基于注解的事务管理功能
 */
@EnableTransactionManagement
@ComponentScan({
    
    "jane.tx"})
@Configuration
public class MyConfigOftx
{
    
    
	//数据源
	@Bean
	public DataSource dataSource() throws Exception
	{
    
    
		ComboPooledDataSource dataSource = new ComboPooledDataSource();
		dataSource.setUser("root");
		dataSource.setPassword("1234");
		dataSource.setDriverClass("com.mysql.cj.jdbc.Driver");
		dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8");
		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());
	}
}

Dao and Service

package jane.tx;

import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

@Repository
public class UserDao
{
    
    
	@Autowired
	JdbcTemplate jdbcTemplate;
	public void insert()
	{
    
    
		String sql="insert into user (name ,age) values (?,?)";
		String name = UUID.randomUUID().toString().substring(0, 5);
		jdbcTemplate.update(sql,name,18 );
	}
}

package jane.tx;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class UserService
{
    
    
	@Autowired
	UserDao userDao;
	
	@Transactional
	public void insertUser()
	{
    
    
		userDao.insert();
		System.out.println("插入成功");
		int i=10/0;
	}
}

	@Test
	public void testTX()
	{
    
    
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfigOftx.class);
		UserService userService = applicationContext.getBean(UserService.class);
		JdbcTemplate bean = applicationContext.getBean(JdbcTemplate.class);
		System.out.println(bean);
		System.out.println(userService);
		userService.insertUser();
		System.out.println("容器关闭");
		applicationContext.close();
	}

Source code analysis

Click into @EnableTransactionManagement to see
@Import(TransactionManagementConfigurationSelector.class)
that a Selector is imported
Insert picture description here

Use TransactionManagementConfigurationSelector to import components into the container.
Look at the properties of AdviceMode to import different components. See the screenshot above
AdviceMode mode() default AdviceMode.PROXY; the default is PROXY,
so two components will be imported
AutoProxyRegistrar
ProxyTransactionManagementConfiguration
Insert picture description here

AutoProxyRegistrar

Click in to AutoProxyRegistrar, which is also to register components for the container.
Insert picture description here
Click in AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry); one is
registered. InfrastructureAdvisorAutoProxyCreator的组件
Look at the following AnnotationAwareAspectJAutoProxyCreator, isn't this the component registered during AOP?
InfrastructureAdvisorAutoProxyCreator, like the previous AOP, is also a post processor
Insert picture description here

InfrastructureAdvisorAutoProxyCreator

Click to InfrastructureAdvisorAutoProxyCreatorview and
you can find that it doesn't do much, mainly using the post-processor mechanism to wrap the object after creating the object, and return a proxy object (enhancer), and the proxy object execution method is called using the interceptor chain
Insert picture description here

ProxyTransactionManagementConfiguration

Click ProxyTransactionManagementConfiguration
to register the transaction enhancer to the container,

Transaction enhancer needs onetransactionAttributeSource()

Transaction annotation information, parsing transaction annotations.
This object is AnnotationTransactionAttributeSource();
it is SpringTransactionAnnotationParser (spring parser)
JtaTransactionAnnotationParser (Jta parser)
Ejb3TransactionAnnotationParser (Ejb3 parser)
These parsers are mainly used to analyze the attributes that can be written by annotations
Insert picture description here
Insert picture description here
Insert picture description here

Transaction enhancer also needs a transaction interceptortransactionInterceptor()

TransactionInterceptor saves transaction attribute information and transaction manager.
Click into TransactionInterceptor and find that it is a MethodInterceptor. In AOP, all enhancers will be packaged into MethodInterceptor and
public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {
Insert picture description here
enter the TransactionInterceptor, invoke() method
return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback()method.

First execute the interceptor chain. There is only TransactionInterceptor in the interceptor chain. Transaction interceptor
workflow:
1) Obtain transaction-related attributes
2) Then obtain PlatformTransactionManager. If no TransactionManager is specified in advance, it
will eventually be selected from the container according to the type. Get a PlatformTransactionManager
3) Execution target method
If abnormal, get the transaction manager, use the transaction manager to roll back
If the transaction manager is used normally to commit the transaction
Insert picture description here
Insert picture description here
Insert picture description here

Guess you like

Origin blog.csdn.net/qq_43416157/article/details/108430700