关于java:SpringBoot自定义starter

37次阅读

共计 5494 个字符,预计需要花费 14 分钟才能阅读完成。

上期讲到,对于 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. 在测试模块中编写测试类

@SpringBootApplication
public 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…

正文完
 0