mybatis mapper parsing (next) @mapperScan

reference

Depth analysis mybatis principle (c) how to integrate Spring
without his reference, I can not make this understanding.

@mapperScan registered MapperFactoryBean

7547741-c4cbb884d0f544a9.jpg
@MapperScan.jpg

MapperFactoryBean those registered (a FactoryBean) in the spring will call its initialization getObjectmethod to generate specific Bean. (About FactoryBean, refer to Spring Source learning --FactoryBean implementation principle )

MapperFactoryBean initialization

7547741-2231338b1fc40010.jpg
mapperFactory initialization .jpg

But after MapperFactoryBean instantiated, calling getObjectbefore, due MapperFactoryBean itself is a Bean, spring framework calls setSqlSessionFactory setSqlSessionTemplate and set its properties. So after getObjectuse.

// SqlSessionDaoSupport.java
// MapperFactoryBean继承了SqlSessionDaoSupport

// 设置sqlSessionFactory, 顺便自动设置sqlSessionTemplate。所以如果没设定sqlSessionTemplate也没关系。
public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
    if (this.sqlSessionTemplate == null || sqlSessionFactory != this.sqlSessionTemplate.getSqlSessionFactory()) {
      this.sqlSessionTemplate = createSqlSessionTemplate(sqlSessionFactory);
    }
}

// 可以手动设置
public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
    this.sqlSessionTemplate = sqlSessionTemplate;
}

After the getObjectmiddle:

  1. getSqlSessionI use sqlSessionTemplate just set.
  2. getMapper(this.mapperInterface)In -depth analysis of mybatis principle (b) have analyzed the
    , the method will eventually return Mapper proxy class object.
// MapperFactoryBean.java
  @Override
  public T getObject() throws Exception {
    return getSqlSession().getMapper(this.mapperInterface);
  }
// SqlSessionDaoSupport.java
  public SqlSession getSqlSession() {
    return this.sqlSessionTemplate;
  }

getObject call

You might ask, when will this MapperFactoryBean.getObject call it?
Remember when @mapperScan registered MapperFactoryBean ClassPathMapperScanner.processBeanDefinitionsway to do this:

  private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {
    GenericBeanDefinition definition;
    for (BeanDefinitionHolder holder : beanDefinitions) {
      definition = (GenericBeanDefinition) holder.getBeanDefinition();
      String beanClassName = definition.getBeanClassName();
      LOGGER.debug(() -> "Creating MapperFactoryBean with name '" + holder.getBeanName()
          + "' and '" + beanClassName + "' mapperInterface");

      // the mapper interface is the original class of the bean
      // but, the actual class of the bean is MapperFactoryBean
      definition.getConstructorArgumentValues().addGenericArgumentValue(beanClassName); // issue #59
      definition.setBeanClass(this.mapperFactoryBeanClass);
      // ...
      }
    }
  }

There are two purposes:

  1. Sign up here for the Bean name beanClassName is xx.xx.xxMapper, but the actual Bean is MapperFactoryBean.
    In the process of springboot initialization, we will call each Bean getBeanis instantiated, therefore MapperFactoryBean.getObject will be called.
  2. When the Service is initialized, spring will deal @Autowire in Mapper, depending on the type of name xx.xx.xxMapperto find Bean, then call beanFactory.getBean(beanName);. However, according to the name found it is actually just registered MapperFactoryBean. Because it is FactoryBean, calling them getBeanonly trigger getObject, thereby returning the proxy class object.
    To verify the effect @Autowired on Mapper, debug their own, may refer to later.

Mapper debugging @autowired injection

  1. In AutowiredAnnotationBeanPostProcessor.injectthe Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter);debugging break point.
  2. When the variable beanNamewhen the name contains the Mapper or the Service Controller, enter the method.
    Then follow into the result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);-> instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);->beanFactory.getBean(beanName); . Enter debugging. Familiar BeanFactory.getBean people should not have to debug know, the name of the corresponding Bean is MapperBeanFactory, is a BeanFactory, so in the end the method beanFactory.getBean(beanName);returns a return value of getObject of MapperFactoryBean. This analysis is just getObject use it!

to sum up

  1. @MapperScan scan the specified package, each Mapper, with its registered name is the actual type of Bean defined MapperFactoryBean.
  2. Bean With these definitions, when the spring is instantiated Bean, these MapperFactoryBean is instantiated, initialized, the corresponding method is also provided
  3. In dealing with @autowired marked Mapper, it will return the result of calling MapperFactoryBean.getObject, which is getSqlSession().getMapper(this.mapperInterface);the.
  4. Previous results will lead to @Autowired SomeMapper mapper;the injection of a class Mapper proxy, the proxy class will all database requests are handed over to the underlying operating SqlSession.
  5. The previous step, Mapper handed over to the sqlSession actually a SqlSessionTemplate, SqlSessionTemplate in turn hand over any database operations to sqlSessionProxy, while the latter is based on the proxy class SqlSessionInterceptor created.
    In other words, SqlSessionTemplate database operations will be intercepted SqlSessionInterceptor.invoke.
  6. Call SqlSessionInterceptor.invoke the getSqlSessionmethod is called internally when you need session = sessionFactory.openSession(executorType);to obtain a new session, it was in fact open a new connection.
    That SqlSessionTemplate database operations will be intercepted SqlSessionInterceptor.invoke, must obtain before each operation to SqlSession (the actual type is DefaultSqlSession), this SqlSession:
    • Either reuse existing (such as multiplexing current transaction used)
    • Either new.
      Therefore, a complete illustration of the above should read as follows:


      7547741-a30a0cacd5c8c1e5.jpg
      mybatis mapper principle .jpg

Guess you like

Origin blog.csdn.net/weixin_33781606/article/details/90976675