写点什么

0.o? 让我看看怎么个事儿之 SpringBoot 自动配置

  • 2024-01-18
    福建
  • 本文字数:2891 字

    阅读完需:约 9 分钟

首先我们提出 2 个问题:


SpringBoot 是干什么的?


是用来简化 Spring 原生的复杂的 xml 配置的进阶框架。


自动配置是什么?


我们用另外一个问题回答这个问题。


我们在 SpringBoot 开发中,就写了几个配置,怎么连接上的数据库?


spring:  datasource:    driverClassName: com.mysql.cj.jdbc.Driver    url: jdbc:mysql://192.0.0.1:3306/test?useUnicode=true&useSSL=false&serverTimezone=Asia/Shanghai    username: root    password: root
复制代码


在新手村时期,我们照着教程生搬硬抄的时候可能也想过这个问题,今天就来简单探究一下。


再次强调:


看明白本篇内容需要前置知识点,尤其是 @Import 注解。


这一切都要从 @SpringBootApplication 注解讲起。


@SpringBootApplication


@SpringBootApplication 注解是一个复合注解,它由如下三个注解组成。


@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited@SpringBootConfiguration  // 第一个@EnableAutoConfiguration  // 第二个@ComponentScan(excludeFilters = {  // 第三个        @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),        @Filter(type = FilterType.CUSTOM,                classes = AutoConfigurationExcludeFilter.class) })public @interface SpringBootApplication {}
复制代码


@SpringBootApplication├── @ComponentScan├── @SpringBootConfiguration│   └── @Configuration└── @EnableAutoConfiguration    ├── @Import(AutoConfigurationImportSelector.class)    └── @AutoConfigurationPackage        └── @Import(AutoConfigurationPackages.Registrar.class)
复制代码


@SpringBootConfiguration


@ComponentScan


@EnableAutoConfiguration


从注解的中文意思中也可以看出来,第三个 @EnableAutoConfiguration 是与我们自动配置紧密相关的。


我们先快速搞定前 2 个。


@SpringBootConfiguration


这个最简单,把头套摘下来,他就是一个普普通通的 @Configuration 注解包装而成而已,表示当前类是一个配置类。


@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Configuration // 本体在这public @interface SpringBootConfiguration {}
复制代码


@ComponentScan


可以指定 basePackageClasses 或 basePackages(或其别名 value)来定义要扫描的特定包。如果没有定义特定包,扫描将从声明此注解的类的包开始。


顾名思义就是扫描 Component。


扫描哪里?


可以通过该注解的属性指定 Spring 应该扫描的包。如果没有指定包,则默认扫描声明 @ComponentScan 的类所在的包及其子包。


哪些 Component?


使用 @Component, @Service, @Repository, @Controller 等注解的类。


扫描了做什么用?


将扫描到的组件注册为 Spring 的 Bean,加入到 ioC 容器进行统一管理。


@EnableAutoConfiguration


这是自动配置的核心注解!


@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited@AutoConfigurationPackage@Import(AutoConfigurationImportSelector.class)public @interface EnableAutoConfiguration {}    
复制代码


我们能看到,其中有 2 个注解:


@AutoConfigurationPackage


@Import(AutoConfigurationImportSelector.class)


@AutoConfigurationPackage


我们再点进去看一下,发现它又是一个 @Import 。


@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited@Import(AutoConfigurationPackages.Registrar.class)public @interface AutoConfigurationPackage {
}
复制代码


@Import(AutoConfigurationPackages.Registrar.class) 中的 Regisgrar 类如下:


static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
    @Override    public void registerBeanDefinitions(AnnotationMetadata metadata,                                        BeanDefinitionRegistry registry) {        register(registry, new PackageImport(metadata).getPackageName());    }
    @Override    public Set<Object> determineImports(AnnotationMetadata metadata) {        return Collections.singleton(new PackageImport(metadata));    }
}
复制代码


如果你有去好好看 @Import 注解的那篇文章,就会知道这是 ImportBeanDefinitionRegistrar 接口实现的方式。


这种方式提供一种手动方式灵活注册 bean。


在这里,我们根据两个提示就可以知道其功能:


• @AutoConfigurationPackage 是自动配置包的意思


• register(registry, new PackageImport(metadata).getPackageName()); 根据包名注册 bean

总结一下就是:


根据通过注解提供的元数据,动态地向 Spring 容器中注册特定包中的类作为 beans。


@Import(AutoConfigurationImportSelector.class)


如果你有去好好看 @Import 注解的那篇文章,就会知道这是 ImportSelector 接口实现的方式。


这种方式只需实现 selectImports 方法,并以数组的形式返回要导入的类名,即可实现批量注册组件。


AutoConfigurationImportSelector 类中通过自己的源码实现了如下一个功能:


把 spring-boot-autoconfigure 依赖中 META-INF/spring.factories 文件中需要自动配置的类名读取到数组中。


它长这个样子:


# Auto Configureorg.springframework.boot.autoconfigure.EnableAutoConfiguration=\org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\...
复制代码


那它到底怎么读取的?


这里我们不讨论具体实现,有兴趣有实力的可以扒源码自己看一下。


当然这些类不会全部都用到,经过筛选,去除重复、去除相应功能模块未开启的配置类、去除人为 exclude 掉的,将剩余的最终配置类全类名 String 数组返回。


最后我们再来回收一下开始的那个问题。


我们在 SpringBoot 开发中,就写了几个配置,怎么连接上的数据库?


我们简单捋一下:


SpringBoot 启动。


@SpringBootApplication 注解生效。


@EnableAutoConfiguration 注解生效。


@Import(AutoConfigurationImportSelector.class) 注解生效。


读取到了 org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration。


注册一个数据源 bean。


读取到 xml 的数据源配置。


大功告成!


文章转载自:JavaCode9

原文链接:https://www.cnblogs.com/cosimo/p/17970377

体验地址:http://www.jnpfsoft.com/?from=001

用户头像

还未添加个人签名 2023-06-19 加入

还未添加个人简介

评论

发布
暂无评论
0.o?让我看看怎么个事儿之SpringBoot自动配置_spring_不在线第一只蜗牛_InfoQ写作社区