Mybatis

Mybatis和Spring的整合:

  1. @MapperScan注解通过@Import方法导入MapperScannerRegistrar类,MapperScannerRegistrar实现了ImportBeanDefinitionRegistrar接口,覆写了registerBeanDefinitions方法,作用为手动注册某个Bean的BeanDefinition到容器中【DefaultListableBeanFactory=>beanDefinitionMap】。
  2. ImportBeanDefinitionRegistrar接口是Spring的扩展点之一,Spring容器启动时会回调所有实现了ImportBeanDefinitionRegistrar接口的实现类中的registerBeanDefinitions方法,完成自定义BeanDefinition注册。
  3. MapperScannerRegistrar的registerBeanDefinitions方法手动将MapperScannerConfigurer类通过这种方式将自己的BeanDefinition实例注册到了容器中,为下一步Bean初始化做准备。
  4. MapperScannerConfigurer类实现了BeanDefinitionRegistryPostProcessor接口,该接口也是Spring的扩展点之一,Spring容器启动时会回调所有实现了BeanDefinitionRegistryPostProcessor接口的实现类中的postProcessBeanDefinitionRegistry方法,进行BeanDefinition注册的后置处理,可以修改BeanDefinition对象。
  5. MapperScannerConfigurer的postProcessBeanDefinitionRegistry方法中创建了ClassPathMapperScanner对象,该对象对@MapperScan注解中配置的包路径进行了扫描,为每个mapper接口创建对应的BeanDefinition实例,并修改所有实例中的beanClass属性值为MapperFactoryBean,autoWireMode为byType。
  6. 将所有mapper接口的BeanDefinition实例注册到Spring的容器中,为下一步实例化mapper接口做准备。
  7. MapperFactoryBean是一个很关键的类,MapperFactryBean集成了SqlSessionDaoSupport类,实现了FactoryBean接口,覆写了getObject()方法。
  8. FactoryBean类型的Bean,在进行Bean初始化时,会通过调用自己的getObject()方法,获取对象;而MapperFactoryBean覆写后的getObject()方法,实际执行的是getSqlSession().getMapper(this.mapperInterface),通过此方法衔接到Mybaits,以JDK动态代理的方式,创建了一个代理对象,最后将代理对象注册到了Spring容器中。

1、定义一个注解MapperScan,注解上含有mapper扫描路径,在MapperScan注解中添加Spring注解解析器

MapperScan注解:

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

 

2、注解解析器会读取路径下的mapper,并对mapper类进行解析

public class ClassPathMapperScanner {

  @Override
  public Set<BeanDefinitionHolder> doScan(String... basePackages) {
    //获取所有符合条件的BeanDefinitionHolder对象
    Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);
//将beanDefinitions注册至spring容器 processBeanDefinitions(beanDefinitions); return beanDefinitions; }
//处理扫描得到的BeanDefinitionHolder集合,将集合中的每一个mapper接口转换成MapperFactoryBean后,注册至spring容器 private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) { GenericBeanDefinition definition; for (BeanDefinitionHolder holder : beanDefinitions) { definition = (GenericBeanDefinition) holder.getBeanDefinition(); //设置代理类 definition.getConstructorArgumentValues().addGenericArgumentValue(definition.getBeanClassName()); //设置bean定义为mapperFactoryBean definition.setBeanClass(this.mapperFactoryBean.getClass()); } } }

3、将Mybatis中的代理对象注册到Spring中

通过Mybatis SqlSession获取Mapper代理对象时,然后通过FactoryBean将对象注册到Spring

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

    private Class<T> mapperInterface;    // 具体Mapper接口类型

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

 

posted @ 2022-01-23 19:44  安小  阅读(39)  评论(0编辑  收藏  举报