Spring-Mybatis 注解连接器 MapperScannerRegistrar

使用Mybatis和spring集成常用2种方式,一种是xml配置。另一种就是注解,这一章我们从注解说起。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(MapperScannerRegistrar.class)
public @interface MapperScan {

我们不在xml配置的话,必须通过MapperScan来扫描。扫描注册的类就是MapperScannerRegistrar实现了ImportBeanDefinitionRegistrar并重写registerBeanDefinitions

public class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware {

  private ResourceLoader resourceLoader;

  /**
   * {@inheritDoc}
   */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
      //拿到MapperScan类里面的属性
      AnnotationAttributes annoAttrs = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName()));
      //获得spring的注册器registry
      ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);

      // this check is needed in Spring 3.1
      if (resourceLoader != null) {
        scanner.setResourceLoader(resourceLoader);
      }

      Class<? extends Annotation> annotationClass = annoAttrs.getClass("annotationClass");
      if (!Annotation.class.equals(annotationClass)) {
        scanner.setAnnotationClass(annotationClass);
      }

      Class<?> markerInterface = annoAttrs.getClass("markerInterface");
      if (!Class.class.equals(markerInterface)) {
        scanner.setMarkerInterface(markerInterface);
      }

      Class<? extends BeanNameGenerator> generatorClass = annoAttrs.getClass("nameGenerator");
      if (!BeanNameGenerator.class.equals(generatorClass)) {
        scanner.setBeanNameGenerator(BeanUtils.instantiateClass(generatorClass));
      }

      Class<? extends MapperFactoryBean> mapperFactoryBeanClass = annoAttrs.getClass("factoryBean");
      if (!MapperFactoryBean.class.equals(mapperFactoryBeanClass)) {
        scanner.setMapperFactoryBean(BeanUtils.instantiateClass(mapperFactoryBeanClass));
      }

      scanner.setSqlSessionTemplateBeanName(annoAttrs.getString("sqlSessionTemplateRef"));
      scanner.setSqlSessionFactoryBeanName(annoAttrs.getString("sqlSessionFactoryRef"));

      List<String> basePackages = new ArrayList<String>();
      for (String pkg : annoAttrs.getStringArray("value")) {
        if (StringUtils.hasText(pkg)) {
          basePackages.add(pkg);
        }
      }
      //如果配置了包路径则将入进去
      for (String pkg : annoAttrs.getStringArray("basePackages")) {
        if (StringUtils.hasText(pkg)) {
          basePackages.add(pkg);
        }
      }
      for (Class<?> clazz : annoAttrs.getClassArray("basePackageClasses")) {
        basePackages.add(ClassUtils.getPackageName(clazz));
      }
      scanner.registerFilters();
      //具体执行扫描
      scanner.doScan(StringUtils.toStringArray(basePackages));
    }

  /**
   * {@inheritDoc}
   */
  @Override
  public void setResourceLoader(ResourceLoader resourceLoader) {
    this.resourceLoader = resourceLoader;
  }

}

然后我们进入ClassPathMapperScanner#doScan方法调用父类ClassPathBeanDefinitionScanner#doScan来实现扫描并注册到spring ioc中

ClassPathMapperScanner

public Set<BeanDefinitionHolder> doScan(String... basePackages) {
  Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);

  if (beanDefinitions.isEmpty()) {
    logger.warn("No MyBatis mapper was found in '" + Arrays.toString(basePackages) + "' package. Please check your configuration.");
  } else {
    processBeanDefinitions(beanDefinitions);
  }

  return beanDefinitions;
}

ClassPathBeanDefinitionScanner

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
  Assert.notEmpty(basePackages, "At least one base package must be specified");
  Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();
  //获取配置的路径下面所有的mapper全限定类名
  for (String basePackage : basePackages) {
    Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
    for (BeanDefinition candidate : candidates) {
      ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
      candidate.setScope(scopeMetadata.getScopeName());
      //获取beanName
      String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
      if (candidate instanceof AbstractBeanDefinition) {
        postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
      }
      //是否懒加载、是否为主键等
      if (candidate instanceof AnnotatedBeanDefinition) {
        AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
      }
      //是否beanName查看是否存在以及注册过
      if (checkCandidate(beanName, candidate)) {
        //包装一下
        BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
        definitionHolder =
                AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
        //将入到当前列表中
        beanDefinitions.add(definitionHolder);
        //注册到IOC        registerBeanDefinition(definitionHolder, this.registry);
      }
    }
  }
  return beanDefinitions;
}

之前博客中讲到IOC这些东西,相信大家看到这里就大致清楚了。

总结一下:

我们使用MapperScan注解时,会将包路径一起设置进入。通过扫描MapperScan注解的类,通过AnnotationConfigUtils.processCommonDefinitionAnnotations来解析。然后包装为BeanDefinitionHolder,然后注册到Spring IOC里面。

 

上一篇:  Mybatis源码动态代理调用

 下一篇: Spring-Mybatis XML配置连接 MapperScannerConfigurer

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于Spring整合MyBatis注解开发,你可以按照以下步骤进行: 1. 首先,在你的项目中引入相应的依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> ``` 2. 创建一个MyBatis的配置文件,比如`mybatis-config.xml`,在该文件中配置MyBatis的相关属性和插件。例如,可以配置数据源、事务管理器等。 3. 创建一个数据源配置类,用于配置数据库连接信息和数据源。可以使用Spring Boot的`application.properties`或`application.yml`文件进行配置。 4. 创建Mapper接口,使用MyBatis注解方式定义SQL语句的映射。例如: ```java @Mapper public interface UserMapper { @Select("SELECT * FROM users") List<User> getAllUsers(); @Insert("INSERT INTO users(name, age) VALUES(#{name}, #{age})") void insertUser(User user); } ``` 5. 创建对应的Mapper XML文件(可选),用于更复杂的SQL语句编写。 6. 在Spring Boot的启动类上加上`@MapperScan`注解,指定扫描Mapper接口所在的包。 ```java @SpringBootApplication @MapperScan("com.example.mapper") public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` 7. 使用@Autowired注解Mapper接口注入到其他组件中使用。 这样,你就可以在Spring Boot项目中使用MyBatis注解方式进行开发了。希望对你有帮助!如果你还有其他问题,可以继续提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值