快捷搜索:  汽车  科技

spring bean 作用域原理(Spring框架系列之bean的生命周期底层原理之数据库事务整合)

spring bean 作用域原理(Spring框架系列之bean的生命周期底层原理之数据库事务整合)另外咱们来回顾下,在Spring关于Bean的整个生命周期处理过程中,AOP处理发生的时间点以及处理的方式是怎样的呢?这个很重要,因为咱们不可能去修改Spring原有的代码,而只能利用Spring为咱们提供的扩展点来实现数据库的事务处理。而Spring针对事务的处理其实就是在不改动原有代码的情况下,如何添加上述第一步和第三步两个动作,要如何做到呢?其实我们考虑下整个需求,其实就是对原有的数据库操作做了增强的处理,而这个增强处理对于所有想要有事务处理的类来说都是相同的,而这其实就是Spring的AOP的典型应用场景,很明显这里咱们可以Spring的AOP。1.获取数据库连接,设置自动提交的值为false;2.执行SQL语句;3.如果SQL执行成功则执行提交,否则执行回滚操作。

Spring可以说是Java界使用最广泛的框架,没有之一,所以前面咱们花了16章的篇幅,把Spring框架的底层大概分析了一遍。到了这里,笔者觉得是时候开始讲下Spring对于数据库事务的处理机制了,其实只要老铁们把Spring的底层原理整明白了,完全可以自己去分析数据库事务的处理机制。

那么笔者就和大家一起来探讨下,如果是咱们自己来设计Spring对数据库的事务处理机制,咱们应该如何来思考!

要设计数据库的事务处理机制,那首先得了解在使用JDBC执行SQL的情况下,咱们是怎么处理事务的呢?

大概分为几个步骤:

1.获取数据库连接,设置自动提交的值为false;

2.执行SQL语句;

3.如果SQL执行成功则执行提交,否则执行回滚操作。

而Spring针对事务的处理其实就是在不改动原有代码的情况下,如何添加上述第一步和第三步两个动作,要如何做到呢?其实我们考虑下整个需求,其实就是对原有的数据库操作做了增强的处理,而这个增强处理对于所有想要有事务处理的类来说都是相同的,而这其实就是Spring的AOP的典型应用场景,很明显这里咱们可以Spring的AOP。

另外咱们来回顾下,在Spring关于Bean的整个生命周期处理过程中,AOP处理发生的时间点以及处理的方式是怎样的呢?这个很重要,因为咱们不可能去修改Spring原有的代码,而只能利用Spring为咱们提供的扩展点来实现数据库的事务处理。

正常情况下,Spring的AOP处理是发生在初始化后,而非正常情况下,也就是出现循环依赖的情况下,Spring会提前进行AOP,当然,不管是非正常情况或是正常情况,AOP的底层实现逻辑是一样的。

大家想起来这个底层逻辑了嘛?这里Spring会执行所有后置处理器的postProcessAfterInitialization方法,所以如果是咱们自己去实现,则是可以自己实现后置处理的逻辑,当然这里Spring给我们提供了专门用于AOP的抽象类:AbstractAutoProxyCreator,咱们继承这个类,实现指定的逻辑,当然这个指定的逻辑是啥,我们后面看Spring是怎么实现的。

我想这里的逻辑大概过程应该包括:将满足一定条件的类,生成代理对象,当操作这个代理对象的时候,所有的方法调用首先都会经过判断,该方法到底需不需要增强处理,如果需要,则会经过增强处理,也就是设置"自动提交值为false",当方法调用完成后,也会执行提交或回滚的增强逻辑,当然这些增强的逻辑有很多细节需要处理,比如如何跨事务处理等。

以上是我们的大概想法,那接下来,咱们看看Spring是如何处理数据库事务的,笔者将Spring的事务处理机制归结为几个大的步骤:注册后置处理器、生成代理对象、方法增强处理,下面详细描述每个步骤:

一、注册后置处理器

Spring通过增加注解EnableTransactionManagement来开启数据库事务,这个是数据库事务的入口,一切的起源就在这个注解类上:

@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(TransactionManagementConfigurationSelector.class) public @interface EnableTransactionManagement{......}

再看TransactionManagementConfigurationSelector:

public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> { protected String[] selectImports(AdviceMode adviceMode) { switch (adviceMode) { case PROXY: return new String[] {AutoProxyRegistrar.class.getName() ProxyTransactionManagementConfiguration.class.getName()}; case ASPECTJ: return new String[] {determineTransactionAspectClass()}; default: return null; } } }

好,到这里,我们可以看到,Spring将会往Bean工厂中添加AutoProxyRegistrar和ProxyTransactionManagementConfiguration的Bean实例。

来继续看:

public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar { ...... public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata BeanDefinitionRegistry registry) { boolean candidateFound = false; Set<String> annTypes = importingClassMetadata.getAnnotationTypes(); for (String annType : annTypes) { AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata annType); if (candidate == null) { continue; } 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; } } } } ...... } }

