mapper实例构建阅读

Mybatis在spring中利用动态代理和bean生成的相关api生成mapper接口实例

根据springboot自动配置会去扫描spring.factory进行自动配置

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.mybatis.spring.boot.autoconfigure.MybatisLanguageDriverAutoConfiguration,\
org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration

所以在mybatis中会去扫描MybatisAutoConfiguration类并进行自动配置

@Bean
  @ConditionalOnMissingBean
  public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
    SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
    factory.setDataSource(dataSource);
    factory.setVfs(SpringBootVFS.class);
    //....构建factory
    applySqlSessionFactoryBeanCustomizers(factory);
    return factory.getObject();
  }

这个方法的作用是返回一个DefaultSqlsessionFactory用于构建defaultSqlsession的

根据jdk动态代理生成mapper类的代理 关键的之一是为每个mapper文件生成sqlsession

关于生成mapper的代理 ,mybatis有一个核心的工厂类MapperFactoryBean,下面看看他的继承结构:

7:16:7:{S}-png.16887174657821688717465230.png

MapperFactory实现了FactoryBean并且标注了他是一个bean对象,并且还实现了InitiallizingBean。实现了Factorybean这个接口的类

会实现getObject的方法:

:MapperFactoryBean的getObject方法

?这里就很奇怪了,getSqlSession方法是返回一个SqlSessionTemplate的成员变量,这个SqlSessionTemplate是怎么来的呢?

答案:

因为实现了FactoryBean,被定义为一个bean,所以spring会在初始化的时候为这种实现类初始化成员变量(追溯源码在BeanWrapperImpl的setValue方法,会一一调用实现了Factorybean类的方法),所以说会调用SqlSessionDaoSupport类(也就是MapperFactortyBean父类)里面的setSqlSessionFactory方法注入SqlSessionTemplate

所以spring的自动装配是怎么修改为通过set注入的呢。(验证后发现不会通过set注入)(既不修改自身的代码,又可以完美兼容spring):

答案就是在@MapperScan里,@MapperScan这个复合注解里面引入了@Import,里面包含了一个MapperScannerRegistrar,这个类实现了ImportBeanDefinitionRegistrar接口并在实现的方法中导入了MapperScannerConfigurer作为一个bean,

7:16:7:{S}-png.16887174967811688717496141.png

这个类就是核心类,他的作用可以解答这个问题:

1:把扫描到的mapper接口替换成MapperFactoryBean这个代理类,这个类的getobj方法将会由spring调用并且会把返回值作为bean而不是这个实现类本身

2:把MapperFactoryBean的自动装配改为通过set注入

下面是MapperScanConfigurer的代码

3:修改构造器注入为mapper接口对象(因为要使用动态代理,就要知道接口信息,所以需要给MapperFactoryBean注入class对象)

7:16:7:{S}-png.16887175127841688717512085.png

修改mapper接口实例和修改set注入:

所以SqlSessionDaoSupport就可以通过set注入SqlSessionTemplate啦!

源码如下:

有了SqlSessionTemplate。再回到MapperFactoryBean的GetObj方法:

这样通过getSqlSession()获得SqlSessionTemplate,就可以创造mapperProxy实体啦,在基于动态代理构建mapper就行了

Last updated