spring整合mybatis核心原理

在我常使用mybatis中,会经常使用@MapperScan注解下面我们来看看它是如何整合进到spring的,首先我们进入MapperScan会看到@Import(MapperScannerRegistrar.class)

spring整合mybatis核心原理_第1张图片

 我们打开MapperScannerRegistrar会看到实现了ImportBeanDefinitionRegistrar接口,这个接口会在spring加载启动解析import注解的时候调用实现ImportBeanDefinitionRegistrar接口的registerBeanDefinitions方法spring整合mybatis核心原理_第2张图片

打开registerBeanDefinitions方法就会看到将MapperScannerConfigurer.class生成了beanefinitionBuilder

spring整合mybatis核心原理_第3张图片

 spring整合mybatis核心原理_第4张图片

从上图我们可以看到,直接将MapperScannerConfigurer注册成了beanDefinitionBuilder,而MapperScannerConfigurer.class到底有什么作用呢?我们进这个类里面去看看他究竟做了什么事情spring整合mybatis核心原理_第5张图片

如果你对spring有了解过的话那么 BeanDefinitionRegistryPostProcessor,InitializingBean,ApplicationContextAware,BeanNameAware这几个类应该都很眼熟吧,在spring加载过程中扫描加载bean定义的时候调用实现了BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry方法spring整合mybatis核心原理_第6张图片

 新建了一个ClassPathMapperScanner类并将BeanDefinitionRegistry注册器作为构造参数传入然后调用了scan方法扫描指定包的mapper接口类,我们进入scan方法中的dosan()注意进入dosan方法要进入mybatis-spring包下面的那个方法,进入doScan方法的时候要注意,mybatis重写了ClassPathBeanDefinitionScanner的doScan方法,所以进入的应该是第二张图片的方法

spring整合mybatis核心原理_第7张图片

 spring整合mybatis核心原理_第8张图片

上图中的标注1中调用父类的spring方法扫描出mapper接口的beanDefinition集合,然后再由标注2的方法进行偷天换日,将扫描出来的beanDefinition包装成factoryBean,然后在实例化bean的时候会调用factoryBean的getObject方法,在getObject方法中进行增强,也就是创建动态代理

 spring整合mybatis核心原理_第9张图片

 进入definition.setBeanClass(this.mapperFactoryBeanClass)代码片段的参数mapperFactoryBeanClass看一下这个工厂bean

public class MapperFactoryBean extends SqlSessionDaoSupport implements FactoryBean {//此类实现了factoryBean接口

  private Class mapperInterface;//存放实际mapper接口的参数

  private boolean addToConfig = true;

  public MapperFactoryBean() {
    // intentionally empty
  }

  public MapperFactoryBean(Class mapperInterface) {//在spring后续的getbean中将通过这个方法进行参数注入
    this.mapperInterface = mapperInterface;
  }

 下面我们找到factoryBean的getObject方法

  @Override
  public T getObject() throws Exception {
    return getSqlSession().getMapper(this.mapperInterface);//从这里跟进去就可以找到生成JDK动态代理的方法了
  }

 最终会调用到如下的代码去生成动态代理类

@Override
    public  T getMapper(Class type, SqlSession sqlSession) {
        // TODO 这里换成 MybatisMapperProxyFactory 而不是 MapperProxyFactory
        final MybatisMapperProxyFactory mapperProxyFactory = (MybatisMapperProxyFactory) knownMappers.get(type);
        if (mapperProxyFactory == null) {
            throw new BindingException("Type " + type + " is not known to the MybatisPlusMapperRegistry.");
        }
        try {
            return mapperProxyFactory.newInstance(sqlSession);//从这里进去就能看到生成动态代理的代码了,有兴趣的自己跟进去看一下就知道了
        } catch (Exception e) {
            throw new BindingException("Error getting mapper instance. Cause: " + e, e);
        }
    }

spring集成mybatis 的核心流程已经梳理完了,下面奉上一张流程图给大家参考 

 

 

 

 

 

你可能感兴趣的:(spring,java,开发语言,spring,mybatis)