乐趣区

关于mybatis:mybatis之注解实现机制

咱们在应用 mybatis 的时候,少数状况下都是创立一个对应 mapper 的 xml 文件来写 sql 语句,这种形式也是官网举荐并且是最灵便的形式。但其实 mybatis 也反对通过注解的形式来实现 sql 语句。本篇文章就是聊聊 mybatis 是如何应用注解形式来实现 sql 执行的。

知识点

  • 什么是注解
  • 如何应用
  • 实现原理

什么是注解

翻译过去可能很多人不分明,翻译回去就是 Annotation。咱们平时在代码中肯定用到很多注解,特地是 springboot 我的项目,看上面的例子你就明确了

@SpringBootApplication
public class MybatisAnalyzeApplication {public static void main(String[] args) {SpringApplication.run(MybatisAnalyzeApplication.class, args);
    }

}

这是非常简单的一个 springboot 启动类,这个 @SpringBootApplication 就是注解。

如何应用

mybatis 注解形式的应用非常简单,间接在你定义的 Mapper 接口对应的办法上加一个注解就能够了,间接上代码:

@Repository
public interface UserInfoMapper {UserInfo selectById(int id);
    @Select("select * from user_info where user_name = #{userName}")
    List<UserInfo> select(String userName, String nickName);
    int insert(UserInfo userInfo);
    int update(int id, String nickName);
}

能够看到 UserInfoMapper 接口中的 select 办法下面有一个 @Select 的注解,这样就完了。其余几个没有加注解的办法,还是须要定义 xml 文件(注解形式和 xml 形式是能够混用的),须要留神的是 xml 文件中不能再定义曾经加过注解的办法,否走会抛出异样。同样的,对于增、改、删操作,加上注解 @Insert@Update@Delete 即可。

如果咱们还须要用到一些启用缓存、期待超时工夫等属性怎么办呢,这些可是在原来的 xml 配置中能够配置的。别急,能够再加一个 @Options 注解,如下

    @Options(useCache = true, timeout = 3000)
    @Select("select * from user_info where user_name = #{userName}")
    List<UserInfo> select(String userName, String nickName);

当然还有 @SelectKey@ResultMap 等注解是和原来的 xml 形式配置对应起来的,不过这里是有局限性的,比方 @ResultMap 就须要联合 xml 配置来应用,这也是为什么官网举荐 xml 形式的起因之一。

实现原理

最初咱们来理解一下 mybatis 是如何实现注解形式来执行 sql 的,顺带的介绍一下为什么咱们定义的 mapper 明明是接口类型,为什么可能在代码中间接应用。先来看一下注解所在包

下面这个包里蕴含了所有注解类型,基本上和 xml 配置的属性是能够关联起来的,如果不晓得 xml 形式对应的注解形式怎么应用,能够间接到这里看看。接着看下哪里启动时加载 mapper 的中央 `org.apache.ibatis.binding.MapperRegistry#addMapper

在这个逻辑中,咱们能够看到有一个 knownMappers,它是寄存所有咱们定义的 mapper 接口的,对应的 value 类型是MapperProxyFactory,这个类型很重要,前面再讲。能够看到这个类型MapperAnnotationBuilder,看名称就晓得是专门对注解形式进行解决的类,与之对应的解决 xml 的类就是XMLMapperBuilder。跟进去看下parser.parse() 逻辑

这里优先会去解析 xml 配置,接着一一解析 mapper 的办法,跟进去看下如何解析的

能够看到这里就对注解进行解析了,办法上的注解肯定要在以下范畴内能力解析

前面每个注解的解析就不介绍了,比较简单。

集成 spring

为什么咱们定义的 mapper 明明是接口类型,为什么可能在代码中间接应用?这是因为集成了 spring,由 mybatis-spring 包帮咱们做掉了。咱们平时在 spring 中应用的还是须要指定扫描的 mapper 包所在门路,注解形式就是@MapperScan

它会通过 MapperScannerRegistrar 将 mapper 注册为 bean,最终在 org.mybatis.spring.mapper.ClassPathMapperScanner#processBeanDefinitions 设置理论的 mapper 类型(MapperFactoryBean)

MapperFactoryBean 是一个 FactoryBean,所以理论的 bean 是通过它的getObject 办法获取到的

跟进去最终在这里获取 `org.apache.ibatis.binding.MapperRegistry#getMapper

其实就是一个动静代理。

总结

注解这一块实现还是比较简单的,对于集成 spring 并做动静代理的形式,咱们本人的代码里也能够参考。

参考资料

https://mybatis.org/mybatis-3…

退出移动版