细节知多少 - spring boot transaction解析之阶段一 带有@Transactional方法的service类生成代理类的阶段
date: 2019-06-04
原文:spring boot transaction解析之阶段一 带有@Transactional方法的service类生成代理类的阶段
概述
spring boot transaction我们平时用着非常简单,只需要在service方法上声明@Transactional就可以了。但是要知道,简单的背后是不简单,只是很多东西spring框架帮我们做好了。如果想进阶,想进步,想弄懂,想学习,需要接近它,了解它,弄懂它,最好的方法莫过于debug它的源码了。
笔者把spring boot transaction的整个过程分为两个阶段
- 带有@Transactional方法的service类生成代理类的阶段
- 访问service类的@Transactional方法实现事务的阶段
本文说下第一阶段,用过spring的人差不多都是知道,spring 事务的实现是通过aop的方式。所以本系列的前提是基于注解的aop实现解析你要知道些,这部分请参考:spring boot aop过程解析之阶段一 AnnotationAwareAspectJAutoProxyCreator加载和初始化, AnnotationAwareAspectJAutoProxyCreator是aop动态代理的起始点和入口处,所有的beanClass经过通过他的实例化前置方法和所有的bean Object经过他的初始化后置方法时都会判断是否生成代理类。笔者假定你了解了这部分。
本文用到的代码项目:springboot_mybatis
技术栈
spring boot 1.5.10
spring framework 4.3.14
用例代码
@RestController
@Slf4j
@RequestMapping("/user")
public class UserController {
@Resource
private IUserService userService;
/**
* @param schoolName
* @param studentId
* @return
*/
@GetMapping("/updateSchoolName")
public ResponseResult updateSchoolName(String schoolName, long studentId) {
log.info("updateSchoolName param schoolName:{} studentId:{}", schoolName, studentId);
userService.updateSchoolName(schoolName, studentId);
return ResponseResult.ok();
}
}
public interface IUserService {
int insert(User user);
int updateScore(long score, long id);
void updateSchoolName(String schoolName, long studentId);
}
@Service
public class UserServiceImpl implements IUserService {
@Resource
private UserMapper userMapper;
@Resource
private StudentMapper studentMapper;
@Override
@Transactional(rollbackFor = Throwable.class)
public int insert(User user) {
int count = userMapper.insert(user);
return count;
}
@Override
@Transactional(rollbackFor = Throwable.class)
public int updateScore(long score, long id) {
int count = userMapper.updateScore(iii, id);
return count;
}
@Override
@Transactional(rollbackFor = Throwable.class)
public void updateSchoolName(String schoolName, long studentId) {
User user = userMapper.fingByStudentId(studentId);
studentMapper.updateSchoolName(schoolName, user.getStudentId());
}
}
public interface StudentMapper {
Student findById(@Param("id") long id);
int updateSchoolName(@Param("schoolName") String schoolName, @Param("id") long id);
}
public interface UserMapper {
int insert(User user);
int updateScore(@Param("score") long score, @Param("id") long id);
}
以上代码模拟了实际开发中mvc层级调用关系,事务在service层。我们以此代码为例阐述spring事务相关知识点
带着问题学习
带着问题学习往往起到更好的效果
问题:
1. service类只要有方法加了@Transactional注解就会生成代理类吗,此处的方法有条件吗
2. spring boot 涉及transaction事务的xxxAutoConfiguration都有哪些
3. spring boot 默认生成代理的方式是cglib还是jdk
4. 什么样的方法可以生成代理方法
下面开始和笔者一起走入spring aop生成代理类的小溪,从本文开头处我们知道,生成代理类的入口是AnnotationAwareAspectJAutoProxyCreator(使用父类的方法)实例化前置方法和初始化后置方法(如果此处不太了解,请参考:spring boot aop过程解析之阶段一 AnnotationAwareAspectJAutoProxyCreator加载和初始化)。我们直接从此处展开
生成代理类条件判断
我们看下前后置方法的代码。同样,因为这里在spring boot aop过程解析之阶段一 AnnotationAwareAspectJAutoProxyCreator加载和初始化)已经阐述过。所以这里我们只关注和spring transaction有关的地方
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
······
// shouldSkip方法是重点,判断是否应该为beanClass生成代理类
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) { // (1)
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
// Create proxy here if we have a custom TargetSource
if (beanName != null) {
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
this.targetSourcedBeans.add(beanName);
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); // (2)
Object proxy = createProxy(beanClass, beanName, sp