[spring] spring integration Mybatis source code analysis

Brief introduction to spring integration Mybatis

  • This article focuses on mybatis spring 1.3.2!
  • The core idea of integration: become the Bean of spring.
  • Implementation of integration: spring Based FactoryBean.

Mybatis spring 1.3.2 integration idea

  • Mappercannerregister class is imported through @ mappercan.
  • The mappercannerregister class implements the importbeandefinitionregister interface, so Spring will call the registerBeanDefinitions method in the mappercannerregister class at startup.
  • A classpathmappercanner object is defined in the registerBeanDefinitions method to scan mappers.
  • Setting the classpathmappercanner object can scan interfaces, because interfaces are not scanned by default in Spring.
  • At the same time, because the isCandidateComponent method is rewritten in ClassPathMapperScanner, isCandidateComponent will only consider the interface as the candidate Component. We can't scan all interfaces of @ Component.
  • After scanning with Spring, the interface will be scanned and the corresponding BeanDefinition will be obtained.
  • Modify the scanned BeanDefinition, change the BeanClass to MapperFactoryBean, and change the AutowireMode to byType (used to read the set method).
  • After scanning, Spring will create beans based on BeanDefinition, which is equivalent to one FactoryBean for each Mapper.
  • In the getObject method of MapperFactoryBean, getSqlSession() is called to get a sqlSession object, and then a Mapper interface proxy object is generated according to the corresponding Mapper interface. The proxy object becomes Bean in the Spring container.
  • sqlSession object is in Mybatis. A sqlSession object needs SqlSessionFactory to generate.
  • The AutowireMode of MapperFactoryBean is byType, so Spring will automatically call the set method. There are two set methods, one setSqlSessionFactory and one setSqlSessionTemplate. The premise of these two methods is to find the corresponding bean according to the method parameter type. Therefore, there should be a bean of SqlSessionFactory type or a bean of SqlSessionTemplate type in the Spring container.
  • If you define a bean of SqlSessionFactory type, it will eventually be wrapped as a SqlSessionTemplate object and assigned to the sqlSession attribute.
  • In the SqlSessionTemplate class, there is a getMapper method, which generates a Mapper interface proxy object.
  • Here, you have the proxy object of Mybatis and put it into the Bean of spring through FactoryBean.

Mybatis spring 2.0.6 integration idea

  • Mappercannerregister class is imported through @ mappercan.
  • The mappercannerregister class implements the importbeandefinitionregister interface, so Spring will call the registerBeanDefinitions method in the mappercannerregister class at startup.
  • Register a mappercannerconfigurer type BeanDefinition in the registerBeanDefinitions method.
  • Mappercannerconfigurer implements the BeanDefinitionRegistryPostProcessor interface, so Spring will call its postProcessBeanDefinitionRegistry() method during startup.
  • In the postProcessBeanDefinitionRegistry method, a classpathmappercanner object will be generated and then scanned
  • The remaining logic is the same as version 1.3.2.
// It can be injected through @ Bean
@Bean 
public MapperScannerConfigurer mapperScannerConfigurer() {
    erScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
    mapperScannerConfigurer.setBasePackage("com.zhangwei");
    return mapperScannerConfigurer; 
}

Source code analysis: @ MapperScan

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(MapperScannerRegistrar.class) // Mappercannerregister class imported
@Repeatable(MapperScans.class)
public @interface MapperScan {

  // Incoming package path to scan
  String[] value() default {};
    
  ......
}

Mappercannerregister source code analysis

public class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware {
    // spring starts the method that will be called
  public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

    // Get the annotation information of MapperScan
    AnnotationAttributes annoAttrs = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName()));
    ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);

    ......
    // MapperFactoryBean is used by default
    Class<? extends MapperFactoryBean> mapperFactoryBeanClass = annoAttrs.getClass("factoryBean");
    if (!MapperFactoryBean.class.equals(mapperFactoryBeanClass)) {
      scanner.setMapperFactoryBean(BeanUtils.instantiateClass(mapperFactoryBeanClass));
    }
    ......
        
    // Set that all scanned can become beans: IncludeFilter directly returns true
    scanner.registerFilters();
    // Scan. Definition will be set after scanning setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE); To ensure that the set method of MapperFactoryBean can be executed.
    // definition.getConstructorArgumentValues().addGenericArgumentValue(definition.getBeanClassName()); Use the construction method to specify a parameter!
    // definition.setBeanClass(this.mapperFactoryBean.getClass()); Set specific Beanclass
    scanner.doScan(StringUtils.toStringArray(basePackages));
  }
}

Let spring scan interfaces

public class ClassPathMapperScanner extends ClassPathBeanDefinitionScanner {
  // Re the method so that the interface can also become a Bean
  protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
    return beanDefinition.getMetadata().isInterface() && beanDefinition.getMetadata().isIndependent();
  }
}

MapperFactoryBean source code analysis

public class MapperFactoryBean<T> extends SqlSessionDaoSupport implements FactoryBean<T> {

  private Class<T> mapperInterface;

  private boolean addToConfig = true;

  public MapperFactoryBean() {
    //intentionally empty 
  }
  
  // The constructor passes in this parameter
  public MapperFactoryBean(Class<T> mapperInterface) {
    this.mapperInterface = mapperInterface;
  }

  ......

  /**
   * Bean The object of is sqlsession Getmapper to get the proxy object of Mybatis
   */
  @Override
  public T getObject() throws Exception {
    return getSqlSession().getMapper(this.mapperInterface);
  }

  /**
   * The returned type is the type passed in by the previous BeanDefinition
   */
  @Override
  public Class<T> getObjectType() {
    return this.mapperInterface;
  }

  ......
}

Source code analysis of SqlSessionDaoSupport inherited by MapperFactoryBean

/**
 * MapperFactoryBean The AutowireMode of is byType, so Spring will automatically call the set method. There are two set methods, one setSqlSessionFactory and one setSqlSessionTemplate. The premise of these two methods is to find the corresponding bean according to the method parameter type. Therefore, there should be a bean of SqlSessionFactory type or a bean of SqlSessionTemplate type in the Spring container.
 */
public abstract class SqlSessionDaoSupport extends DaoSupport {
  private SqlSession sqlSession;

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

  public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
    this.sqlSession = sqlSessionTemplate;
    this.externalSqlSession = true;
  }
  // Inject sqlSession dependency. The previous code was set to AUTOWIRE_BY_TYPE.
  public SqlSession getSqlSession() {
    return this.sqlSession;
  }
}   

Concluding remarks

  • Get more pre knowledge articles of this article and new valuable articles. Let's become architects together!
  • Paying attention to the official account enables you to have an in-depth understanding of MySQL, concurrent programming and spring source code.
  • Pay attention to the official account and follow the continuous and efficient learning of JVM!
  • This official account is not advertising!!! Update daily!!!

Keywords: Java Mybatis Spring Back-end

Added by Jordi_E on Sat, 05 Mar 2022 17:32:41 +0200