Spring源码解析之事务(一)
1、开启事务注解:@EnableTransactionManagement
2、向容器注入DataSourceTransactionManager对象,并向其传入DataSource对象。
@Configuration
@ComponentScan
@EnableTransactionManagement
@EnableAspectJAutoProxy
public class TxConfig {
@Bean
public DataSource dataSource() throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource(true);
dataSource.setUser("root");
dataSource.setPassword("123456");
dataSource.setDriverClass("com.mysql.cj.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false");
dataSource.setInitialPoolSize(3);
dataSource.setMaxPoolSize(10);
dataSource.setMinPoolSize(3);
dataSource.setAcquireIncrement(3);
return dataSource;
}
@Bean
@Autowired
public JdbcTemplate jdbcTemplate(DataSource ds) throws PropertyVetoException {
JdbcTemplate jdbcTemplate = new JdbcTemplate(ds);
return jdbcTemplate;
}
@Bean
public PlatformTransactionManager transactionManager() throws PropertyVetoException {
return new DataSourceTransactionManager(dataSource());
}
}
@Repository
public class UserDao {
@Autowired
public JdbcTemplate jdbcTemplate;
@Transactional
public void insert() {
String sql = "INSERT INTO `user` VALUES (7, 'name', '123123', 'test', '44422', '1231231')";
jdbcTemplate.execute(sql);
int i=10/0;
}
}
@Service
public class UserService {
@Autowired
public UserDao userDao;
public void insertUser(){
userDao.insert();
System.out.println("UserService执行成功insertUser()方法");
}
}
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext annotationConfigApplicationContext=new AnnotationConfigApplicationContext(TxConfig.class);
System.out.println("容器初始化成功");
UserService userService = annotationConfigApplicationContext.getBean(UserService.class);
userService.insertUser();
}
}
3、源码解析:
@EnableTransactionManagement注解导入TransactionManagementConfigurationSelector类。TransactionManagementConfigurationSelector类继承了ImportSelector接口,该接口的selectImports方法会返回需要被导入到容器中的类名,TransactionManagementConfigurationSelector的selectImports方法向容器中导入两个组件,分别是AutoProxyRegistrar和ProxyTransactionManagementConfiguration。
AutoProxyRegistrar类为容器注册InfrastructureAdvisorAutoProxyCreator类(如果@EnableTransactionManagement注解的属性AdviceMode为 ---AdviceMode.PROXY)。而aop时注入的是AnnotationAwareAspectJAutoProxyCreator类。
InfrastructureAdvisorAutoProxyCreator类也是一个后置处理器。利用后置处理器机制在对象创建以后,包装对象,返回一个代理对象(增强器),代理对象执行方法利用拦截器链进行调用。
ProxyTransactionManagementConfiguration类是配置类,为容器注册事务增强器BeanFactoryTransactionAttributeSourceAdvisor(bean的名字org.springframework.transaction.config.internalTransactionAdvisor),需要为其添加事务属性(AnnotationTransactionAttributeSource)
AnnotationTransactionAttributeSource实现了接口TransactionAttributeSource,为其注入注解解析器:SpringTransactionAnnotationParser。其中SpringTransactionAnnotationParser是TransactionAnnotationParser的实现类,TransactionAnnotationParser:基于已知的注释类型解析给定方法或类的事务属性。这实际上将已知的事务注释解析为Spring的元数据属性类。如果方法/类不是事务性的,则返回null。
@Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
advisor.setTransactionAttributeSource(transactionAttributeSource());
advisor.setAdvice(transactionInterceptor());//添加拦截器
advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
return advisor;
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
return new AnnotationTransactionAttributeSource();
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionInterceptor transactionInterceptor() {
TransactionInterceptor interceptor = new TransactionInterceptor();
interceptor.setTransactionAttributeSource(transactionAttributeSource());
if (this.txManager != null) {
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
}
ProxyTransactionManagementConfiguration配置类也为容器注入事务拦截器,TransactionInterceptor保存了事务属性信息和事务管理器。
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionInterceptor transactionInterceptor() {
TransactionInterceptor interceptor = new TransactionInterceptor();
interceptor.setTransactionAttributeSource(transactionAttributeSource());
if (this.txManager != null) {
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
4、动态代理源码解析:当UserDao.java的insert方法带有注解:@Transactional,且LogAspects切面类具有execution( public void com.transaction.UserDao.insert(..))的pointcut(切入点)。解析UserDao类实例化返回代理对象的源码(Spring事务与Spring AOP对比学习):
UserDao实例化后,创建代理对象源码起始点(AbstractAdvisorAutoProxyCreator类的wrapIfNecessary(Object bean, String beanName, Object cacheKey)方法,该方法返回所有符合当前类的通知):

------> Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
------>List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
List<Advisor> candidateAdvisors = findCandidateAdvisors();
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
1)查询全部的advisor(通知),然后再筛选符合当前类的通知(advisor)。方法findCandidateAdvisors() ----> this.advisorRetrievalHelper.findAdvisorBeans()
---->advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Advisor.class, true, false); 方法获取到org.springframework.transaction.config.internalTransactionAdvisor,即事务为容器注册的事务增强器BeanFactoryTransactionAttributeSourceAdvisor。
this.aspectJAdvisorsBuilder.buildAspectJAdvisors()方法为容器注入aop相关的通知,包括前置通知,后置通知等等。
@Override
protected List<Advisor> findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
return advisors;
}
2)List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);获取符合当前类的通知
------>canApply(candidate, clazz, hasIntroductions),循环遍历通知,判断当前candidate通知是否作用当前类。事务增强器实现了PointcutAdvisor接口
------>canApply(pca.getPointcut(), targetClass, hasIntroductions),获取事务增强器的切入点pointcut:该切入点继承了对象: TransactionAttributeSourcePointcut,该类重写了getTransactionAttributeSource方法,返回AnnotationTransactionAttributeSource对象。
------>methodMatcher.matches(method, targetClass)) ,获取UserDao以及接口和父类的全部方法,然后判断该通知是否匹配该方法
------>TransactionAttributeSource tas = getTransactionAttributeSource();获取为事务增强器注入的事务属性类。
------>TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
------>TransactionAttribute txAttr = findTransactionAttribute(specificMethod)
------->determineTransactionAttribute(method);
------->源码如下(先获取注解解析器SpringTransactionAnnotationParser然后用其去判断是否匹配)
-------->AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ae, Transactional.class);
protected TransactionAttribute determineTransactionAttribute(AnnotatedElement ae) {
if (ae.getAnnotations().length > 0) {
for (TransactionAnnotationParser annotationParser : this.annotationParsers) {//获取注入的注解解析器
TransactionAttribute attr = annotationParser.parseTransactionAnnotation(ae);
if (attr != null) {
return attr;
}
}
}
return null;
}
5、执行事务方法:
userDao.insert();
-----> public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) ,动态代理对象拦截
----->List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); adviced是AdvisedSupport对象,管理器。
----->cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(this, method, targetClass);
----->循环遍历adviced下(AdvisedSupport对象)的全部通知(Advisor)
----->MethodInterceptor[] interceptors = registry.getInterceptors(advisor);,获取该通知的拦截器列表
----->Advice advice = advisor.getAdvice(); 获取advice,事务事务增强器的拦截器即TransactionInterceptor保存了事务属性信息和事务管理器。将该拦截器添加到该拦截器链中。
----->执行拦截器链:retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
----->依次调用拦截器链中的拦截器的invoke(this)方法,该方法执行完后会调用传参变量(MethodInvocation)的proceed()进而调用下一个拦截器的invoke(this)方法,这也是aop的原理。
----->TransactionInterceptor的invoke方法:
@Override
public Object invoke(final MethodInvocation invocation) throws Throwable {
// Work out the target class: may be {@code null}.
// The TransactionAttributeSource should be passed the target class
// as well as the method, which may be from an interface.
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
// Adapt to TransactionAspectSupport's invokeWithinTransaction...
return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {
@Override
public Object proceedWithInvocation() throws Throwable {
return invocation.proceed();
}
});
}
invokeWithinTransaction方法(spring事务的核心源码):
public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean {
//protected修饰,不允许其他包和无关类调用
protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation) throws Throwable {
// 获取对应事务属性.如果事务属性为空(则目标方法不存在事务)
final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
// 根据事务的属性获取beanFactory中的PlatformTransactionManager(spring事务管理器的顶级接口),一般这里或者的是DataSourceTransactiuonManager
final PlatformTransactionManager tm = determineTransactionManager(txAttr);
// 目标方法唯一标识(类.方法,如service.UserServiceImpl.save)
final String joinpointIdentification = methodIdentification(method, targetClass);
//如果txAttr为空或者tm 属于非CallbackPreferringPlatformTransactionManager,执行目标增强 ①
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
//看是否有必要创建一个事务,根据事务传播行为,做出相应的判断
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
Object retVal = null;
try {
//回调方法执行,执行目标方法(原有的业务逻辑)
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// 异常回滚
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
//清除信息
cleanupTransactionInfo(txInfo);
}
//提交事务
commitTransactionAfterReturning(txInfo);
return retVal;
}
//编程式事务处理(CallbackPreferringPlatformTransactionManager) 不做重点分析
else {
try {
Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr,
new TransactionCallback<Object>() {
@Override
public Object doInTransaction(TransactionStatus status) {
TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
try {
return invocation.proceedWithInvocation();
}
catch (Throwable ex) {
if (txAttr.rollbackOn(ex)) {
// A RuntimeException: will lead to a rollback.
if (ex instanceof RuntimeException) {
throw (RuntimeException) ex;
}
else {
throw new ThrowableHolderException(ex);
}
}
else {
// A normal return value: will lead to a commit.
return new ThrowableHolder(ex);
}
}
finally {
cleanupTransactionInfo(txInfo);
}
}
});
// Check result: It might indicate a Throwable to rethrow.
if (result instanceof ThrowableHolder) {
throw ((ThrowableHolder) result).getThrowable();
}
else {
return result;
}
}
catch (ThrowableHolderException ex) {
throw ex.getCause();
}
}
}
}

浙公网安备 33010602011771号