Spring AOP源码篇四之 数据库事务

了解了Spring AOP执行过程,再看Spring事务源码其实非常简单。
首先从简单使用开始, 演示Spring事务使用过程

Xml配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xmlns:aop="http://www.springframework.org/schema/aop"
	   xmlns:tx="http://www.springframework.org/schema/tx"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

	<!-- 数据库连接池 -->
	<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
		<property name="url" value="jdbc:mysql:///custom_db" />
		<property name="username" value="root" />
		<property name="password" value="123456" />
		<property name="driverClassName" value="com.mysql.jdbc.Driver" />
	</bean>

	<!-- JdbcTemplate 对象 -->
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource"></property>
	</bean>

	<!-- transactionManager 对象 -->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>

	<tx:advice id="txAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			<tx:method name="*" propagation="REQUIRED"/>
		</tx:attributes>
	</tx:advice>

	<aop:config>
		<aop:advisor advice-ref="txAdvice" pointcut="execution(* org.spring.tx.dao.*.*(..))"></aop:advisor>
	</aop:config>


	<bean id="userDao" class="org.spring.tx.dao.UserDaoImpl">
		<constructor-arg index="0" ref="jdbcTemplate"></constructor-arg>
	</bean>

</beans>

实体类:

package org.spring.tx.dto;

public class UserDto {
	private Long id;
	private String UserName;

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getUserName() {
		return UserName;
	}

	public void setUserName(String userName) {
		UserName = userName;
	}
}

业务Dao类:

package org.spring.tx.dao;

import org.spring.tx.dto.UserDto;

public interface UserDao {
	void insert(UserDto userDto);
}
package org.spring.tx.dao;

import org.spring.tx.dto.UserDto;
import org.springframework.jdbc.core.JdbcTemplate;

public class UserDaoImpl implements UserDao {
	//注入 JdbcTemplate
	private JdbcTemplate jdbcTemplate;

	public UserDaoImpl(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}

	@Override
	public void insert(UserDto userDto) {
		//创建 sql 语句
		String sql = "insert into user (username)values(?)";
		//调用方法实现
		Object[] args = {userDto.getUserName()};
		//返回影响行数
		int update = jdbcTemplate.update(sql,args);
		System.out.println("user新增条数:" + update);
		//throw new RuntimeException("业务出错了!!!");
	}
}

测试代码:

package org.spring.tx;

import org.spring.tx.dao.UserDao;
import org.spring.tx.dto.UserDto;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainTest {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-tx.xml");
        applicationContext.start();

        UserDao userDao = applicationContext.getBean(UserDao.class);
        UserDto userDto = new UserDto();
        userDto.setUserName("zhangsan");
        userDao.insert(userDto);

        applicationContext.stop();
    }
}

执行结果:

==================从源码角度简单分析一下=====================
根据Spring AOP过程(参考:Spring AOP源码篇二之 代理工厂ProxyFactory学习-CSDN博客  Spring AOP源码篇三之 xml配置-CSDN博客),增强工作由Advice完成,而事务的Advice对应的是TransactionInterceptor.
public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {

    public TransactionInterceptor() {
    }
    
    public TransactionInterceptor(PlatformTransactionManager ptm, Properties attributes) {
        setTransactionManager(ptm);
        setTransactionAttributes(attributes);
    }
    
    public TransactionInterceptor(PlatformTransactionManager ptm, TransactionAttributeSource tas) {
        setTransactionManager(ptm);
        setTransactionAttributeSource(tas);
    }

    //TransactionInterceptor实现了Advice(MethodInterceptor)接口,增强工作由该方法完成
    //核心代码,方法调用入口
    public Object invoke(final MethodInvocation invocation) throws Throwable {
        Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);

        // 父类TransactionAspectSupport中方法
        return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {
            public Object proceedWithInvocation() throws Throwable {
                return invocation.proceed();
            }
        });
    }


    //---------------------------------------------------------------------
    // Serialization support
    //---------------------------------------------------------------------

    private void writeObject(ObjectOutputStream oos) throws IOException {
        // Rely on default serialization, although this class itself doesn't carry state anyway...
        oos.defaultWriteObject();

        // Deserialize superclass fields.
        oos.writeObject(getTransactionManagerBeanName());
        oos.writeObject(getTransactionManager());
        oos.writeObject(getTransactionAttributeSource());
        oos.writeObject(getBeanFactory());
    }

    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
        // Rely on default serialization, although this class itself doesn't carry state anyway...
        ois.defaultReadObject();

        // Serialize all relevant superclass fields.
        // Superclass can't implement Serializable because it also serves as base class
        // for AspectJ aspects (which are not allowed to implement Serializable)!
        setTransactionManagerBeanName((String) ois.readObject());
        setTransactionManager((PlatformTransactionManager) ois.readObject());
        setTransactionAttributeSource((TransactionAttributeSource) ois.readObject());
        setBeanFactory((BeanFactory) ois.readObject());
    }

}

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值