其中AnnotationConfigUtils.attributesFor(importingClassMetadata annType)这个方法,是获取EnableTransactionManagement注解的属性值,而AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry)方法,则是注册一个InfrastructureAdvisorAutoProxyCreator类型的Bean,这个Bean的注册名称为:org.springframework.aop.config.internalAutoProxyCreator。

而ProxyTransactionManagementConfiguration则是一个配置类,其中定义了很多重要的Bean实例,其中一个实例类型:BeanFactoryTransactionAttributeSourceAdvisor,它是PointcutAdvisor的实现类,这个类表示啥意思呢?它是切点和代理逻辑(也就是Advice)的封装类,是生成AOP代理对象的核心参数,表示在调用代理对象时,需要对哪些方法进行增强,以及增强的代理逻辑:

@Configuration(proxyBeanMethods = false) public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration { @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME) @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor( TransactionAttributeSource transactionAttributeSource TransactionInterceptor transactionInterceptor) { BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor(); advisor.setTransactionAttributeSource(transactionAttributeSource); advisor.setAdvice(transactionInterceptor); if (this.enableTx != null) { 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( TransactionAttributeSource transactionAttributeSource) { TransactionInterceptor interceptor = new TransactionInterceptor(); interceptor.setTransactionAttributeSource(transactionAttributeSource); if (this.txManager != null) { interceptor.setTransactionManager(this.txManager); } return interceptor; } }

可以看出,切点是AnnotationTransactionAttributeSource对象,而TransactionInterceptor则是代理逻辑对象。

可以想想,这里所有代理对象的切点类都是AnnotationTransactionAttributeSource对象,代理逻辑都是TransactionInterceptor,代理逻辑是一个对象可以理解,因为都设置autocommit、提交事务、回滚事务都是相同的。而切点是同一个,则表明在这个AnnotationTransactionAttributeSource有很多的处理逻辑是针对某个具体的原始对象进行的,而事实上,也确实是这样。

二、生成代理对象

如上面所说,Spring向Bean工厂中添加了InfrastructureAdvisorAutoProxyCreator类型的对象,它的继承关系结构如下:

spring bean 作用域原理(Spring框架系列之bean的生命周期底层原理之数据库事务整合)(1)

它是BeanPostProcessor的实现类,所以初始化完成后,会进入该类的postProcessAfterInitialization方法(这个方法是在AbstractAutoProxyCreator类中实现的),其中调用了方法wrapIfNecessary:

protected Object wrapIfNecessary(Object bean String beanName Object cacheKey) { if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { return bean; } if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass() beanName)) { this.advisedBeans.put(cacheKey Boolean.FALSE); return bean; } Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass() beanName null); if (specificInterceptors != DO_NOT_PROXY) { this.advisedBeans.put(cacheKey Boolean.TRUE); Object proxy = createProxy( bean.getClass() beanName specificInterceptors new SingletonTargetSource(bean)); this.proxyTypes.put(cacheKey proxy.getClass()); return proxy; } this.advisedBeans.put(cacheKey Boolean.FALSE); return bean; }

其中getAdvicesAndAdvisorsForBean方法是关键,这里就是用来获取咱们上面说的BeanFactoryTransactionAttributeSourceAdvisor这个Advisor,我们直到,所有的Bean都会进入这个后置处理器的postProcessAfterInitialization方法,所以不可能是所有的Bean都会返回这个Advisor,一定是满足某些条件的Bean才会返回这个Advisor,那问题来了,这个条件是啥呢?

我们来一步步跟踪下就清楚了:

上述AbstractAutoProxyCreator会调用getAdvicesAndAdvisorsForBean获取Bean支持的所有Advisor,进入到findEligibleAdvisors方法中,在findEligibleAdvisors方法中,List<Advisor> candidateAdvisors = findCandidateAdvisors()会得到所有的Advisor,这里可以获取到我们上面定义的BeanFactoryTransactionAttributeSourceAdvisor,然后调用findAdvisorsThatCanApply方法进行过滤,判断满足条件的Advisor:

