spring注解驱动(声明式事务):简单使用,原码解析,AutoProxyRegistrar,ProxyTransactionManagementConfiguration

简单使用

配置类

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和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();
	}

原码解析

点进@EnableTransactionManagement查看
@Import(TransactionManagementConfigurationSelector.class)
里面导入了一个Selector
在这里插入图片描述

利用TransactionManagementConfigurationSelector给容器中导入组件
看AdviceMode的属性导入不同的组件,看上面的一张截图
AdviceMode mode() default AdviceMode.PROXY;默认是PROXY
所以就会导入两个组件
AutoProxyRegistrar
ProxyTransactionManagementConfiguration
在这里插入图片描述

AutoProxyRegistrar

点进去AutoProxyRegistrar,它也是给容器注册组件的
在这里插入图片描述
点进AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
注册了一个InfrastructureAdvisorAutoProxyCreator的组件
你看下面的AnnotationAwareAspectJAutoProxyCreator,这不是AOP时候注册的组件吗?
InfrastructureAdvisorAutoProxyCreator和之前的AOP一样,也是一个后置处理器
在这里插入图片描述

InfrastructureAdvisorAutoProxyCreator

点进InfrastructureAdvisorAutoProxyCreator查看
可以发现它没干什么,主要是利用后置处理器机制在创建对象之后包装对象,返回一个代理对象(增强器),代理对象执行方法利用拦截器链进行调用
在这里插入图片描述

ProxyTransactionManagementConfiguration

点进ProxyTransactionManagementConfiguration
给容器注册了事务增强器,

事务增强器需要一个transactionAttributeSource()

事务注解信息,解析事务注解
这个对象是AnnotationTransactionAttributeSource();
它是SpringTransactionAnnotationParser(spring的解析器)
JtaTransactionAnnotationParser(Jta解析器)
Ejb3TransactionAnnotationParser(Ejb3解析器)
这些解析器主要是解析注解能写的属性
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

事务增强器还需要一个事务拦截器transactionInterceptor()

TransactionInterceptor保存了事务属性信息和事务管理器
点进TransactionInterceptor,发现它是一个MethodInterceptor,AOP的时候所有的增强器都会包装成MethodInterceptor
public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {
在这里插入图片描述
进入TransactionInterceptor,invoke()方法的
return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback()方法

首先执行拦截器链,拦截器链里面就只有TransactionInterceptor一个拦截器
事务拦截器工作流程:
1)先获取事务相关的属性
2)再获取PlatformTransactionManager,如果事先没有指定任何的TransactionManager
最终会从容器中按照类型获取一个PlatformTransactionManager
3)执行目标方法
如果异常,获取事务管理器,利用事务管理器回滚
如果正常利用事务管理器提交事务
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_43416157/article/details/108430700
今日推荐