Spring transaction configuration research-Alibaba Cloud Developer Community

generally, we use the datasource. The following configuration is implemented in xml, but the principle and purpose of each configuration item are not so clear. If not clear, it is likely to encounter problems in use, so we will explain these configuration items one by one.

(1)配置数据源
 <bean id="dataSourace" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
        <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
        <property name="url" value="${db_url}" />
        <property name="username" value="$db_user}" />
        <property name="password" value="${db_passwd}" />
        <property name="maxWait" value="${db_maxWait}" />
        <property name="maxActive" value="28" /> 
        <property name="initialSize" value="2" />
        <property name="minIdle" value="0" />
        <property name="timeBetweenEvictionRunsMillis" value="db_time" />
    </bean>

(2)创建sqlSessionFactory
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="mapperLocations" value="classpath*:com/**/mapper/*Mapper*.xml" /> 
        <property name="dataSource" ref="dataSource" />
        <property name="typeAliasesPackage" value="com.test.***.dal" />
</bean>
    
(3)配置扫描器,扫描指定路径的mapper生成数据库操作代理类
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="annotationClass" value="javax.annotation.Resource"></property>
        <property name="basePackage" value="com.test.***.dal.***.mapper" />
        <property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>

(4)配置事务管理器
<bean id="transactionManager"
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>

(5)声明使用注解式事务
<tx:annotation-driven transaction-manager="transactionManager" />
(6)注册各种beanfactory处理器
<context:annotation-config />    

(7)该配置创建了一个TransactionInterceptor的bean,作为事务切面的执行方法
 <tx:advice id="defaultTxAdvice">
    <tx:attributes>
        <tx:method name="*" rollback-for="Exception" />
    </tx:attributes>
</tx:advice>

(8)该配置创建了一个DefaultBeanFactoryPointcutAdvisor的bean,该bean是一个advisor,里面包含了pointcut和advice.前者说明切面加在哪里,后者是执行逻辑。此处可以配多个advisor
<aop:config>
    <aop:pointcut id="myCut" expression="(execution(* *..*BoImpl.*(..))) "/>
    <aop:advisor pointcut-ref="myCut" advice-ref="defaultTxAdvice" />
</aop:config>

1.1 Data Source configuration

(1) it is the data source configuration, there is nothing to say.

1.2 configuration SqlSessionFactory

(2) the function is to create a SqlSessionFactory according to the configuration, and look at the code SqlSessionFactoryBean to know that it implements FactoryBean and InitializingBean classes. Because it implements InitializingBean, it naturally afterPropertiesSet methods, because FactoryBean classes are implemented, getObject methods are naturally available. The following figure shows the sequence diagram: it can be seen from the sequence diagram that the SqlSessionFactoryBean class creates SqlSessionFactory instances through attribute configuration. Specifically, it parses all mapper files in the configuration and puts them into configuration, and then instantiates a DefaultSqlSessionFactory as a SqlSessionFactory as a constructor parameter.

1.3 configure the scanner to scan the mapper in the specified path to generate the database operation proxy class

MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, and BeanNameAware interfaces, the following method is rewritten:

1.3.1
//在bean注册到ioc后创建实例前修改bean定义和新增bean注册,这个是在context的refresh方法调用
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
1.3.2
//在bean注册到ioc后创建实例前修改bean定义或者属性值
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
1.3.3
//set属性设置后调用
void afterPropertiesSet() throws Exception;
1.3.4
//获取IOC容器上下文,在context的prepareBeanFactory中调用
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
1.3.5
//获取bean在ioc容器中名字,在context的prepareBeanFactory中调用
void setBeanName(String name);

first scan the mapper to generate the proxy class and register it with the ioc sequence diagram: first, MapperScannerConfigurer afterPropertiesSet method to ensure that the attribute basePackage is not empty.

public void afterPropertiesSet() throws Exception {
    notNull(this.basePackage, "Property 'basePackage' is required");
  }

