写点什么

spring 中如何自己去实现一个 starter

作者:ZuccRoger
  • 2022 年 5 月 10 日
  • 本文字数:2267 字

    阅读完需:约 7 分钟

什么是自动装配

通过注解或者一些简单的配置就能在 Spring Boot 的帮助下实现某块功能。

spring 是如何实现自动装配的?

springboot 的自动配置是基于 spring factories 机制实现的,这是一种服务发现机制,类似 Java SPI。 spring 会自动扫描所有 jar 包类路径下的 META-INF/spring.factories 文件,读取其中的类型并进项实例化。spring.factories 文件中的内容实际上就是要导入的接口名和实现类组成的 kv 对,key 为文件中定义的一些标识工厂类,value 就是能自动配置的一些工厂实现的类。 在自动装配时,其实就是去加载 AutoConfiguration 类和实现类,在加载自动配置类的时候,并不是将 spring.factories 的配置全部加载进来,而是通过 @Conditional 等注解的判断进行动态加载,只有当容器满足了注解中的条件的时候,才会将类加载到容器中




偷来的八股文:自动装配依托 @Import 的强大功能和 spring 的 SPI 机制。通过 SPI 机制发现类,通过 @Import 将类注册到 spring 中。@SpringBootApplication 这个注解时组合注解里面包含自动扫描注解,里面包含一个 EnableAutoConfiguration 注解,这个注解作用是去寻找每个 jar 包里面的 META-INF/spring.factories 文件,之后将文件里面的类全部实例化。每个需要自动装配的模块都需要编写一个 AutoConfiguration 类,这些 AutoConfiguration 类的原理大概是通过 @Import 注解将其属性类 Properties 全部到注册 spring 容器中,属性类通过注解 @ConfigurationProperties 从配置文件里面取到配置值。之后将关键的类注册为 bean 自动注入属性类进行初始化完成自动装配的功能。

细分相关知识如下:

我们知道


@SpringBootApplication = @SpringBootConfiguration+@EnableAutoConfiguration+@ComponentScan
复制代码


我们要重点关注这个 @EnableAutoConfiguration.看到 EnableAutoConfiguration.class 文件有个 @Import({AutoConfigurationImportSelector.class})


@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited@AutoConfigurationPackage@Import({AutoConfigurationImportSelector.class})public @interface EnableAutoConfiguration {    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
Class<?>[] exclude() default {};
String[] excludeName() default {};}
复制代码

流程图

  1. 第一步会去看这个

  2. 可以看到默认是 spring.boot.enableautoconfiguration 的值默认是 true。

  3. 得到排除的依赖项

  4. 得到配置内容

如何自己实现一个 starter?

  1. 在 resources/META-INF 中新建 spring.factories 文件


org.springframework.boot.autoconfigure.EnableAutoConfiguration=\com.roger.demospringbootstarter.config.DemoConfig
复制代码


  1. 在这个 EnableAutoConfiguration 的属性所对应的 java 文件中写入自己想装配的 bean.


/** * @author: 骆佳俊 * @date: 2022/4/27 10:21 AM */@Configurationpublic class DemoConfig {  private static final Logger logger = LoggerFactory.getLogger(DemoConfig.class);  @Bean  public void demoService() {    logger.info("我是自动装配进来的");  }}
复制代码


  1. 在外部如何引用?本地打包的时候可以直接点击 mvn clean pakcage.然后会在本地的 maven 仓库中出现该 jar 文件。


        <dependency>            <groupId>com.roger</groupId>            <artifactId>demo-spring-boot-starter</artifactId>            <version>0.0.1-SNAPSHOT</version>        </dependency>
复制代码

如何自动配置是否生效

启动的时候可以增加-Ddebug 参数.会有以下 4 种形式的输出



Unconditional classes:----------------------
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration
com.roger.demospringbootstarter.config.DemoConfig
org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration
org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration
复制代码


最终在输出的命令行中我看见了 com.roger.demospringbootstarter.config.DemoConfig 该 Bean.

最后的效果

2022-04-30 10:57:06.150  INFO 56979 --- [           main] r.c.j.JavaFundamentApplication           : Starting JavaFundamentApplication using Java 1.8.0_312 on YolandadeMacBook-Air.local with PID 56979 (/Users/yolanda/code/javaProject/javaFundament/target/classes started by yolanda in /Users/yolanda/code/javaProject/javaFundament)2022-04-30 10:57:06.152  INFO 56979 --- [           main] r.c.j.JavaFundamentApplication           : No active profile set, falling back to 1 default profile: "default"2022-04-30 10:57:09.567  INFO 56979 --- [           main] c.r.d.config.DemoConfig                  : 我是自动装配进来的asdas dlksa dsj kldsja kldsaj klasjdl ksaj2022-04-30 10:57:09.656  INFO 56979 --- [           main] r.c.j.JavaFundamentApplication           : Started JavaFundamentApplication in 3.71 seconds (JVM running for 4.835)Disconnected from the target VM, address: '127.0.0.1:61225', transport: 'socket'
复制代码

源代码自取

  1. https://github.com/ZuccRoger/AutoConfigaration

参考资料

  1. Javaguide

  2. 极客时间-了解自动装配实现原理

发布于: 刚刚阅读数: 3
用户头像

ZuccRoger

关注

还未添加个人签名 2019.10.06 加入

还未添加个人简介

评论

发布
暂无评论
spring中如何自己去实现一个starter_5月月更_ZuccRoger_InfoQ写作社区