• 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);
        }
    }
  • 相关阅读:
    Leetcode题目practice
    文件操作
    39个奇葩代码注释,拿走不谢
    Spring Boot 之配置导入,强大到不行!
    Git 的这个神技,学会爽歪歪~
    同事天天写垃圾代码,就没办法?
    for (;;) 与 while (true),哪个更快?
    Spring Boot 怎么打一个可执行 Jar 包?
    程序员真的是太太太太太太太太难了!
    面试官:new一个对象有哪两个过程?
  • 原文地址:https://www.cnblogs.com/anxiao/p/15837127.html
Copyright © 2020-2023  润新知