Nothing is done in the postProcessBeanFactory, setBeanName the bean name is obtained, and the ioc context is obtained in the setApplicationContext. The following is an important method postProcessBeanDefinitionRegistry. mybais generates a proxy class by parsing the mapper file and injects it into the ioc at runtime, so postProcessBeanDefinitionRegistry can just do this.

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
    if (this.processPropertyPlaceHolders) {
      processPropertyPlaceHolders();
    }

    //构造一个ClassPathMapperScanner查找mapper
    ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
    scanner.setAddToConfig(this.addToConfig);
    //javax.annotation.Resource
    scanner.setAnnotationClass(this.annotationClass);
    scanner.setMarkerInterface(this.markerInterface);
    //引用sqlSessionFactory
    scanner.setSqlSessionFactory(this.sqlSessionFactory);
    scanner.setSqlSessionTemplate(this.sqlSessionTemplate);
    scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName);
    scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName);
    //ioc上下文
    scanner.setResourceLoader(this.applicationContext);
    scanner.setBeanNameGenerator(this.nameGenerator);
    scanner.registerFilters();
   //basePackage=com.alibaba.***.dal.***.mapper,com.alibaba.rock.auth.mapper,com.alibaba.rock.workflow.dal.workflow.mapper
    scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS));
  }

The following focuses on the scan method:

 public Set<BeanDefinitionHolder> doScan(String... basePackages) {
    //根据指定路径去查找对应mapper的接口类,并转化为beandefination
    Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);

    if (beanDefinitions.isEmpty()) {
      logger.warn("No MyBatis mapper was found in '" + Arrays.toString(basePackages) + "' package. Please check your configuration.");
    } else {
      //修改接口类bean的beandefination
      processBeanDefinitions(beanDefinitions);
    }

    return beanDefinitions;
  }

super.doScan(basePackages); Searches for The mapper interface class according to the specified path, generates the bean definition object, which contains the beanclassname and beanclass attributes, and finally registers the bean to the ioc container. Let's take a look at the most important processBeanDefinitions method to modify the bean definition.

 private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {
    GenericBeanDefinition definition;
    for (BeanDefinitionHolder holder : beanDefinitions) {
      definition = (GenericBeanDefinition) holder.getBeanDefinition();

      // 上面讲的扫描后beanclass设置的为mapper接口类,但是这里修改为MapperFactoryBean,MapperFactoryBean代理了mapper接口类,并且实际mapper接口类作为构造函数传入了      definition.getConstructorArgumentValues().addGenericArgumentValue(definition.getBeanClassName()); 
      definition.setBeanClass(this.mapperFactoryBean.getClass());
      definition.getPropertyValues().add("addToConfig", this.addToConfig);

      //设置属性配置中的sqlSessionFactory
      boolean explicitFactoryUsed = false;
      if (StringUtils.hasText(this.sqlSessionFactoryBeanName)) {
        definition.getPropertyValues().add("sqlSessionFactory", new RuntimeBeanReference(this.sqlSessionFactoryBeanName));
        explicitFactoryUsed = true;
      } else if (this.sqlSessionFactory != null) {
        definition.getPropertyValues().add("sqlSessionFactory", this.sqlSessionFactory);
        explicitFactoryUsed = true;
      }

      if (StringUtils.hasText(this.sqlSessionTemplateBeanName)) {
        if (explicitFactoryUsed) {
          logger.warn("Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored.");
        }
        definition.getPropertyValues().add("sqlSessionTemplate", new RuntimeBeanReference(this.sqlSessionTemplateBeanName));
        explicitFactoryUsed = true;
      } else if (this.sqlSessionTemplate != null) {
        if (explicitFactoryUsed) {
          logger.warn("Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored.");
        }
        definition.getPropertyValues().add("sqlSessionTemplate", this.sqlSessionTemplate);
        explicitFactoryUsed = true;
      }

      if (!explicitFactoryUsed) {
        if (logger.isDebugEnabled()) {
          logger.debug("Enabling autowire by type for MapperFactoryBean with name '" + holder.getBeanName() + "'.");
        }
        definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
      }
    }
  }

Note: In this example, beanclass in beandefination of The mapper interface class is changed to MapperFactoryBean, which is responsible for the production data Class operation proxy class. The actual mapper interface class is passed in as a constructor. Because only beanclass is modified, but beanname is not modified, we do not perceive it when obtaining it from the container.

