Source code analysis of Spring transaction initialization

Keywords: Java Spring Back-end source code

preface

In the last article   Spring transaction usage details   Described in detail in   Spring   Let's take a look at the usage process of transactions today   Spring   How are transactions implemented, such as   Spring   What does the transaction do during initialization, spring   How transactions are committed and rolled back; In order to avoid too long, separate two articles for analysis. This article will analyze it first   Spring   How the transaction is initialized and what is done during initialization.

Register infrastructure advisor autoproxycreator

We know, want to use   Spring   Business, you have to turn it on   Spring   If the transaction function is configured in the configuration file, it needs to be configured in the configuration file  < tx:annotation-driven />   Label, then analyze   Spring   Transaction initialization starts with parsing the tag.

stay   TxNamespaceHandler   Class   init   Method, you can see the code logic for parsing the tag:

 public class TxNamespaceHandler extends NamespaceHandlerSupport {
    // .......
    @Override
    public void init() {
        registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());
        registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
        registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());
    }
}

So, when parsing  < tx:annotation-driven />   When labeling, it will be used   AnnotationDrivenBeanDefinitionParser   Class   parse   Method to parse:

// AnnotationDrivenBeanDefinitionParser.java

public BeanDefinition parse(Element element, ParserContext parserContext) {
    this.registerTransactionalEventListenerFactory(parserContext);
    String mode = element.getAttribute("mode");
    if ("aspectj".equals(mode)) {
        //  aspectj   pattern
        this.registerTransactionAspect(element, parserContext);
    } else {
        //  proxy   pattern  
    AnnotationDrivenBeanDefinitionParser.AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
    }
    return null;
}

Next, let's look at the proxy mode, that is, the resolution of the default mode; That is, its inner class is used   AopAutoProxyConfigurer   of   configureAutoProxyCreator   Method:

public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {
    AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);
    // ...............
}

In this method, the first line is to register   Infrastructure advisor autoproxycreator and other bean registrations are ignored here; Let's first look at the registration process:

public static void registerAutoProxyCreatorIfNecessary(ParserContext parserContext, Element sourceElement) {
    //  register
    BeanDefinition beanDefinition = AopConfigUtils.registerAutoProxyCreatorIfNecessary(
            parserContext.getRegistry(), parserContext.extractSource(sourceElement));
    //  Handling proxy target class and   Expose proxy attribute
    useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
    // ......
}

Here and   Spring AOP   The processing flow is the same. First, register the target   bean, reprocessing   proxy-target-class   and   expose-proxy   Property, you can refer to: Spring AOP annotation source code parsing( https://my.oschina.net/mengyuankan/blog/2995521)

Register infrastructure advisor autoproxycreator.class

public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry,Object source) {
    return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}

private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, 
                BeanDefinitionRegistry registry,Object source) {
    //  Processing Priority 
    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;
    }
    //  register
    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;
}

About this   bean   The role of is analyzed below   AopAutoProxyConfigurer   of   configureAutoProxyCreator   Method in addition to registering the   Bean, also registered three beans, these three   bean   Used to support   Spring   The entire transaction function of:

public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {
    //  register   InfrastructureAdvisorAutoProxyCreator
    AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);
    //  Transaction advisor beanname
    String txAdvisorBeanName = "org.springframework.transaction.config.internalTransactionAdvisor";
    if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {
        //  register   AnnotationTransactionAttributeSource
        Object 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);
        //  register   TransactionInterceptor
        RootBeanDefinition 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);
        //  register   BeanFactoryTransactionAttributeSourceAdvisor
        RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);
        advisorDef.setSource(eleSource);
        advisorDef.setRole(2);
        //  And take the two beans registered above as the properties of the 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);
        //  Register other event notification components
    }
}

Three registered here   bean:

  • BeanFactoryTransactionAttributeSourceAdvisor

  • AnnotationTransactionAttributeSource

  • TransactionInterceptor

It is mainly used to execute the target method, transaction commit and rollback

The three bean relationships are as follows:

InfrastructureAdvisorAutoProxyCreator

What does this class mean? What's the use of it? According to the class name   basic   Advisor   The automatic agent creator does not need to be created for custom advisor. Its class diagram is as follows:

You can see that it's implemented   BeanPostProcessor   Interface, which was analyzed earlier   Spring   When you know the relevant source code, the interface is   Spring   It provides an extension interface with two methods:

public interface BeanPostProcessor {
    //  bean   Execute before initialization
    default Object postProcessBeforeInitialization(Object bean, String beanName){
        return bean;
    }
    //  bean   Execute after initialization
    default Object postProcessAfterInitialization(Object bean, String beanName) {
        return bean;
    }
}

So when we define a   bean   After the initialization is completed, it will be executed   postProcessAfterInitialization   Method, and   InfrastructureAdvisorAutoProxyCreator   Class implements the method:

public Object postProcessAfterInitialization(Object bean, String beanName) {
    if (bean != null) {
        //  according to   beanClassName   and   beanName   Create a key
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        if (!this.earlyProxyReferences.contains(cacheKey)) {
            //  packing   bean
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}

//  Wrapper bean
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    //  It has been processed and returned directly
    if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
        return bean;
    }
    //  Should   The bean does not need to be enhanced and returns directly
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
        return bean;
    }
    //  Is it Advice.class,   Pointcut.class,   Advisor.class,   AopInfrastructureBean.class   These categories, if yes
    //  These classes, or those that the bean needs to skip, are returned directly
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }
    //  If there are enhancements, create a proxy
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    if (specificInterceptors != DO_NOT_PROXY) {
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
        //  Create proxy
        Object proxy = createProxy(
                bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
        this.proxyTypes.put(cacheKey, proxy.getClass());
        //  Return agent
        return proxy;
    }
    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
}

//  Create proxy
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   agent
            proxyFactory.setProxyTargetClass(true);
        }
        else {
            //  JDK interface proxy
            evaluateProxyInterfaces(beanClass, proxyFactory);
        }
    }
    //  Create proxy
    return proxyFactory.getProxy(getProxyClassLoader());
}

//  Really create proxy
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 {
    //  judge   CGLIB   Agency and   JDK   Conditions of agency
    if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
        Class<?> targetClass = config.getTargetClass();
        //  JDK   agent
        if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
            return new JdkDynamicAopProxy(config);
        }
        //  CGLIB   agent
        return new ObjenesisCglibAopProxy(config);
    }
    else {
        //  JDK   agent
        return new JdkDynamicAopProxy(config);
    }
}

The above code, when we   bean   After initialization, the   bean   Create an agent. When creating an agent, create a JDK dynamic agent or   CGLIB agent

Spring proxy creation reference: source code analysis of Spring AOP proxy creation( https://my.oschina.net/mengyuankan/blog/2995754)

But is it all   bean   Will create an agent, no, in the packaging   bean   Method of   wrapIfNecessary   In, I will find the   bean   Corresponding enhancement. If there is a corresponding enhancement, the agent will be created. Therefore, before creating the agent, the agent will be found first   Bean corresponding enhancement (interceptor), in   wrapIfNecessary   The code is in the method:

Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);

about   For Spring transactions, this method returns   specificInterceptors   It cannot be empty, so we will follow the logic of creating an agent later.
Next, let's look at the implementation process of this method, that is, query the enhancer corresponding to class or method.

Query the enhancer of the corresponding class or method

stay   In the getAdvicesAndAdvisorsForBean method, the first step is to find the qualified enhancer, and the second step is to judge whether the enhancer meets the requirements.

protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName,TargetSource targetSource) {
    //  according to   className   and   beanName   Find the qualified intensifier
    List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
    if (advisors.isEmpty()) {
        return DO_NOT_PROXY;
    }
    return advisors.toArray();
}

//  Find the intensifier
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    //Find intensifier
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    //Judge whether the intensifier meets the conditions
    List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
    //.......
    return eligibleAdvisors;
}

Find enhancer findcandidate Advisors

protected List<Advisor> findCandidateAdvisors() {
    return this.advisorRetrievalHelper.findAdvisorBeans();
}

public List<Advisor> findAdvisorBeans() {
    String[] advisorNames = this.cachedAdvisorBeanNames;
    if (advisorNames == null) {
        //  Get all   Advisor.class   class  
        //  Previously registered   bean: BeanFactoryTransactionAttributeSourceAdvisor   Also a   Advisor,
        //  So, here we should   bean   Will be extracted and subsequently implanted into the agent
        advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Advisor.class, true, false);
        this.cachedAdvisorBeanNames = advisorNames;
    }
    List<Advisor> advisors = new ArrayList<>();
    for (String name : advisorNames) {
       //  Judge whether the enhancer bean meets the conditions, and return true here  
       if (isEligibleBean(name)) {
         if (this.beanFactory.isCurrentlyInCreation(name)) {
            //Skip intensifier being created
         }
         else {
            advisors.add(this.beanFactory.getBean(name, Advisor.class));
          }
       }
    }
    return advisors;
}

