前言
在上篇文章 Spring 事务使用详解 中详细介绍了 Spring 事务的使用过程,而今天就来看下 Spring 事务是如何来实现,比如 Spring 事务在初始化的时候做了什么,Spring 事务是如何进行事务的提交和回滚的;为了避免篇幅太长,所以分开两篇文章进行分析,这篇文章先来分析下 Spring 事务是如何初始化的,在初始化的时候做了什么。
注册 InfrastructureAdvisorAutoProxyCreator
我们知道,想要使用 Spring 事务,就得开启 Spring 的事务功能,如果是配置文件的方式,则需要在配置文件中配置 标签,那么分析 Spring 事务初始化就从解析该标签开始。
在 TxNamespaceHandler 类的 init 方法中可以看到解析该标签的代码逻辑:
public class TxNamespaceHandler extends NamespaceHandlerSupport { // .......@Overridepublic void init() {registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());}}
所以,当在解析 标签的时候,会使用 AnnotationDrivenBeanDefinitionParser 类的 parse 方法来进行解析:
// AnnotationDrivenBeanDefinitionParser.javapublic BeanDefinition parse(Element element, ParserContext parserContext) {this.registerTransactionalEventListenerFactory(parserContext);String mode = element.getAttribute("mode");if ("aspectj".equals(mode)) { // aspectj 模式this.registerTransactionAspect(element, parserContext);} else { // proxy 模式 AnnotationDrivenBeanDefinitionParser.AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);}return null;}
接下来看下proxy模式,即默认模式的解析;使用的是它的内部类 AopAutoProxyConfigurer 的 configureAutoProxyCreator 方法进行解析:
public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element); // ...............}
在该方法中,第一行就是进行注册 InfrastructureAdvisorAutoProxyCreator,还有其他的bean的注册,这里先不管;先来看下注册过程:
public static void registerAutoProxyCreatorIfNecessary(ParserContext parserContext, Element sourceElement) { // 注册BeanDefinition beanDefinition = AopConfigUtils.registerAutoProxyCreatorIfNecessary(parserContext.getRegistry(), parserContext.extractSource(sourceElement)); // 处理proxy-target-class和 expose-proxy属性useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement); // ......}
这里和 Spring AOP 的处理流程是一样的,显示注册目标bean,再处理 proxy-target-class 和 expose-proxy 属性,可以参考 Spring AOP 注解方式源码解析 ,注册 AopConfigUtils.registerAutoProxyCreatorIfNecessary:
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry,Object source) {return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);}private static BeanDefinition registerOrEscalateApcAsRequired(Class> cls, BeanDefinitionRegistry registry,Object source) { // 处理优先级if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);if (!cls.getName().equals(apcDefinition.getBeanClassName())) {int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());int requiredPriority = findPriorityForClass(cls);if (currentPriority < requiredPriority) {apcDefinition.setBeanClassName(cls.getName());}}return null;}// 注册RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);beanDefinition.setSource(source);beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);return beanDefinition;}
关于该bean的作用下面分析,再 AopAutoProxyConfigurer 的 configureAutoProxyCreator 方法中除了注册该bean,还注册了三个bean,这三个bean用来支撑Spring的整个事务功能:
public static void configureAutoProxyCreator(Element element, ParserContext parserContext) { // 注册 InfrastructureAdvisorAutoProxyCreatorAopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);// 事务AdvisorBeanNameString txAdvisorBeanName = "org.springframework.transaction.config.internalTransactionAdvisor";if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) { // 注册 AnnotationTransactionAttributeSourceObject eleSource = parserContext.extractSource(element);RootBeanDefinition sourceDef = new RootBeanDefinition("org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");sourceDef.setSource(eleSource);sourceDef.setRole(2);String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);// 注册 TransactionInterceptorRootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);interceptorDef.setSource(eleSource);interceptorDef.setRole(2);AnnotationDrivenBeanDefinitionParser.registerTransactionManager(element, interceptorDef);interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);// 注册 BeanFactoryTransactionAttributeSourceAdvisorRootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);advisorDef.setSource(eleSource);advisorDef.setRole(2);// 并把上面注册的两个bean当作该bean的属性advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));advisorDef.getPropertyValues().add("adviceBeanName", interceptorName);if (element.hasAttribute("order")) {advisorDef.getPropertyValues().add("order", element.getAttribute("order"));}parserContext.getRegistry().registerBeanDefinition(txAdvisorBeanName, advisorDef); // 注册其他的事件通知组件}}
这三个 bean 关系如下:
![cef9a61fff9bacb36236bd8c7e2f7a65.png](https://i-blog.csdnimg.cn/blog_migrate/7e76449fe65545cb0acd40bc87e028ce.jpeg)
InfrastructureAdvisorAutoProxyCreator
这个类是什么意思呢?它有什么用呢?按照类名来理解就是 基础的 Advisor 自动代理创建器,对于自定义的 Advisor,则不用它来创建,它的类图如下:
![c86ae4b27d41e14cbfe6e23f21f8d05e.png](https://i-blog.csdnimg.cn/blog_migrate/a7fa12ac45f452cbe2a5591d5eae10dd.jpeg)
可以看到它实现了 BeanPostProcessor 接口,而在前面分析 Spring 相关源码的时候知道,该接口是 Spring 提供了一个扩展接口,有两个方法:
public interface BeanPostProcessor { // bean 初始化之前执行default Object postProcessBeforeInitialization(Object bean, String beanName){return bean;} // bean 初始化之后执行default Object postProcessAfterInitialization(Object bean, String beanName) {return bean;}}
所以,当我们定义的一个 bean 初始化完成后,就会执行 postProcessAfterInitialization 方法,而 InfrastructureAdvisorAutoProxyCreator 类实现了该方法:
public Object postProcessAfterInitialization(Object bean, String beanName) {if (bean != null) { // 根据 beanClassName 和 beanName 创建一个keyObject cacheKey = getCacheKey(bean.getClass(), beanName);if (!this.earlyProxyReferences.contains(cacheKey)) { // 包装 beanreturn wrapIfNecessary(bean, beanName, cacheKey);}}return bean;}// 包装beanprotected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { // 已经处理过了,直接返回if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {return bean;} // 该 bean不需要增强,直接返回if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {return bean;} // 是否是Advice.class, Pointcut.class, Advisor.class, AopInfrastructureBean.class 这几个类,如果是 // 这几个类,或者该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;}// 创建代理protected Object createProxy(Class> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) { // ....ProxyFactory proxyFactory = new ProxyFactory();proxyFactory.copyFrom(this);if (!proxyFactory.isProxyTargetClass()) {if (shouldProxyTargetClass(beanClass, beanName)) { // CGLIB 代理proxyFactory.setProxyTargetClass(true);}else { // JDK接口代理evaluateProxyInterfaces(beanClass, proxyFactory);}} // 创建代理return proxyFactory.getProxy(getProxyClassLoader());}// 真正创建代理public Object getProxy(ClassLoader classLoader) {return createAopProxy().getProxy(classLoader);}protected final synchronized AopProxy createAopProxy() { //.....return getAopProxyFactory().createAopProxy(this);}public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { // 判断 CGLIB 代理和 JDK 代理的条件if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {Class> targetClass = config.getTargetClass(); // JDK 代理if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {return new JdkDynamicAopProxy(config);} // CGLIB 代理return new ObjenesisCglibAopProxy(config);}else { // JDK 代理return new JdkDynamicAopProxy(config);}}
上述的这段代码,当我们的 bean 初始化完成后,就会为该 bean 创建代理,创建代理的时候,根据配置条件创建 JDK 动态代理或者 CGLIB 代理
Spring 代理创建参考 Spring AOP 创建代理的源码解析
但是,是不是所有的 bean 都会创建代理呢,不是的,在包装 bean 的方法 wrapIfNecessary 中,会去查找该bean对应的增强,如果有相应的增强,则才会去创建代理,所有说在创建代理之前,会先去查找该 bean 对应的增强(拦截器),在 wrapIfNecessary 方法中有该代码:
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
对于 Spring 事务来说,该方法返回 specificInterceptors 不可能为空,所以才会走后面创建代理的逻辑。
接下来看下该方法的实现过程,即查询对应 class 或 method 的增强器。
查询对应 class 或 method 的增强器
在 getAdvicesAndAdvisorsForBean 方法中,第一步,要找出符合条件的增强器,第二步,需要判断增强器是否符合要求。
protected Object[] getAdvicesAndAdvisorsForBean(Class> beanClass, String beanName,TargetSource targetSource) { // 根据 className 和 beanName 找出符合条件的增强器List advisors = findEligibleAdvisors(beanClass, beanName);if (advisors.isEmpty()) {return DO_NOT_PROXY;}return advisors.toArray();}// 找出增强器protected List findEligibleAdvisors(Class> beanClass, String beanName) { //查找增强器List candidateAdvisors = findCandidateAdvisors(); //判断增强器是否符合条件List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); //.......return eligibleAdvisors;}
查找增强器 findCandidateAdvisors:
protected List findCandidateAdvisors() {return this.advisorRetrievalHelper.findAdvisorBeans();}public List findAdvisorBeans() {String[] advisorNames = this.cachedAdvisorBeanNames;if (advisorNames == null) { // 获取所有 Advisor.class 类 // 在前面注册的 bean:BeanFactoryTransactionAttributeSourceAdvisor 也是一个 Advisor,// 所以,在这里该 bean 会被提取出来,后续一起植入代理advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Advisor.class, true, false);this.cachedAdvisorBeanNames = advisorNames;}List advisors = new ArrayList<>();for (String name : advisorNames) { // 判断增强器bean是否符合条件,这里返回true if (isEligibleBean(name)) { if (this.beanFactory.isCurrentlyInCreation(name)) {//跳过正在创建的增强器 } else { advisors.add(this.beanFactory.getBean(name, Advisor.class)); } }}return advisors;}
这里要说明一下,在前面注册的bean:BeanFactoryTransactionAttributeSourceAdvisor,它也是一个 Advisor,所以在获取所有的 Advisor.class 类的时候,也会把该 bean 提取出来;此外,该 bean 还拥有 AnnotationTransactionAttributeSource 和 TransactionInterceptor 这两个 bean,后面会一起被织入代理。
当查找到所有的增强后,需要判断哪些增强符合我们的目标 bean,对应方法 findAdvisorsThatCanApply:
public static List findAdvisorsThatCanApply(List candidateAdvisors, Class> clazz) { // 用来存放符合条件的增强List eligibleAdvisors = new ArrayList<>(); // 处理引介增强for (Advisor candidate : candidateAdvisors) {if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {eligibleAdvisors.add(candidate);}}boolean hasIntroductions = !eligibleAdvisors.isEmpty();for (Advisor candidate : candidateAdvisors) {if (candidate instanceof IntroductionAdvisor) {// 在处理引介增强时已经处理过了continue;} // 普通的beanif (canApply(candidate, clazz, hasIntroductions)) {eligibleAdvisors.add(candidate);}}return eligibleAdvisors;}
canApply 方法:
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) { /// pca=BeanFactoryTransactionAttributeSourceAdvisorPointcutAdvisor pca = (PointcutAdvisor) advisor; //pca.getPointcut()=TransactionAttributeSourcePointcutreturn canApply(pca.getPointcut(), targetClass, hasIntroductions);}else {return true;}}
对于一个事务 bean 来说,该增强 Advisor 就是前面注册的 BeanFactoryTransactionAttributeSourceAdvisor,而该 bean 实现了 PointcutAdvisor 接口,所以会通过 第二个 if 判断;之后 通过 getPointcut 得到 TransactionAttributeSourcePointcut 对象继续调用 重载的 canApply 方法如下:
public static boolean canApply(Pointcut pc, Class> targetClass, boolean hasIntroductions) {// 获取方法匹配器 // 此时的匹配器是 TransactionAttributeSourcePointcutMethodMatcher methodMatcher = pc.getMethodMatcher();// 如果可以匹配所有方法,则不再循环方法进行判断if (methodMatcher == MethodMatcher.TRUE) {return true;} // 存放目标类和目标类所有的接口Set> 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;}
到这里,只看到了根据方法去判断是否符合增强器,没有根据类来和接口判断,因为事务注解 Translation 可以放在类或接口上,对其下的所有public方法有用;其实,对类和接口的判断条件在是在 matcher 方法里面,调用的使用 TransactionAttributeSourcePointcut 的 mathcer 方法:
public boolean matches(Method method, Class> targetClass) {// .....TransactionAttributeSource tas = getTransactionAttributeSource();return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);}
这里的 tas 就是 AnnotationTransactionAttributeSource,即在文章开头注册的那三个 bean 之一,它的 getTransactionAttribute 如下,去获取事务:
public TransactionAttribute getTransactionAttribute(Method method, Class> targetClass) {// 忽略 Object 的方法if (method.getDeclaringClass() == Object.class) {return null;}// 根据method和class来创建keyObject cacheKey = getCacheKey(method, targetClass);// 根据key查询事务,TransactionAttribute cached = this.attributeCache.get(cacheKey);if (cached != null) { //... // 已经判断过了 return cached;}else { TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass); //.... return txAttr;}}
computeTransactionAttribute 方法如下:
protected TransactionAttribute computeTransactionAttribute(Method method, Class> targetClass) {// 不是public方法,则跳过if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {return null;}// 实现类的方法Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);// 首先在实现类的方法上查询注解,查询到,则直接返回TransactionAttribute txAttr = findTransactionAttribute(specificMethod);if (txAttr != null) {return txAttr;}// 如果在实现类对应方法上找不到注解,则在方法的实现类上查找注解,找到直接返回txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {return txAttr;} // 存在接口if (specificMethod != method) {// 在接口方法上查找注解,找到直接返回txAttr = findTransactionAttribute(method);if (txAttr != null) {return txAttr;}// 如果在接口方法上找不到注解,则在接口上查找注解txAttr = findTransactionAttribute(method.getDeclaringClass());if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {return txAttr;}}return null;}
在上述的 computeTransactionAttribute 方法中,可以看到,去查找是一个事务方法,首先在实现类的方法上查找,找到直接返回,如果还找不到,则在实现类上查找注解;如果在实现类上找不到,再到接口上的方法里面去找,如果接口方法还找不到,则再接口上查找;所以,在这里可以看到,放在类或接口上事务注解可以作用于其下的所有 public 方法,且 方法上的事务注解要优先于类或接口上的注解,即如果再类,接口和方法上都加上事务注解,则会以方法上的注解为准,其次是 类,最后才是接口。
之后,就是去解析注解的属性,对应方法为:findTransactionAttribute,
protected TransactionAttribute findTransactionAttribute(Method method) {return determineTransactionAttribute(method);}protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) { // 事务注解解析器for (TransactionAnnotationParser annotationParser : this.annotationParsers) {TransactionAttribute attr = annotationParser.parseTransactionAnnotation(element);if (attr != null) {return attr;}}return null;}// 方法上获取 Transactional 注解public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) { // 在方法上获取 Transactional 注解AnnotationAttributes attributes =AnnotatedElementUtils.findMergedAnnotationAttributes(element, Transactional.class, false, false);if (attributes != null) { // 解析 Transactional 注解属性return parseTransactionAnnotation(attributes);}else {return null;}}// 解析 Transactional 注解属性protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();Propagation propagation = attributes.getEnum("propagation");rbta.setPropagationBehavior(propagation.value());Isolation isolation = attributes.getEnum("isolation");rbta.setIsolationLevel(isolation.value());rbta.setTimeout(attributes.getNumber("timeout").intValue());rbta.setReadOnly(attributes.getBoolean("readOnly"));rbta.setQualifier(attributes.getString("value"));List rollbackRules = new ArrayList<>();for (Class> rbRule : attributes.getClassArray("rollbackFor")) {rollbackRules.add(new RollbackRuleAttribute(rbRule));}for (String rbRule : attributes.getStringArray("rollbackForClassName")) {rollbackRules.add(new RollbackRuleAttribute(rbRule));}for (Class> rbRule : attributes.getClassArray("noRollbackFor")) {rollbackRules.add(new NoRollbackRuleAttribute(rbRule));}for (String rbRule : attributes.getStringArray("noRollbackForClassName")) {rollbackRules.add(new NoRollbackRuleAttribute(rbRule));}rbta.setRollbackRules(rollbackRules);return rbta;}
在这里就可以看到,事务注解 Transaction 的各种各样的属性了。
当然,到这里还没有完;到这里,可以从下往上看下所有的代码,当方法存在 Transaction 注解的时候,该方法 就会满足增强器 BeanFactoryTransactionAttributeSourceAdvisor ,之后就会为我们的目标bean 创建代理,并把 增强器 BeanFactoryTransactionAttributeSourceAdvisor 织入到代理中,进而来影响我们的业务逻辑。
总结
这篇文章主要介绍了 Spring 事务的初始化功能,在 Spring 加载的时候,会注册 InfrastructureAdvisorAutoProxyCreator bean,而该 bean 又实现了 BeanPostProcessor 接口,所以当目标bean在初始化完成后,会执行 postProcessAfterInitialization 方法,在该方法中,会去遍历我们的目标 bean 中的方法,如果方法上有 Translaction 事务注解,则会为目标 bean 创建代理,并把 增强器 BeanFactoryTransactionAttributeSourceAdvisor 织入到代理中;当然,BeanFactoryTransactionAttributeSourceAdvisor 该 bean 还拥有 AnnotationTransactionAttributeSource 和 TransactionInterceptor 这两个 bean,会一起被织入代理。
所以在 Spring 事务初始化的过程中,主要注册了四个 bean:
1. InfrastructureAdvisorAutoProxyCreator
2. BeanFactoryTransactionAttributeSourceAdvisor
3. AnnotationTransactionAttributeSource
4. TransactionInterceptor
InfrastructureAdvisorAutoProxyCreator 主要是用来查找方法,类或者接口上的事务注解 Translaction,如果存在注解,则为目标bean创建代理,并把其他的三个 bean 织入到代理中,而另外的三个 bean 主要是用来 执行目标方法,进行事务的提交和回滚。