How to construct the sequence diagram of the previous proxy bean: let's take a look at how the MapperFactoryBean generates the proxy class. First, the preceding code sets the MapperFactoryBean setSqlSessionFactory method:

  public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
    if (!this.externalSqlSession) {
      this.sqlSession = new SqlSessionTemplate(sqlSessionFactory);
    }
  }

the preceding method creates a sqlSession. Because the MapperFactoryBean is a factory bean, the getObject method is called during instantiation:

 public T getObject() throws Exception {
    return getSqlSession().getMapper(this.mapperInterface);
  }

In fact, the SqlSessionTemplate-&gt;getMapper is called, where mapperInterface is the constructor parameter when creating MapperFactoryBean.


public <T> T getMapper(Class<T> type) {
    return getConfiguration().getMapper(type, this);
  }

getConfiguration().getMapper(type, this) is called here. this is actually the DefaultSqlSessionFactory method of configration in the getMapper:

public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
   //knownMappers是上面时序图中步骤6设置进入的。
    final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
    if (mapperProxyFactory == null) {
      throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
    }
    try {
      return mapperProxyFactory.newInstance(sqlSession);
    } catch (Exception e) {
      throw new BindingException("Error getting mapper instance. Cause: " + e, e);
    }
  }
 protected T newInstance(MapperProxy<T> mapperProxy) {
    return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
  }

  public T newInstance(SqlSession sqlSession) {
   //代理回调类为MapperProxy
    final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
    return newInstance(mapperProxy);
  }

the sequence diagram of calling the proxy class during the last SQL execution: therefore, when the actual database operation is called, The invoke method of the MapperProxy is called:

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    if (Object.class.equals(method.getDeclaringClass())) {
      try {
        return method.invoke(this, args);
      } catch (Throwable t) {
        throw ExceptionUtil.unwrapThrowable(t);
      }
    }
    final MapperMethod mapperMethod = cachedMapperMethod(method);
    return mapperMethod.execute(sqlSession, args);
  }

mapperMethod.execute(sqlSession, args); It actually calls the database operation of the SqlSessionTemplate corresponding to the current mapper, and it is delegated to the proxy class sqlSessionProxy,sqlSessionProxy is created in the constructor of the SqlSessionTemplate:

public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType,
      PersistenceExceptionTranslator exceptionTranslator) {

    notNull(sqlSessionFactory, "Property 'sqlSessionFactory' is required");
    notNull(executorType, "Property 'executorType' is required");

    this.sqlSessionFactory = sqlSessionFactory;
    this.executorType = executorType;
    this.exceptionTranslator = exceptionTranslator;
    this.sqlSessionProxy = (SqlSession) newProxyInstance(
        SqlSessionFactory.class.getClassLoader(),
        new Class[] { SqlSession.class },
        new SqlSessionInterceptor());
  }

therefore, the final database operation is performed by the proxy SqlSessionInterceptor:

 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      //有TransactionSynchronizationManager管理
      SqlSession sqlSession = getSqlSession(
          SqlSessionTemplate.this.sqlSessionFactory,
          SqlSessionTemplate.this.executorType,
          SqlSessionTemplate.this.exceptionTranslator);
      try {
        Object result = method.invoke(sqlSession, args);
        if (!isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) {
          // force commit even on non-dirty sessions because some databases require
          // a commit/rollback before calling close()
          sqlSession.commit(true);
        }
        return result;
      } catch (Throwable t) {
          .....
      }
    }

public static SqlSession getSqlSession(SqlSessionFactory sessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) {

    notNull(sessionFactory, NO_SQL_SESSION_FACTORY_SPECIFIED);
    notNull(executorType, NO_EXECUTOR_TYPE_SPECIFIED);

    SqlSessionHolder holder = (SqlSessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);

    SqlSession session = sessionHolder(executorType, holder);
    if (session != null) {
      return session;
    }

    if (LOGGER.isDebugEnabled()) {
      LOGGER.debug("Creating a new SqlSession");
    }
   //这里看到了使用sessionfactory熟悉的打开了一个session
    session = sessionFactory.openSession(executorType);

    registerSessionHolder(sessionFactory, executorType, exceptionTranslator, session);

    return session;
  }

note: the scan file configured in 3 must be included in the scan file of 4, because 3 generates a proxy for each scan File. If an mapper is added to 4, then it cannot be found in 4.

1.4 configure transaction manager

the transaction manager is used to manage transactions.

1.5 advice configuration

Creates a TransactionInterceptor bean as the execution method of the transaction section. Tag resolution flowchart: because it is a tx tag, you must search for TxNamespaceHandler. The code is as follows:

public class TxNamespaceHandler extends NamespaceHandlerSupport {

    static final String TRANSACTION_MANAGER_ATTRIBUTE = "transaction-manager";
    static final String DEFAULT_TRANSACTION_MANAGER_BEAN_NAME = "transactionManager";

    static String getTransactionManagerName(Element element) {
        return (element.hasAttribute(TRANSACTION_MANAGER_ATTRIBUTE) ?
                element.getAttribute(TRANSACTION_MANAGER_ATTRIBUTE) : DEFAULT_TRANSACTION_MANAGER_BEAN_NAME);
    }

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

}

from the init method, we know that the advice tag needs to TxAdviceBeanDefinitionParser the parsing class. The reference of the transaction manager is set in the first step of the flowchart. Let's take a look at the name of the referenced bean:

static final String DEFAULT_TRANSACTION_MANAGER_BEAN_NAME = "transactionManager";

static String getTransactionManagerName(Element element) {
        return (element.hasAttribute(TRANSACTION_MANAGER_ATTRIBUTE) ?
                element.getAttribute(TRANSACTION_MANAGER_ATTRIBUTE) : DEFAULT_TRANSACTION_MANAGER_BEAN_NAME);
    }

you can see that if this attribute is not configured, the default search dependency beanname = transactionManager. Then, parseAttributeSource the main loop to parse the method tag we configured and the transaction attributes of the set method. Additional code:


protected Class<?> getBeanClass(Element element) {
        return TransactionInterceptor.class;
    }

you can see that the advice tag actually creates TransactionInterceptor object, and sets the transaction manager by calling the setTransactionManager, and sets the transaction properties by setTransactionAttributeSources.

1.6 settings advisor

A tag creates a DefaultBeanFactoryPointcutAdvisor as an interceptor, and uses a transactional interceptor to block the bean that meets the tangent point as a proxy. For more information about the tag logic, see the flowchart: from the tag, we can find AopNamespaceHandler. The code is as follows:

public class AopNamespaceHandler extends NamespaceHandlerSupport {

    @Override
    public void init() {
        registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
        registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
        registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());

        registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
    }
}

we can see that the config tag is parsed by ConfigBeanDefinitionParser. According to the flowchart, we can know that configureAutoProxyCreator has registered the AspectJAwareAdvisorAutoProxyCreator class, and then createAdvisorBeanDefinition has created a DefaultBeanFactoryPointcutAdvisor, which is an advisor, and the settings reference advice, this adivce is explained in the preceding 1.5, then the createPointcutDefinition creates a tangent point AspectJExpressionPointcut, and finally sets the tangent point to advisor. DefaultBeanFactoryPointcutAdvisor acts as a proxy for the methods of classes that meet the pointcut expression, and uses advice for interception. advice is the transaction interceptor.

1.7 set annotation transactions

after the above introduction, you can use the transaction section, but sometimes you need to annotate the row transaction on a specific class or method, then you need to add the configuration to the sequence diagram first: ! Similarly, 1.6 The difference is that advisor is created and advice (transaction interceptor) is set here, but pointcut is not set. Check BeanFactoryTransactionAttributeSourceAdvisor source code:


public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {

    private TransactionAttributeSource transactionAttributeSource;

    private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
        @Override
        protected TransactionAttributeSource getTransactionAttributeSource() {
            return transactionAttributeSource;
        }
    };
}