protected Object[] getAdvicesAndAdvisorsForBean( Class<?> beanClass String beanName @Nullable TargetSource targetSource) { //关键点入口 List<Advisor> advisors = findEligibleAdvisors(beanClass beanName); if (advisors.isEmpty()) { return DO_NOT_PROXY; } return advisors.toArray(); } protected List<Advisor> findEligibleAdvisors(Class<?> beanClass String beanName) { List<Advisor> candidateAdvisors = findCandidateAdvisors(); //关键点入口 List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors beanClass beanName); ...... } protected List<Advisor> findAdvisorsThatCanApply( List<Advisor> candidateAdvisors Class<?> beanClass String beanName) { ProxyCreationContext.setCurrentProxiedBeanName(beanName); try { //关键点入口 return AopUtils.findAdvisorsThatCanApply(candidateAdvisors beanClass); }finally { ProxyCreationContext.setCurrentProxiedBeanName(null); } }

public abstract class AopUtils{ ...... public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors Class<?> clazz) { ...... boolean hasIntroductions = !eligibleAdvisors.isEmpty(); for (Advisor candidate : candidateAdvisors) { if (candidate instanceof IntroductionAdvisor) { continue; } //关键点入口 if (canApply(candidate clazz hasIntroductions)) { eligibleAdvisors.add(candidate); } } return eligibleAdvisors; } public static boolean canApply(Advisor advisor Class<?> targetClass boolean hasIntroductions) { if (advisor instanceof IntroductionAdvisor) { return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass); } else if (advisor instanceof PointcutAdvisor) { PointcutAdvisor pca = (PointcutAdvisor) advisor; //关键点入口 return canApply(pca.getPointcut() targetClass hasIntroductions); } else { return true; } } public static boolean canApply(Pointcut pc Class<?> targetClass boolean hasIntroductions) { Assert.notNull(pc "Pointcut must not be null"); if (!pc.getClassFilter().matches(targetClass)) { return false; } MethodMatcher methodMatcher = pc.getMethodMatcher(); if (methodMatcher == MethodMatcher.TRUE) { return true; } IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null; if (methodMatcher instanceof IntroductionAwareMethodMatcher) { introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher; } Set<Class<?>> classes = new LinkedHashSet<>(); if (!Proxy.isProxyClass(targetClass)) { classes.add(ClassUtils.getUserClass(targetClass)); } classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass)); for (Class<?> clazz : classes) { Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz); for (Method method : methods) { if (introductionAwareMethodMatcher != null ? introductionAwareMethodMatcher.matches(method targetClass hasIntroductions) : //关键点入口 methodMatcher.matches(method targetClass)) { return true; } } } return false; }

哪些是满足条件的Advisor呢?这个逻辑是由AopUtils来进行处理,而最终的判断是methodMatcher.matches来进行判断,这个methodMatcher是个啥?它是BeanFactoryTransactionAttributeSourceAdvisor对象的TransactionAttributeSourcePointcut属性值,表示切点,它的matches方法:

abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable { public boolean matches(Method method Class<?> targetClass) { TransactionAttributeSource tas = getTransactionAttributeSource(); //关键点入口 return (tas == null || tas.getTransactionAttribute(method targetClass) != null); } ...... }

可以看到调用了TransactionAttributeSource类的TransactionAttributeSource方法,这里大家应该直到TransactionAttributeSource这个类对象是在哪里注入到Spring中的吧?对,它就是AnnotationTransactionAttributeSource对象。

spring bean 作用域原理(Spring框架系列之bean的生命周期底层原理之数据库事务整合)(2)

从上面类的继承关系图上可以看到,最终会进入到AbstractFallbackTransactionAttributeSource的getTransactionAttribute方法

public abstract class AbstractFallbackTransactionAttributeSource implements TransactionAttributeSource { public TransactionAttribute getTransactionAttribute(Method method @Nullable Class<?> targetClass) { if (method.getDeclaringClass() == Object.class) { return null; } Object cacheKey = getCacheKey(method targetClass); TransactionAttribute cached = this.attributeCache.get(cacheKey); if (cached != null) { if (cached == NULL_TRANSACTION_ATTRIBUTE) { return null; } else { return cached; } } else { //关键点入口 TransactionAttribute txAttr = computeTransactionAttribute(method targetClass); if (txAttr == null) { this.attributeCache.put(cacheKey NULL_TRANSACTION_ATTRIBUTE); } else { String methodIdentification = ClassUtils.getQualifiedMethodName(method targetClass); if (txAttr instanceof DefaultTransactionAttribute) { ((DefaultTransactionAttribute) txAttr).setDescriptor(methodIdentification); } if (logger.isTraceEnabled()) { logger.trace("Adding transactional method '" methodIdentification "' with attribute: " txAttr); } this.attributeCache.put(cacheKey txAttr); } return txAttr; } } }

而上述方法computeTransactionAttribute最终会调用SpringTransactionAnnotationParser的parseTransactionAnnotation来返回TransactionAttribute对象:

public class SpringTransactionAnnotationParser implements TransactionAnnotationParser Serializable { public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) { AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes( element Transactional.class false false); if (attributes != null) { return parseTransactionAnnotation(attributes); } else { return null; } } }

上面如果被代理类类或方法上存在Transactional注解,则返回TransactionAttribute对象,否则返回null,这说明什么呢?说明只有被代理的类或方法上存在Transactional注解,才会返回BeanFactoryTransactionAttributeSourceAdvisor这个类型的Advisor对象,才会生成代理对象。

三、方法增强处理

这块涉及到具体的事务处理机制,咱们放到下一章节“Spring框架系列之bean的生命周期底层原理之事务处理机制?”详细分析。

spring bean 作用域原理(Spring框架系列之bean的生命周期底层原理之数据库事务整合)(3)

猜您喜欢: