Spring注解系列二十六:声明式事务

一、基本使用
1、配置类 TxConfig 。主要有两点:
(1)、@EnableTransactionManagement 开启基于注解的事务管理功能;相当于<tx:annotation-driven/>
(2)、要配置事务管理器来控制事务;PlatformTransactionManager

@EnableTransactionManagement  //开启基于注解的事务管理功能
@ComponentScan("com.atguigu.tx")
@Configuration
public class TxConfig {
	
	//数据源
	@Bean
	public DataSource dataSource() throws Exception{
		ComboPooledDataSource dataSource = new ComboPooledDataSource();
		dataSource.setUser("root");
		dataSource.setPassword("123456");
		dataSource.setDriverClass("com.mysql.jdbc.Driver");
		dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
		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());
	}
	
}

2、UserDao

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

}

3、@Transactional 注解表示当前方法是一个事务方法

@Service
public class UserService {
	
	@Autowired
	private UserDao userDao;
	
	@Transactional  //表示当前方法是一个事务方法
	public void insertUser(){
		userDao.insert();

		System.out.println("插入完成...");
		int i = 10/0;
	}

}

测试:

@Test
public void test01(){
	AnnotationConfigApplicationContext applicationContext = 
			new AnnotationConfigApplicationContext(TxConfig.class);

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

在这里插入图片描述
添加事务后,抛异常就会回滚操作,数据表没有插入数据。
在这里插入图片描述
二、源码解析
1、@EnableTransactionManagement
 利用TransactionManagementConfigurationSelector给容器中会导入两个组件:AutoProxyRegistrar和ProxyTransactionManagementConfiguration;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({TransactionManagementConfigurationSelector.class})
public @interface EnableTransactionManagement {
    boolean proxyTargetClass() default false;

    AdviceMode mode() default AdviceMode.PROXY;

    int order() default 2147483647;
}
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
    public TransactionManagementConfigurationSelector() {
    }

    protected String[] selectImports(AdviceMode adviceMode) {
        switch(adviceMode) {
        case PROXY:
            return new String[]{AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()};
        case ASPECTJ:
            return new String[]{"org.springframework.transaction.aspectj.AspectJTransactionManagementConfiguration"};
        default:
            return null;
        }
    }
}

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

public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
 	boolean candidateFound = false;
    Set<String> annoTypes = importingClassMetadata.getAnnotationTypes();
    Iterator var5 = annoTypes.iterator();

    while(var5.hasNext()) {
        String annoType = (String)var5.next();
        AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annoType);
        if (candidate != null) {
            Object mode = candidate.get("mode");
            Object proxyTargetClass = candidate.get("proxyTargetClass");
            if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() && Boolean.class == proxyTargetClass.getClass()) {
                candidateFound = true;
                if (mode == AdviceMode.PROXY) {
                    AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
                    if ((Boolean)proxyTargetClass) {
                        AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
                        return;
                    }
                }
            }
        }
    }

    if (!candidateFound) {
        String name = this.getClass().getSimpleName();
        this.logger.warn(String.format("%s was imported but no annotations were found having both 'mode' and 'proxyTargetClass' attributes of type AdviceMode and boolean respectively. This means that auto proxy creator registration and configuration may not have occurred as intended, and components may not be proxied as expected. Check to ensure that %s has been @Import'ed on the same class where these annotations are declared; otherwise remove the import of %s altogether.", name, name, name));
    }

}

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

@Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
    public ProxyTransactionManagementConfiguration() {
    }

    @Bean(
        name = {"org.springframework.transaction.config.internalTransactionAdvisor"}
    )
    @Role(2)
    public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
        BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
        advisor.setTransactionAttributeSource(this.transactionAttributeSource());
        advisor.setAdvice(this.transactionInterceptor());
        advisor.setOrder((Integer)this.enableTx.getNumber("order"));
        return advisor;
    }

    @Bean
    @Role(2)
    public TransactionAttributeSource transactionAttributeSource() {
        return new AnnotationTransactionAttributeSource();
    }

    @Bean
    @Role(2)
    public TransactionInterceptor transactionInterceptor() {
        TransactionInterceptor interceptor = new TransactionInterceptor();
        interceptor.setTransactionAttributeSource(this.transactionAttributeSource());
        if (this.txManager != null) {
            interceptor.setTransactionManager(this.txManager);
        }

        return interceptor;
    }
}
public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {
    public TransactionInterceptor() {
    }

    public TransactionInterceptor(PlatformTransactionManager ptm, Properties attributes) {
        this.setTransactionManager(ptm);
        this.setTransactionAttributes(attributes);
    }

    public TransactionInterceptor(PlatformTransactionManager ptm, TransactionAttributeSource tas) {
        this.setTransactionManager(ptm);
        this.setTransactionAttributeSource(tas);
    }

    public Object invoke(final MethodInvocation invocation) throws Throwable {
        Class<?> targetClass = invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null;
        return this.invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {
            public Object proceedWithInvocation() throws Throwable {
                return invocation.proceed();
            }
        });
    }

    private void writeObject(ObjectOutputStream oos) throws IOException {
        oos.defaultWriteObject();
        oos.writeObject(this.getTransactionManagerBeanName());
        oos.writeObject(this.getTransactionManager());
        oos.writeObject(this.getTransactionAttributeSource());
        oos.writeObject(this.getBeanFactory());
    }

    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
        ois.defaultReadObject();
        this.setTransactionManagerBeanName((String)ois.readObject());
        this.setTransactionManager((PlatformTransactionManager)ois.readObject());
        this.setTransactionAttributeSource((TransactionAttributeSource)ois.readObject());
        this.setBeanFactory((BeanFactory)ois.readObject());
    }
}

TransactionAspectSupport

protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final TransactionAspectSupport.InvocationCallback invocation) throws Throwable {
    final TransactionAttribute txAttr = this.getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
    final PlatformTransactionManager tm = this.determineTransactionManager(txAttr);
    final String joinpointIdentification = this.methodIdentification(method, targetClass, txAttr);
    if (txAttr != null && tm instanceof CallbackPreferringPlatformTransactionManager) {
        try {
            Object result = ((CallbackPreferringPlatformTransactionManager)tm).execute(txAttr, new TransactionCallback<Object>() {
                public Object doInTransaction(TransactionStatus status) {
                    TransactionAspectSupport.TransactionInfo txInfo = TransactionAspectSupport.this.prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);

                    TransactionAspectSupport.ThrowableHolder var4;
                    try {
                        Object var3 = invocation.proceedWithInvocation();
                        return var3;
                    } catch (Throwable var8) {
                        if (txAttr.rollbackOn(var8)) {
                            if (var8 instanceof RuntimeException) {
                                throw (RuntimeException)var8;
                            }

                            throw new TransactionAspectSupport.ThrowableHolderException(var8);
                        }

                        var4 = new TransactionAspectSupport.ThrowableHolder(var8);
                    } finally {
                        TransactionAspectSupport.this.cleanupTransactionInfo(txInfo);
                    }

                    return var4;
                }
            });
            if (result instanceof TransactionAspectSupport.ThrowableHolder) {
                throw ((TransactionAspectSupport.ThrowableHolder)result).getThrowable();
            } else {
                return result;
            }
        } catch (TransactionAspectSupport.ThrowableHolderException var14) {
            throw var14.getCause();
        }
    } else {
        TransactionAspectSupport.TransactionInfo txInfo = this.createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
        Object retVal = null;

        try {
            retVal = invocation.proceedWithInvocation();
        } catch (Throwable var15) {
            this.completeTransactionAfterThrowing(txInfo, var15);
            throw var15;
        } finally {
            this.cleanupTransactionInfo(txInfo);
        }

        this.commitTransactionAfterReturning(txInfo);
        return retVal;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值