Finding all the intensifiers is finding   Advisor.class   Class,
To illustrate, the bean registered earlier   BeanFactoryTransactionAttributeSourceAdvisor, which is also a   Advisor, so getting all   Advisor.class   Class, the   bean   Extracted; In addition, the   Beans also have   AnnotationTransactionAttributeSource and   TransactionInterceptor   These two beans will be woven into the proxy together.

After finding all the enhancements, we need to determine which enhancements meet our goals   bean, corresponding method   Findadvisors that can apply, the criterion is very simple, that is, go to the method of the target class to find out whether there are transaction annotations  @ Transactional. If it exists, it is satisfied.

public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
    //  Used to store qualified enhancements
    List<Advisor> eligibleAdvisors = new ArrayList<>();
    //  Processing referral enhancement
    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) {
            //  It has been processed when processing the introduction enhancement
            continue;
        }
        //  Ordinary bean
        if (canApply(candidate, clazz, hasIntroductions)) {
            eligibleAdvisors.add(candidate);
        }
    }
    return eligibleAdvisors;
}

Here, if the intensifier meets our goal   bean, it will return enhancement, and then the target   bean creates a proxy and weaves the enhancement into the proxy.

Judge whether it is satisfied and use   canApply method

Resolve @ Transactional

canApply   The method is as follows:

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=BeanFactoryTransactionAttributeSourceAdvisor
        PointcutAdvisor pca = (PointcutAdvisor) advisor;
        //pca.getPointcut()=TransactionAttributeSourcePointcut
        return canApply(pca.getPointcut(), targetClass, hasIntroductions);
    }
    else {
        return true;
    }
}

For a transaction   bean   In general, this enhancement   Advisor   It was registered earlier   BeanFactoryTransactionAttributeSourceAdvisor, which   bean   Realized   PointcutAdvisor   Interface, so it will pass through the second   if   Judgment; After passing   getPointcut   obtain   TransactionAttributeSourcePointcut   Object to continue calling overloaded   canApply   The method is as follows:

public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
    //  Get method matcher
    //  The matcher at this time is   TransactionAttributeSourcePointcut
    MethodMatcher methodMatcher = pc.getMethodMatcher();
    //  If all methods can be matched, the circular method will not be judged
    if (methodMatcher == MethodMatcher.TRUE) {
        return true;
    }
    //  Store the target class and all interfaces of the target class
    Set<Class<?>> classes = new LinkedHashSet<>();
    if (!Proxy.isProxyClass(targetClass)) {
        classes.add(ClassUtils.getUserClass(targetClass));
    }
    classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
    //  Traverse the methods under the target class and all interfaces of the target class,
    //  If any method can meet the requirements of the enhancer, that is, it has @ Transactional annotation, it will be returned directly
    for (Class<?> clazz : classes) {
      Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
      for (Method method : methods) {
        if (introductionAwareMethodMatcher != null ? 
          introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
          //  Whether the matching method meets the conditions
           methodMatcher.matches(method, targetClass)) {
        return true;
        }
      }
    }
    return false;

Here, you can only judge whether it conforms to the enhancer according to the method, but not according to the class and interface, because the transaction annotation  @ Transactional   It can be placed on a class or interface, and all   The public method is useful; In fact, the judgment condition for classes and interfaces is the matcher   Method, the use of the call   TransactionAttributeSourcePointcut   of   mathcer   The method is as follows:

public boolean matches(Method method, Class<?> targetClass) {
    // .....
    TransactionAttributeSource tas = getTransactionAttributeSource();
    return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}

Here, it is determined whether the conditions are met, that is, whether the corresponding method has  @ Transactional   Notes.
there   tas   namely   Annotation transaction attribute source, that is, the three registered at the beginning of the article   bean   One of its   getTransactionAttribute   Get the transaction attribute as follows:

public TransactionAttribute getTransactionAttribute(Method method, Class<?> targetClass) {
    //  ignore   Object   Method of
    if (method.getDeclaringClass() == Object.class) {
        return null;
    }
    //  Create a key based on method and class
    Object cacheKey = getCacheKey(method, targetClass);
    //  Query transactions according to the key,
    TransactionAttribute cached = this.attributeCache.get(cacheKey);
    if (cached != null) {
       //...
       //  Already judged
       return cached;
    }
    else {
       TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
       //....
       return txAttr;
    }
}

computeTransactionAttribute   The method is as follows:

protected TransactionAttribute computeTransactionAttribute(Method method, Class<?> targetClass) {
    //  If it is not a public method, skip
    if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
        return null;
    }
    //  Methods of implementing classes
    Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);

    //  First, query the annotation on the method of the implementation class. If it is found, it will be returned directly
    TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
    if (txAttr != null) {
        return txAttr;
    }

    //  If the annotation cannot be found on the corresponding method of the implementation class, find the annotation on the implementation class of the method and return it directly
    txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
    if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
        return txAttr;
    }
    //  Existing interface
    if (specificMethod != method) {
        //  Find the annotation on the interface method and return it directly
        txAttr = findTransactionAttribute(method);
        if (txAttr != null) {
            return txAttr;
        }
        //  If the annotation cannot be found on the interface method, look for the annotation on the interface
        txAttr = findTransactionAttribute(method.getDeclaringClass());
        if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
            return txAttr;
        }
    }
    return null;
}

In the above computeTransactionAttribute method, you can see that to find is an annotation on a transaction method. First, find it on the method of the implementation class and return it directly. If it is not found, find the annotation on the implementation class; If the implementation class cannot be found, go to the method on the interface. If the interface method cannot be found, go to the interface again; Therefore, it can be seen here that the transaction annotation placed on the class or interface can act on all public methods under it, and the transaction annotation on the method should take precedence over the annotation on the class or interface, that is, if the transaction annotation is added to the class, interface and method, the annotation on the method will prevail, followed by the class and finally the interface.

After that, the annotation attribute is parsed. The corresponding method is: findTransactionAttribute:

protected TransactionAttribute findTransactionAttribute(Method method) {
    return determineTransactionAttribute(method);
}
protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
    //  Transaction annotation parser
    for (TransactionAnnotationParser annotationParser : this.annotationParsers) {
        TransactionAttribute attr = annotationParser.parseTransactionAnnotation(element);
        if (attr != null) {
            return attr;
        }
    }
    return null;
}

//  Get on method   Transactional   annotation
public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
    //  Get on method   Transactional   annotation
    AnnotationAttributes attributes =
        AnnotatedElementUtils.findMergedAnnotationAttributes(element, Transactional.class, false, false);
    if (attributes != null) {
        //  analysis   Transactional   Annotation Properties 
        return parseTransactionAnnotation(attributes);
    }
    else {
        return null;
    }
}

//  analysis   Transactional   Annotation Properties 
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<RollbackRuleAttribute> 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;
}

You can see the transaction annotation here  @ Transactional   Various properties of.

Of course, it's not over yet; Here, you can look at all the code from bottom to top when the method exists  @ This method will satisfy the enhancer when the Transactional annotation is used   BeanFactoryTransactionAttributeSourceAdvisor  , Then it will be our goal   bean   Create agents and add enhancers   BeanFactoryTransactionAttributeSourceAdvisor   Woven into the agent, which in turn affects our business logic.

summary

This article mainly introduces   Spring   Transaction initialization function, in   Spring   When loading, it will register   InfrastructureAdvisorAutoProxyCreator   Bean, and the   bean   Again   BeanPostProcessor   Interface, so when the initialization of the target bean is completed, it will execute   postProcessAfterInitialization   Method, in which we will traverse our target   bean   Method in, if there is  @ Transactional transaction annotation, it will be the target   bean   Create agents and add enhancers   BeanFactoryTransactionAttributeSourceAdvisor   Weaving into the agent; Of course, beanfactorytransactionattributesourceadvisor    Also have   AnnotationTransactionAttributeSource   and   TransactionInterceptor   these two items.   bean   Will be woven into the agent together.

So in   In the process of Spring transaction initialization, four main transactions are registered   bean:

  • InfrastructureAdvisorAutoProxyCreator

  • BeanFactoryTransactionAttributeSourceAdvisor

  • AnnotationTransactionAttributeSource

  • `TransactionInterceptor`

InfrastructureAdvisorAutoProxyCreator   It is mainly used to find transaction annotations on methods, classes or interfaces  @ Transactional, target if annotation exists   bean   Create the agent and put the other three   bean   Woven into the agent, while the other three   bean   It is mainly used to execute the target method and commit and rollback transactions.

BeanFactoryTransactionAttributeSourceAdvisor

About using   BeanFactoryTransactionAttributeSourceAdvisor,AnnotationTransactionAttributeSource,TransactionInterceptor    To execute the target method, commit the transaction and roll back the transaction, which will be analyzed in the next article.

Posted by paulsbooker on Wed, 20 Oct 2021 23:02:15 -0700