SpringBoot自定义starter

上期讲到,关于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



    4.0.0

    
        org.springframework.boot
        spring-boot-starter-parent
        2.3.5.RELEASE
         
    

    cn.zijiancode
    spring-boot-starter-demo
    1.0.0-SNAPSHOT
    pom

    
        UTF-8
        UTF-8
        1.8
    

    
        
        spring-boot-starter-demo-starter
        
        spring-boot-starter-demo-sample
    

2. 创建子模块spring-boot-starter-demo-starter



    4.0.0

    
        cn.zijiancode
        spring-boot-starter-demo
        1.0.0-SNAPSHOT
    

    spring-boot-starter-demo-starter
    1.0.0-SNAPSHOT

    
        
            org.springframework.boot
            spring-boot-starter
        
    


3. 创建测试用模块spring-boot-starter-demo-sample



    4.0.0

    
        cn.zijiancode
        spring-boot-starter-demo
        1.0.0-SNAPSHOT
    

    spring-boot-starter-demo-sample
    1.0.0-SNAPSHOT

    
        
            org.springframework.boot
            spring-boot-starter
        

        
        
            cn.zijiancode
            spring-boot-starter-demo-starter
            1.0.0-SNAPSHOT
        
    

项目结构如下:

image

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. 启动项目查看结果

image

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 {

    @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. 使用测试模块测试

image

测试成功,listern已生效

小结

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

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

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

gitee: https://gitee.com/lzj960515/spring-boot-starter-demo

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

个人博客空间:https://zijiancode.cn/archives/springbootcustomstarter

你可能感兴趣的:(SpringBoot自定义starter)