首先明确一点,在SSM或SpringBoot项目中,Mapper接口是通过BeanFactory后处理器MapperScannerConfigurer解析的。解析逻辑是从指定包中扫描所有Mapper接口、注意判断逻辑里要求必须是接口类型,然后基于每个Mapper接口(和容器中已存在的SqlSessionFactory对象)都创建一个MapperFactoryBean的bean定义并注册到容器中,即注册到容器的是工厂Bean的bean定义,每一个Mapper接口都对应一个工厂Bean,由工厂Bean来生产其对应的Mapper接口的代理实现类对象

  • 从上述内容可知,只要为MapperScannerConfigurer指定了Mapper接口所在的包、且该包中确实是Mapper接口,就能通过容器创建的MapperFactoryBean生产出Mapper接口的代理实现类对象(说明:工厂Bean本身由容器创建,而其生产的对象并非由容器创建,但是会交给容器管理,也就能从容器获取并使用)
  • 在SSM项目中,由于没有自动配置,所以需要手动向容器中注册MapperScannerConfigurer,注册方式有两种:
  • 在配置类中通过@Bean方法创建MapperScannerConfigurer,并通过setter方法为其basePakage属性指定Mapper接口所在的包(或在xml配置文件中通过标签配置,同样要为basePakage属性指定Mapper接口所在的包)
  • 在配置类上使用@MapperScan注解(该注解会自动向容器注册MapperScannerConfigurer),并通过该注解的value属性或basePakages属性指定Mapper接口所在的包

以上两种方式中不管哪一种,由于都指定了Mapper接口所在的包,所以无需为Mapper接口加@Mapper注解,最后都能从容器中成功获取Mapper接口的代理实现类对象

  • 在SpringBoot项目中,由于有自动配置,所以容器中会被自动注册MapperScannerConfigurer,但是这种自动注册的情况并未指定Mapper接口所在的包,所以需要为Mapper接口加@Mapper注解以让MapperScannerConfigurer找到它们来解析(前提:Mapper接口所在的包在@ComponentScan扫描的范围内)
  • SpringBoot项目中若也在配置类上使用了@MapperScan注解,则自动配置的MapperScannerConfigurer不会生效,因为@MapperScan注解会先于自动配置向容器注册MapperScannerConfigurer,而@MapperScan注解的value属性或basePakages属性是必须指定的否则容器启动时就会报错,也就意味着此时无需为Mapper接口加@Mapper注解

注:MapperScannerConfigurer、MapperFactoryBean、@MapperScan,都由MyBatis与Spring的整合包提供

总结:

  • 为MapperScannerConfigurer指定了Mapper接口所在的包时,无需为Mapper接口加@Mapper注解
  • 没有为MapperScannerConfigurer指定Mapper接口所在的包时,需要为Mapper接口加@Mapper注解(前提:Mapper接口所在的包在@ComponentScan扫描的范围内)