springBoot中的starter你讲的很好(每天一题,一起进大厂)

214 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第7天,点击查看活动详情

每天一题,一起进大厂,欢迎大家点击阅读。《一起进大厂系列》是我一直持续更新的,主要是针对大厂面试题进入针对性深入学习。欢迎大家关注该专栏,会进行不间断更新。一起加油,一起进大厂。话不多说,进入今天的正题。

写在前面

前情回顾,我们上一篇讲到Boot的自动装配原理,发现利用spi机制实现,不清楚的可以去看看。今天我们拿出一篇针对性的文章再细深入实践下。

SpringBoot 最强大的功能就是把我们常用的场景抽取成了一个个starter(场景启动器),我们通过引入springboot 为 我提供的这些场景启动器,我们再进行少量的配置就能使用相应的功能。即使是这样,springboot也不能囊括我们所有 的使用场景,往往我们需要自定义starter,来简化我们对springboot的使用。

什么是starter

我们照顾下基础比较弱的伙伴,简单聊下starter,starter是一组方便的依赖描述符,当我们使用它时,可以获得所有需要的Spring和相关技术的一站式服务。典型的如spring-boot-starter-web,引入之后,自动引入所有有关spring web项目相关的依赖。

还有各种的starter,比如上节讲到的redis starter。

说实话,用久了SpringBoot,都已经忘记被每个项目都需要引入spring-core,spring-context,spring-web等等所支配的恐惧了哈哈。

我们先提前总结下,一会儿根据这个规则实践下

  • 启动器(starter)是一个空的jar文件,仅仅提供辅助性依赖管理,这些依赖可能用于自动装配或其他类库。

  • 需要专门写一个类似spring-boot-autoconfigure的配置模块

  • 用的时候只需要引入启动器starter,就可以使用自动配置了

官方命名空间

  • 前缀:spring-boot-starter-
  • 模式:spring-boot-starter-模块名
  • 举例:spring-boot-starter-web、spring-boot-starter-jdbc

自定义命名空间

  • 后缀:-spring-boot-starter
  • 模式:模块-spring-boot-starter
  • 举例:mybatis-spring-boot-starter

如何自定义starter

如何编写自动配置

我们参照@WebMvcAutoConfiguration为例,我们看看们需要准备哪些东西,下面是WebMvcAutoConfiguration的 部分代码:

@Configuration
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class,
      ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {

   public static final String DEFAULT_PREFIX = "";

   public static final String DEFAULT_SUFFIX = "";

   private static final String[] SERVLET_LOCATIONS = { "/" };

   @Bean
   @ConditionalOnMissingBean(HiddenHttpMethodFilter.class)
   public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() {
      return new OrderedHiddenHttpMethodFilter();
   }

   @Bean
   @ConditionalOnMissingBean(HttpPutFormContentFilter.class)
   @ConditionalOnProperty(prefix = "spring.mvc.formcontent.putfilter", name = "enabled", matchIfMissing = true)
   public OrderedHttpPutFormContentFilter httpPutFormContentFilter() {
      return new OrderedHttpPutFormContentFilter();
   }
   
   //省略

我们可以抽取到我们自定义starter时同样需要的一些配置。

@Configuration : 指定这个类是一个配置类

@ConditionalOnXXX : 指定条件成立的情况下自动配置类生效

@AutoConfigureOrder : 指定自动配置类的顺序

@Bean : 向容器中添加组件

@ConfigurationProperties : 结合相关xxxProperties来绑定相关的配置

@EnableConfigurationProperties : 让xxxProperties生效加入到容器中

自动配置类要能加载需要将自动配置类,配置在META‐INF/spring.factories中

org.springframework.boot.autoconfigure.EnableAutoConfiguration org.springframework.boot.autoconfigure.aop.AopAutoConfiguration

自定义starter 实例

我们需要先创建一个父maven项目:springboot_custome_starter

两个子Module:

1、shushi-spring-boot-starter
2、shushi-spring-boot-starter-sample

springboot_custome_starter pom.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>


    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>cn.shushi</groupId>
    <artifactId>springboot_custome_starter</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>


    <modules>
        <!-- 自定义starter -->
        <module>shushi-spring-boot-starter</module>
        <!-- 用于测试自定义starter-->
        <module>shushi-spring-boot-starter-sample</module>
    </modules>

</project>

创建子模块shushi-spring-boot-starter

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springboot_custome_starter</artifactId>
        <groupId>cn.shushi</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>shushi-spring-boot-starter</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>



    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

    </dependencies>
</project>

创建测试用模块shushi-spring-boot-starter-sample

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springboot_custome_starter</artifactId>
        <groupId>cn.shushi</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>shushi-spring-boot-starter-sample</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <!-- 自定义starter-->
        <dependency>
            <groupId>cn.shushi</groupId>
            <artifactId>shushi-spring-boot-starter</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

项目结构如下:

image.png

shushi-spring-boot-starter: 我们本次的主角,自定义starter
shushi-spring-boot-starter-sample: 测试模块,用于测试starter是否生效

编写starter代码

public class DemoHandler {

    public DemoHandler(){
        System.out.println("demo handler init!!");
    }
}

编写自动配置类

public class DemoAutoConfiguration {

    @Bean
    public DemoHandler demoHandler(){
        return new DemoHandler();
    }
}

resources目录下新建META-INF/spring.factories文件

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.shushi.starter.config.DemoAutoConfiguration

在测试模块中编写测试类

@SpringBootApplication
public class SampleApplication {

    public static void main(String[] args) {
        SpringApplication.run(SampleApplication.class, args).close();
    }
}

启动项目看控制台打印

image.png

demo handler成功的被自动配置类注入了,也就是说,我们的starter生效啦~

OK 我们的starter 今天就讲到这里,下面进行下总结

总结

本文基于上一期的SpringBoot自动装配原理介绍了如何自定义starter,不管是面试还是实战都是需要的,希望可以好好回顾下。

这一章的内容还是比较简单的,希望大家有所收获。

我们下期继续学习 加油

弦外之音

啰嗦一句,欢迎大家关注学习《一起进大厂系列》