上期讲到,对于SpringBoot主动拆卸原理,置信小伙伴们曾经看明确啦,明天,咱们就来聊一聊如何依据主动拆卸原理,自定义一个starter吧

什么是starter

咱们玩了那么久的SpringBoot, 简直我的项目依赖中基本上全是各种各样的starter, 那么到底什么是starter?

starter是一组不便的依赖描述符,当咱们应用它时,能够取得所有须要的Spring和相干技术的一站式服务,典型的如spring-boot-starter-web,引入之后,主动引入所有无关spring web我的项目相干的依赖。

说实话,用久了SpringBoot,阿鉴都曾经遗记被每个我的项目都须要引入spring-core,spring-context,spring-web等等所摆布的恐怖了哈哈。

回顾SpringBoot主动拆卸的内容

在上一节,咱们是从探索redis的主动拆卸过程开始的,那么小伙伴们还记得它的过程吗?

阿鉴带大家回顾一下:

我的项目启动时,Spring通过@Import注解导入了AutoConfigurationImportSelector, 而后调用该类selectImports时,从classpath下的META-INF/spring.factories文件中读取key为EnableAutoConfiguration的配置类,而后Spring便会将这些类加载到Spring的容器中,变成一个个的Bean。

入手实际

流程曾经梳理完了,当初就开始实际吧,思路其实非常简单

  1. 写一个配置类
  2. 将该配置类放到资源文件夹中的META-INF/spring.factories

先来创立一个我的项目

1. 创立spring-boot-starter-demo我的项目并编写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.3.5.RELEASE</version>        <relativePath/> <!-- lookup parent from repository -->    </parent>    <groupId>cn.zijiancode</groupId>    <artifactId>spring-boot-starter-demo</artifactId>    <version>1.0.0-SNAPSHOT</version>    <packaging>pom</packaging>    <properties>        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>        <java.version>1.8</java.version>    </properties>    <modules>        <!-- 自定义starter -->        <module>spring-boot-starter-demo-starter</module>        <!-- 用于测试自定义starter-->        <module>spring-boot-starter-demo-sample</module>    </modules></project>

2. 创立子模块spring-boot-starter-demo-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">    <modelVersion>4.0.0</modelVersion>    <parent>        <groupId>cn.zijiancode</groupId>        <artifactId>spring-boot-starter-demo</artifactId>        <version>1.0.0-SNAPSHOT</version>    </parent>    <artifactId>spring-boot-starter-demo-starter</artifactId>    <version>1.0.0-SNAPSHOT</version>    <dependencies>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter</artifactId>        </dependency>    </dependencies></project>

3. 创立测试用模块spring-boot-starter-demo-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">    <modelVersion>4.0.0</modelVersion>    <parent>        <groupId>cn.zijiancode</groupId>        <artifactId>spring-boot-starter-demo</artifactId>        <version>1.0.0-SNAPSHOT</version>    </parent>    <artifactId>spring-boot-starter-demo-sample</artifactId>    <version>1.0.0-SNAPSHOT</version>    <dependencies>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter</artifactId>        </dependency>        <!-- 自定义starter-->        <dependency>            <groupId>cn.zijiancode</groupId>            <artifactId>spring-boot-starter-demo-starter</artifactId>            <version>1.0.0-SNAPSHOT</version>        </dependency>    </dependencies></project>

我的项目构造如下:

spring-boot-starter-demo-starter: 咱们本次的配角,自定义starter

spring-boot-starter-demo-sample: 测试模块,用于测试starter是否失效

4. 编写starter中的代码

编写一个handler,用于做注入测试

public class DemoHandler {    public DemoHandler(){        System.out.println("demo handler init!!");    }}
不须要加任何注解,因为等下应用@Bean的形式注入

编写主动配置类

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

主动配置类同样也能够不须要加任何注解,因为它实质上是应用@Import导入的

当然,如果不加@Configuration注解的话在特定的场景其实会引发一个小小的问题

这个小问题阿鉴决定卖个关子,放到下期和大家聊一聊,很快的,就这两天(其实是因为说起来还是有些内容的)

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

编写配置

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

5. 在测试模块中编写测试类

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

6. 启动我的项目查看后果

demo handler胜利的被主动配置类注入了

也就是说,咱们的starter失效啦~

我晓得,到这个时候,必定有小伙伴说:就这?

阿鉴:的确,就这,哈哈,一个广泛的应用形式到这就完结了~

利用starter做一些额定的操作

在下面的例子中,咱们只是通过starter注入了bean,然而其实咱们能够利用这样的机制做更多的事件,比方spring-boot-starter-data-redis就在我的项目启动时与redis建设了连贯,并初始化连接池。还有咱们之前学的nacos,在我的项目启动时,将服务注册到nacos等等。

那么,这样的操作应该怎么实现呢?

其实在例子中,咱们的DemoHandler在构造方法里打印了一句demo hanlder init,这就是个小小的思路,咱们齐全能够在初始化bean时做些别的事件,当然,这样的做法并不太好,因为spring中的bean是一个接一个初始化的,如果咱们在UserService的构造方法里写调用RoleService的逻辑,很可能会因为RoleService还没初始化而报错。

在Spring中,还有一个货色叫做监听器,咱们能够利用它在做一些事件,这也是阿鉴最喜爱的一种形式。

监听器必定是对应着一系列的事件的,有个事件叫做ContextRefreshedEvent, 示意Spring的上下文刷新结束,所有的Bean都曾经初始化实现,Spring的启动流程行将完结。

试试

1. 在DemoHandler加个办法

public class DemoHandler {    public DemoHandler(){        System.out.println("demo handler init!!");    }        public void hello(){        System.out.println("hello world for demo starter!");    }}

2. 编辑监听器

public class DemoListener implements ApplicationListener<ContextRefreshedEvent> {    @Resource    private DemoHandler demoHandler;    @Override    public void onApplicationEvent(ContextRefreshedEvent event) {        demoHandler.hello();    }}

3. 将监听器注入到容器中

public class DemoAutoConfiguration {    @Bean    public DemoHandler demoHandler(){        return new DemoHandler();    }        @Bean    public DemoListener demoListener(){        return new DemoListener();    }}

4. 应用测试模块测试

测试胜利,listern已失效

小结

本文基于上一期的SpringBoot主动拆卸原理介绍了如何自定义starter,并和小伙伴们聊了下怎么利用这个机制做一些额定的事件。

这一期的内容还是比较简单的,心愿大家有所播种。

咱们下期...完了,上一期还说了要和大家聊一聊如何查看组件的源码并进行扩大,我有罪,请容许我放到下一期吧「磕头.png」,咱们下期再见~

gitee: https://gitee.com/lzj960515/s...

想要理解更多精彩内容,欢送关注公众号:程序员阿鉴,阿鉴在公众号欢送你的到来~

集体博客空间:https://zijiancode.cn/archive...