9.自定义扫描器与Mybatis的扫描器


highlight: arduino-light

Mybatis自定义扫描器

上一篇详细讲解了spring的扫描器ClassPathBeanDefinitionScanner,本篇我们我们将模拟mybatis如何通过spring完成Mapper扫描,讲解如何通过spring编写自定义扫描器。

既然ClassPathBeanDefinitionScanner完成了spring的扫描功能,我们完全可以继承这个类来达到创建自定义扫描器的目的。

自定义CustomScanner

java public class CustomScanner extends ClassPathBeanDefinitionScanner {    public CustomScanner(BeanDefinitionRegistry registry) {        super(registry);   }    @Override    public void addIncludeFilter(TypeFilter includeFilter) {        super.addIncludeFilter(includeFilter);   } }

上一篇我们讲过ClassPathBeanDefinitionScanner可以通过includeFilters来过滤符合条件的业务类。spring启动时会默认生成一个ClassPathBeanDefinitionScanner对象,该对象在初始化时会注册默认的过滤器。

```java protected void registerDefaultFilters() { this.includeFilters.add(new AnnotationTypeFilter(Component.class)); ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader(); try { this.includeFilters.add (new AnnotationTypeFilter (ClassUtils.forName("javax.annotation.ManagedBean", cl), false)); this.logger.trace ("JSR-250 'javax.annotation.ManagedBean' found"); } catch (ClassNotFoundException var4) { }

try {
    this.includeFilters.add(new AnnotationTypeFilter
                            (ClassUtils.forName("javax.inject.Named", cl),
                            false));
    this.logger.trace
            ("JSR-330 'javax.inject.Named' annotation found");
} catch (ClassNotFoundException var3) {
}

} ```

ClassPathBeanDefinitionScanner注册的过滤器类型是AnnotationTypeFilter,也就是说,我们只要调用addIncludeFilter添加自定义的AnnotationTypeFilter就行了,其余的交给ClassPathBeanDefinitionScanner来完成。

自定义注解MyAnnotation

OK,我们先自定义一个注解:

java public @interface MyAnnotation { }

再自定义一些类

```java

@MyAnnotation public class MyClass { }

@MyAnnotation public class MyClass2 { } ```

自定义AnnotationTypeFilter

```java public class Test { public static void main(String[] args) { AnnotationConfigApplicationContext context = new
AnnotationConfigApplicationContext(); //注册配置类 context.register(Config.class); //实例化自定义扫描器 CustomScanner customScanner = new CustomScanner(context); //为自定义扫描器增加包含过滤器 customScanner.addIncludeFilter(new
AnnotationTypeFilter(MyAnnotation.class)); //将带有MyAnnotation注解的类扫描到springIOC容器中,并返回扫描的个数 int num = customScanner.scan("com.scan");

System.out.println("扫描的个数:"+num);
    context.refresh();
    System.out.println(context.getBean(MyClass.class));
}

}

//打印结果: //扫描的个数:2 //com.scan.MyClass@1199fe66 ```

PS:spring只能扫描实体类,抽象类和接口是不能扫描的。

自定义扫描器重写isCandidateComponent

ClassPathScanningCandidateComponentProvider#isCandidateComponent

```java if (isCandidateComponent(sbd)) { if (debugEnabled) { logger.debug("Identified candidate component class:"+resource); } //返回BeanDefinition 注册到 BeanFactory candidates.add(sbd); }

/** * metadata.isIndependent():不是内部类或者是静态内部类 * metadata.isConcrete():不能是接口或抽象类 * metadata.isAbstract():是抽象类、 * metadata.hasAnnotatedMethods(Lookup.class.getName()):有lookUp注解标注 * 总结就是需要满足以下两个条件: * 1. 不能是内部类或者是静态内部类 * 2. 不能是接口或者抽象类,如果是抽象类,则需要LookUp注解标注 */ protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) { AnnotationMetadata metadata = beanDefinition.getMetadata(); //1.普通的实体类 //2.带@Lookup注解的方法的抽象类 //上面2种情况返回true return (metadata.isIndependent() && (metadata.isConcrete() || (metadata.isAbstract() && metadata.hasAnnotatedMethods(Lookup.class.getName())))); } ```

isCandidateComponent这个方法判断

  • 如果是实体类 返回true

  • 如果是抽象类,但是有抽象方法被@Lookup注解注释返回true。

也就是说如果你是接口,isCandidateComponent返回的是false,candidates.add(sbd);就不会执行了。自然添加不到IOC容器中。

mybatis就是修改了这个方法,让Mapper接口能扫描到IOC容器中的,我们先模拟.

自定义注解@MyAnnotation加到接口上。

java @MyAnnotation public interface MyInterFace { @Select("select * from table") public void select(); }

自定义扫描器

```java public class CustomScanner extends ClassPathBeanDefinitionScanner { public CustomScanner(BeanDefinitionRegistry registry) { super(registry); }

@Override
public void addIncludeFilter(TypeFilter includeFilter) {
    super.addIncludeFilter(includeFilter);
}

@Override
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
        //如果是接口,则返回true,会添加到IOC容器中去
        return beanDefinition.getMetadata().isInterface();
}

} ```

测试

```java public class Test { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); //注册配置类 context.register(Config.class); CustomScanner customScanner = new CustomScanner(context); customScanner.addIncludeFilter(new
AnnotationTypeFilter(MyAnnotation.class)); int num = customScanner.scan("com.scan"); System.out.println("扫描的个数:"+num); context.refresh(); } } //打印结果 //扫描的个数:1

```

然后,spring会根据MyInterFace生成一个动态代理类,并通过反射拿到你所有的方法,拿到方法后再通过反射拿到你的注解信息,实际上,mybatis就是这么做的,不信看mybatis源码:

java // mybatis的自定义扫描类ClassPathMapperScanner.java protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) { //接口 && 不是内部类或者是静态内部类 return beanDefinition.getMetadata().isInterface() && beanDefinition.getMetadata().isIndependent(); }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Spring Boot Starter 是 Spring Boot 应用程序的预配置模块,可以帮助我们快速集成常用框架。MyBatis 是一个持久层框架,用于映射 Java 对象到数据库表。 如果要在 Spring Boot 应用程序中使用 MyBatis,可以创建自定义的 Spring Boot Starter 来简化配置。 步骤如下: 1. 创建一个 maven 项目,并在 pom 文件中添加依赖 spring-boot-starter、mybatis-spring-boot-starter。 2. 创建一个配置类,来配置 MyBatis。 3. 创建一个自动配置类,用于自动配置 MyBatis。 4. 创建一个 starter 类,用于向 Spring Boot 提供自动配置。 5. 在 pom 文件中添加相关信息,用于发布到 maven 仓库。 6. 发布到 maven 仓库,并在其他项目中使用。 如果你想要详细了解,可以参考官网上关于 Spring Boot Starter 的文档。 ### 回答2: 要自定义 Spring Boot Starter 操作 MyBatis 数据库,可以按照以下步骤进行操作: 1. 创建一个 Maven 项目,并指定父项目为 Spring Boot Starter Parent。 2. 在项目的 pom.xml 文件中添加必要的依赖,包括 Spring Boot Starter、MyBatis 和相应的数据库驱动程序。 3. 创建一个自定义的配置类,用于配置 MyBatis 的数据源、事务管理器等。 4. 在配置类中使用 @Configuration 注解标注该类为配置类,并使用 @EnableConfigurationProperties 注解引入配置属性。 5. 创建一个自定义的 Starter 类,用于自动配置 MyBatis 相关的组件。 6. 在 Starter 类中使用 @Configuration 注解标注该类为配置类,并使用 @EnableAutoConfiguration 注解启用自动配置。 7. 在 Starter 类中使用 @ConditionalOnClass 注解,指定条件,在类路径下存在 MyBatis 相关的类时才进行自动配置。 8. 在 Starter 类中使用 @Import 注解,导入配置类,将自定义的配置应用到 Spring Boot 项目中。 9. 编写自定义的配置文件,用于配置 MyBatis 的相关属性,例如数据库连接信息、Mapper 扫描路径等。 10. 在项目的 pom.xml 文件中添加 spring.factories 文件,将自定义的 Starter 类注册到 Spring Boot 应用中。 11. 在 Spring Boot 项目中添加对自定义 Starter 的依赖,可通过 Maven 依赖坐标来引入。 12. 配置项目的 application.properties 或 application.yml 文件,指定数据库相关的信息以及其他自定义属性。 经过以上步骤的操作,就可以自定义 Spring Boot Starter 来操作 MyBatis 数据库了。可以通过引入自定义的 Starter 来简化项目的配置,并在应用中直接使用 MyBatis 进行数据库操作,提高开发效率和代码的可维护性。 ### 回答3: 自定义Spring Boot Starter操作Mybatis数据库涉及以下步骤: 1. 创建一个新的Maven项目,并在pom.xml文件中添加Spring Boot和Mybatis依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> </dependency> ``` 2. 创建一个自定义的starter模块,在其中定义配置类和Mybatis相关配置: ```java @Configuration @AutoConfigureAfter(DataSourceAutoConfiguration.class) @EnableConfigurationProperties(MybatisProperties.class) public class MybatisAutoConfiguration { @Autowired private MybatisProperties properties; @Autowired(required = false) private List<Interceptor> interceptors; @Bean public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception { SqlSessionFactoryBean factory = new SqlSessionFactoryBean(); factory.setDataSource(dataSource); factory.setConfiguration(properties.getConfiguration()); if (interceptors != null) { factory.setPlugins(interceptors.toArray(new Interceptor[0])); } return factory.getObject(); } @Bean public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) { return new SqlSessionTemplate(sqlSessionFactory); } } ``` 3. 创建自定义的配置类MybatisProperties,用于定义数据库的相关配置: ```java @ConfigurationProperties(prefix = "spring.mybatis") public class MybatisProperties { private Configuration configuration; // 其他配置... // Getter和Setter方法 } ``` 4. 在resources目录下创建配置文件application.yml,配置数据库相关信息: ```yaml spring: datasource: url: jdbc:mysql://localhost:3306/mydb username: username password: password spring: mybatis: configuration: map-underscore-to-camel-case: true cache-enabled: true ``` 5. 在使用的项目中添加自定义的starter依赖,并在application类上添加@EnableMybatis注解: ```java @SpringBootApplication @EnableMybatis public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` 通过以上步骤,我们就可以自定义Spring Boot Starter来操作Mybatis数据库了。这样做的好处是,可以将Mybatis的配置和操作封装在starter中,使得项目更加简洁,并且能够方便地重用该starter。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值