pointcut is directly built in, except that 1.6 is the tangent point of the AspectJExpressionPointcut expression. Here is the annotation. When is this BeanFactoryTransactionAttributeSourceAdvisor used to enhance the class of annotation transactions? That is what InfrastructureAdvisorAutoProxyCreator do. InfrastructureAdvisorAutoProxyCreator is a BeanPostProcessor that calls the postProcessAfterInitialization after the bean is created and initialized. This is the method.

Note that if multiple annotation tags are configured, only the first tag takes effect in datasource.xml.


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

            String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;
            //如果配置了多个注解式标签在datasource.xml里面时候只有第一个生效
            if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {
                Object eleSource = parserContext.extractSource(element);

                // Create the TransactionAttributeSource definition.
                RootBeanDefinition sourceDef = new RootBeanDefinition(
                        "org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");
                sourceDef.setSource(eleSource);
                sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
                String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);

                // Create the TransactionInterceptor definition.
                RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);
                interceptorDef.setSource(eleSource);
                interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
                registerTransactionManager(element, interceptorDef);
                interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
                String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);

                // Create the TransactionAttributeSourceAdvisor definition.
                RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);
                advisorDef.setSource(eleSource);
                advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
                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);

                CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);
                compositeDef.addNestedComponent(new BeanComponentDefinition(sourceDef, sourceName));
                compositeDef.addNestedComponent(new BeanComponentDefinition(interceptorDef, interceptorName));
                compositeDef.addNestedComponent(new BeanComponentDefinition(advisorDef, txAdvisorBeanName));
                parserContext.registerComponent(compositeDef);
            }
        }

1.8 register various beanfactory processors

<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor "/>


<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/>

with tags, we can automatically register these commonly used beanfactory processors at the same time, avoiding the tedious steps of configuring one by one:


public class ContextNamespaceHandler extends NamespaceHandlerSupport {

                ...
        registerJava5DependentParser("annotation-config",
                "org.springframework.context.annotation.AnnotationConfigBeanDefinitionParser");
        ....
}

public class AnnotationConfigBeanDefinitionParser implements BeanDefinitionParser {

    public BeanDefinition parse(Element element, ParserContext parserContext) {
                ...
        // Obtain bean definitions for all relevant BeanPostProcessors.
        Set<BeanDefinitionHolder> processorDefinitions =
                AnnotationConfigUtils.registerAnnotationConfigProcessors(parserContext.getRegistry(), source);

        // Register component for the surrounding <context:annotation-config> element.
        CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), source);
        parserContext.pushContainingComponent(compDefinition);

        // Nest the concrete beans in the surrounding component.
        for (BeanDefinitionHolder processorDefinition : processorDefinitions) {
            parserContext.registerComponent(new BeanComponentDefinition(processorDefinition));
        }

        // Finally register the composite component.
        parserContext.popAndRegisterContainingComponent();

        return null;
    }

}


public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
            BeanDefinitionRegistry registry, Object source) {

        Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>(4);

        // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
        if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition();
            try {
                ClassLoader cl = AnnotationConfigUtils.class.getClassLoader();
                def.setBeanClass(cl.loadClass(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME));
            }
            catch (ClassNotFoundException ex) {
                throw new IllegalStateException(
                        "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
            }
            def.setSource(source);
            def.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
            beanDefinitions.add(registerBeanPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

        // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
        if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
            def.setSource(source);
            def.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
            beanDefinitions.add(registerBeanPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

        if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
            def.setSource(source);
            def.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
            beanDefinitions.add(registerBeanPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

        if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
            def.setSource(source);
            def.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
            beanDefinitions.add(registerBeanPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

        return beanDefinitions;
    }

main registered commonly used: RequiredAnnotationBeanPostProcessorAutowiredAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessor usually we use autowired or required the reason to take effect, is because this automatic injection ioc already.

welcome to pay attention to WeChat public account: Original technology accumulation to obtain more technical dry goods

Selected, One-Stop Store for Enterprise Applications
Support various scenarios to meet companies' needs at different stages of development

Start Building Today with a Free Trial to 50+ Products

Learn and experience the power of Alibaba Cloud.

Sign Up Now