你必须懂!也可以懂的@Transactional原理!
Posted Java程序员飞飞
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了你必须懂!也可以懂的@Transactional原理!相关的知识,希望对你有一定的参考价值。
1.前言
系统应用开发过程中通常需要使用事务来保证业务数据的一致性,实现方式如:开启事务、执行数据库写操作、提交或者回滚事务,这种标准实现方式适用于少量一致性业务,如果存在大量需要保证数据一致性的业务,不仅会让开发人员重复编码,还会给系统造成冗余代码。基于这些问题,伟大的Spring框架为我们提供了@Transactional注解,那么它是如何使用一个注解就解决了我们的烦恼呢?我们该如何着手进行分析呢?
SpringBoot集成的功能往往要从一个xxxAutoConfiguration开始说起
2.自动配置
打开TransactionAutoConfiguration自动配置类可以看到一个比较重要的注解@EnableTransactionManagement用于开启事务管理功能,@EnableTransactionManagement注解又导入了AutoProxyRegistrar和ProxyTransactionManagementConfiguration
2.1 事务配置
ProxyTransactionManagementConfiguration中声明了一个切面BeanFactoryTransactionAttributeSourceAdvisor,看到切面必定会有相对应的切点TransactionAttributeSourcePointcut(用于声明切入的范围)和通知TransactionInterceptor(用于实现切入目标的后续操作)。
2.2 声明@Transactional注解处理器
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
return new AnnotationTransactionAttributeSource();
}
AnnotationTransactionAttributeSource实例化指定了注解解析器为SpringTransactionAnnotationParser
可以看到该解析器主要用来处理@Transactional注解
2.3 注入自动代理注册器
在2.自动配置提到@EnableTransactionManagement还引入了AutoProxyRegistrar,向IOC容器中注入InfrastructureAdvisorAutoProxyCreator
@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}
InfrastructureAdvisorAutoProxyCreator实现了BeanPostProcessor接口,具有拦截并处理Bean的能力
2.3.1 Bean后置处理
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
2.3.2 从容器中获取所有的Advisor
/**
* Find all candidate Advisors to use in auto-proxying.
* @return the List of candidate Advisors
*/
protected List<Advisor> findCandidateAdvisors() {
Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
return this.advisorRetrievalHelper.findAdvisorBeans();
}
2.3.3 筛选出符合条件的Advisor
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
// 1.获取切点对应的MethodMatcher
MethodMatcher methodMatcher = pc.getMethodMatcher();
for (Class<?> clazz : classes) {
// 2.获取当前类中的所有方法
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
// 3.判断是否符合切点要求,此处的methodMatcher为TransactionAttributeSourcePointcut
if (methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
判断方法上是否有@Transactional注解,如果有则使用SpringTransactionAnnotationParser进行解析并生成TransactionAttribute
2.3.4 Advisor排序
sortAdvisors(eligibleAdvisors);
2.3.4 小结
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 1.从容器中获取所有类型为Advisor的切面
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 2.筛选出符合条件的切面(也就是类或方法上被@Transactional注解标注)
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
// 3.对符合条件的切面进行升序排序
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
2.4 选择代理方法
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (!IN_NATIVE_IMAGE &&
(config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {
Class<?> targetClass = config.getTargetClass();
// 1.如果实现接口则选择jdk代理
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
// 2.选择cglib代理
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
2.4.1 生成代理
此处以cglib为例
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
try {
Class<?> rootClass = this.advised.getTargetClass();
Class<?> proxySuperClass = rootClass;
// Configure CGLIB Enhancer...
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
}
enhancer.setSuperclass(proxySuperClass);
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
Callback[] callbacks = getCallbacks(rootClass);
}
}
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
// Choose an "aop" interceptor (used for AOP calls).
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
}
创建Enhancer并指定回调为DynamicAdvisedInterceptor
2.5 调用代理
执行被代理对象目标方法userService.saveUser(user);时会调用DynamicAdvisedInterceptor的intercept()方法
2.5.1 筛选满足条件的Advice
@Override
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass) {
// 1.遍历所有满足条件的Advisor,也就是2.3.3章节返回的Advisor
for (Advisor advisor : advisors) {
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
// 2. 判断是否满足切点要求
boolean match = mm.matches(method, actualClass);
// 3.满足切点要求
if (match) {
// 3. 获取切面对应的通知,也就是TransactionInterceptor
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
// 4.返回满足条件的通知
return interceptorList;
}
2.5.2 执行满足条件的Advice
@Override
@Nullable
public Object proceed() throws Throwable {
// 1.如果没有advice可以执行,则执行目标方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
// 2.从advice列表中取出一个advice
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
// 3.执行advice的invoke方法,也就是TransactionInterceptor的invoke
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
3. 事务调用
3.1 获取事务配置属性
TransactionAttributeSource tas = getTransactionAttributeSource();
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
也就是@Transactional注解声明的属性
3.2 获取事务管理器
final TransactionManager tm = determineTransactionManager(txAttr);
从容器中获取DataSourceTransactionManagerAutoConfiguration自动配置类中声明的事务管理器JdbcTransactionManager
public class DataSourceTransactionManagerAutoConfiguration {
@Bean
@ConditionalOnMissingBean(TransactionManager.class)
JdbcTransactionManager transactionManager(DataSource dataSource,
ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {
JdbcTransactionManager transactionManager = new JdbcTransactionManager(dataSource);
transactionManagerCustomizers.ifAvailable((customizers) -> customizers.customize(transactionManager));
return transactionManager;
}
}
3.3 执行事务
4. 总结
@Transactional实现原理三要素切面、切点、通知
- InfrastructureAdvisorAutoProxyCreator后置处理器拦截所有Bean
- 遍历所有类型为Advisor的切面
- 返回满足切点条件的切面列表
- 选择代理方法
- 生成代理
- 调用通知的invoke()方法
开启事务
调用其它通知的invoke()方法,如果没有执行目标方法
执行异常,回滚事务
执行成功,提交事务 - 执行目标方法
了解@Transactional注解实现原理,不仅可以让我们对切面、切点、通知有一个清晰的认识,还可以让我们通过其思想实现类似功能,如@Cache注解实现应用缓存,@Async注解实现业务异步执行
Java高级架构面试知识点整理
以上是关于你必须懂!也可以懂的@Transactional原理!的主要内容,如果未能解决你的问题,请参考以下文章