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