spring-mybatis 整合分析

作者: Tim在路上 | 来源:发表于2020-06-02 22:13 被阅读0次

    spring-mybatis 整合分析

    spring-mybatis 的整合流程
    1. 载入配置jar
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>2.0.4</version>
    </dependency>
    
    1. 配置datasource 和 sqlsessionFactoryBean
    @Bean
    public SqlSessionFactory sqlSessionFactory() throws Exception {
      SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
      factoryBean.setDataSource(dataSource());
      return factoryBean.getObject();
    }
    
    1. 创建mapper 接口
    public interface UserMapper {
      @Select("SELECT * FROM users WHERE id = #{userId}")
      User getUser(@Param("userId") String userId);
    } 
    
    1. 将接口注入到容器中
    @Bean
    public UserMapper userMapper() throws Exception {
      SqlSessionTemplate sqlSessionTemplate = new SqlSessionTemplate(sqlSessionFactory());
      return sqlSessionTemplate.getMapper(UserMapper.class);
    }
    
    1. 交给mapperFactory bean 注入到容器
    <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
      <property name="mapperInterface" value="org.mybatis.spring.sample.mapper.UserMapper" />
      <property name="sqlSessionFactory" ref="sqlSessionFactory" />
    </bean>
    

    然后我们就可以像普通的IOC容器中的bean进行调用;

    1. 使用mapperScan("")扫描我们接口,交给spring管理
    原理分析
    1. 接口是如何注入到容器?

    我们知道只有将实体类或者抽象类注入到容器,接口是无法注入到容器中。spring-mybatis 是如何将接口注入到容器。

    这里很明显可以通过动态代理进行,生成实体类进行注入;

    public class MapperProxy<T> implements InvocationHandler, Serializable {
     
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if (Object.class.equals(method.getDeclaringClass())) {
                return method.invoke(this, args);
            } else {
                MapperMethod mapperMethod = this.cachedMapperMethod(method);
                return mapperMethod.execute(this.sqlSession, args);
            }
        }
    }
    
    1. userMapper 接口是通过 MapperFactoryBean注入到bean容器

    在 postBeanFactoryProcesser() 改了class为MapperFactoryBean,
    在注册的过程中将@mapperScan扫描的接口改为,MapperFactoryBean,将其注册到容器中;

    构造函数任然是原本的构造函数参数,然后通过动态代理在MapperFactoryBean,实例化userMapper;

    把注入模型改为 by_type, 给父类sqlSession进程set方法赋值,不改为by_name 是为容错处理,避免配错;

    适应工厂bean进行注入,可以隐藏配置的代码;

    sqlSessionFactoryBean,会解析全局配置文件进行缓存;

    然后通过动态代理在MapperFactoryBean 的 getObject()生成代理对象;

    1. 我没并没有配置代理类的注解(@Bean,@Service),也没有进行扫描,他是如何注入的;

    我们知道spring将bean注入容器的 可以使用 @Bean,
    @service 等 + @ComponentScan(""), 或者 @Import进行注入;

    // 通过在注册器中,构造bean定义并通过import导入,spring整合mybatis
    @import(value = {ImportBeanDifinitionRegister.class})

    可以实现一个bean定义的注册类,将需要的bean注册到容器;

    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        if (this.processPropertyPlaceHolders) {
            this.processPropertyPlaceHolders();
        }
        ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
        scanner.setAddToConfig(this.addToConfig);
        scanner.setAnnotationClass(this.annotationClass);
        scanner.setMarkerInterface(this.markerInterface);
        scanner.setSqlSessionFactory(this.sqlSessionFactory);
        scanner.setSqlSessionTemplate(this.sqlSessionTemplate);
        scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName);
        scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName);
        scanner.setResourceLoader(this.applicationContext);
        scanner.setBeanNameGenerator(this.nameGenerator);
        scanner.registerFilters();
        scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ",; \t\n"));
    }
    

    Spring 中循环依赖是如何解决?

    spring中单利支持循环依赖。

    怎么关闭spring的循环依赖?

    spring 在初始化的时候完成依赖注入

    singlonObjects cache 单利缓存池 容器

    为什么要先get singlonObjects

    判断对象是否在创建中

    为什么有三级缓存?

    相关文章

      网友评论

        本文标题:spring-mybatis 整合分析

        本文链接:https://www.haomeiwen.com/subject/azfmzhtx.html