Day167.声明式事务 -Spring注解驱动

Spring注解驱动

声明式事务

一、环境搭建

1、导入相关依赖

​ 数据源、数据库驱动、Spring-jdbc模块

2、配置数据源、JdbcTemplate(Spring提供的简化数据库操作的工具)操作数据库

导入相关依赖

<dependency>
    <groupId>com.mchange</groupId>
    <artifactId>c3p0</artifactId>
    <version>0.9.5.2</version>
</dependency>

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.44</version>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>4.3.12.RELEASE</version>
</dependency>

配置文件

db.user=root
db.password=00000
db.url=jdbc:mysql://localhost:3306/
db.driverClass=com.mysql.jdbc.Driver

配置类

@PropertySource("classpath:/dbconfig.properties")
@Configuration
@ComponentScan("com.achang.tx")
public class TxConfig {

    @Value("${db.user}")
    private String user;

    @Value("${db.password}")
    private String pwd;

    @Value("${db.driverClass}")
    private String driverClass;

    //数据源
    @Bean
    public DataSource dataSource() throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
        dataSource.setUser(user);
        dataSource.setPassword(pwd);
        dataSource.setDriverClass(driverClass);
        return dataSource;
    }

    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource){
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
        return jdbcTemplate;
    }

}

dao类

@Repository
public class UserDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    public void insert(){
        String sql ="INSERT INTO tbl_user(username,age) VALUES(?,?)";
        String username = UUID.randomUUID().toString().substring(0, 5);
        jdbcTemplate.update(sql,username,20);
    }

}

service类

@Service
public class UserService {
    @Autowired
    private UserDao userDao;
    
    public void insertUser(){
        userDao.insert();
        int i = 10 / 0; //出现异常后 方法不会回滚
        System.out.println("插入成功");
    }

}

测试类

public class IOCTest_tx {
    @Test
    public void test01(){
        //创建ioc容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(TxConfig.class);

        UserService userService = applicationContext.getBean(UserService.class);
        userService.insertUser();

    }
    
}

二、开启事务

开启事务流程

1、开启事务管理功能 标注@EnableTransactionManagement
2、给需要加事务的方法上标注@Transactional
3、在配置类中,配置事务管理器,来控制事务

  • 在配置类上标注@EnableTransactionManagement
@EnableTransactionManagement
public class TxConfig {}
  • 给需要加事务的方法标注@Transactional
@Transactional
public void insertUser(){
    userDao.insert();
    int i = 10 / 1;
    System.out.println("插入成功");
  • 在配置类中,配置事务管理器,来控制事务
//注册事务管理器在容器中
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource){
    return new DataSourceTransactionManager(dataSource);//要加入数据源,控制数据源
}

三、源码分析

事务管理通过AOP机制实现

   1、@EnableTransactionManagement
       利用 TransactionManagementConfigurationSelector 给容器中导入组件
       导入两个组件:
           AutoProxyRegistrar
           ProxyTransactionManagementConfiguration

   2、AutoProxyRegistrar:
           给容器中注册一个 InfrastructureAdvisorAutoProxyCreator 组件
           InfrastructureAdvisorAutoProxyCreator: ?
               利用后置处理器机制在对象创建以后,包装对象,返回一个代理对象(增强器),代理对象执行方法利用拦截器链进行调用;

   3、ProxyTransactionManagementConfiguration
           1)、给容器中注册 事务增强器
                   ①事务增强器要用事务注解的信息
                       AnnotationTransactionAttributeSource 解析事务注解
                   ②事务拦截器:
                       TransactionInterceptor 保存了事务的属性信息,事务管理器
                       他是一个MethodInterceptor
                       在目标方法执行的时候:
                           执行拦截器链;
                           事务拦截器TransactionInterceptor
                               1、先获取事务相关的属性
                               2、再获取PlatformTransactionManager事务管理器;
                                   如果事先没有添加指定任何TransactionManager
                                   最终会从容器中按照类型获取一个PlatformTransactionManager
                               3、执行目标方法:
                                   如果异常,获取到事务管理器,利用事务管理器回滚这次操作
                                   如果正常,利用事务管理器,提交事务

总结

通过@EnableTransactionManagement注解会为容器中导入AutoProxyRegistrarProxyTransactionManagementConfiguration两个组件;

AutoProxyRegistrar会给容器再注册InfrastructureAdvisorAutoProxyCreator组件,利用后置处理器在对象创建以后,将包装对象,并返回一个代理对象(增强器),返回的代理对象执行方法利用拦截器链调用

ProxyTransactionManagementConfiguration会给容器中注册事务增强器,并给其获取解析事务注解的信息;同时也用事务拦截器先获取事务相关属性,再获取PlatformTransactionManager事务管理器,再执行目标方法,如果异常就回滚操作正常则利用事务管理器提交事务

感谢尚硅谷

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿昌喜欢吃黄桃

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值