tulip notes
首页
  • 学习笔记

    • 《Vue》
  • 踩坑日记

    • JavaScript
  • MQ
  • Nginx
  • IdentityServer
  • Redis
  • Linux
  • Java
  • SpringBoot
  • SpringCloud
  • MySql
  • docker
  • 算法与设计模式
  • 踩坑与提升
  • Git
  • GitHub技巧
  • Mac
  • 网络
  • 项目构建合集
  • 一些技巧
  • 面试
  • 一些杂货
  • 友情链接
  • 项目发布
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Star-Lord

希望一天成为大师的学徒
首页
  • 学习笔记

    • 《Vue》
  • 踩坑日记

    • JavaScript
  • MQ
  • Nginx
  • IdentityServer
  • Redis
  • Linux
  • Java
  • SpringBoot
  • SpringCloud
  • MySql
  • docker
  • 算法与设计模式
  • 踩坑与提升
  • Git
  • GitHub技巧
  • Mac
  • 网络
  • 项目构建合集
  • 一些技巧
  • 面试
  • 一些杂货
  • 友情链接
  • 项目发布
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 探索SpringBoot

    • 初步认识SpringBoot
    • 自定义starter
      • 为什么要自定义starter
      • 探究starter
        • 准备
      • 命名规则
      • 实现
        • 1.创建项目并引入对应架包
        • 2 编写自己需要的代码
        • 3 配置文件的编写
      • 使用自定义starter
        • 引入自定义的starter
    • 一些常用注解
    • 自动装配
    • spring中开启事务
    • Spring中事务的属性
    • SpringBoot启动流程
    • Spring中Bean的创建跟循环依赖
    • IOC的实现机制是什么
  • 常用功能实现

  • Security认证授权

  • 扩展

  • 实战与注意事项

  • 其它

  • 《SpringBoot》笔记
  • 探索SpringBoot
EffectTang
2023-09-21
目录

自定义starter

# 自定义starter

# 为什么要自定义starter

Starter的作用是简化依赖管理和自动配置,让用户只需引入一个依赖就能使用特定功能。

虽然 Spring Boot 已经提供了很多常用的 starter,但是有些特殊的需求可能并没有被满足。这时候,开发者就可以自定义自己的 starter 来满足这些特殊需求。以下是一些可能需要自定义 starter 的情况:

  1. 整合第三方库:有时候,我们需要整合一些第三方的库或者框架到 Spring 应用中。这时候,我们可以自定义一个 starter,将这个第三方库封装成一个 bean,然后在应用中使用。
  2. 优化常用配置:Spring Boot 虽然提供了很多默认的配置,但是有些情况下,我们需要对一些常用的配置进行优化。这时候,我们可以自定义一个 starter,对这些常用的配置进行封装和优化。
  3. 提供特殊功能:有时候,我们需要提供一些特殊的功能,例如日志收集、性能监控等。这时候,我们可以自定义一个 starter,将这些特殊的功能封装成一个 bean,然后在应用中使用。
  4. 简化配置:有时候,我们需要使用一些复杂的配置来启动 Spring 应用。这时候,我们可以自定义一个 starter,将这些复杂的配置封装成一个简单的配置方式,然后在应用中使用。

总的来说,自定义一个 starter 可以帮助我们简化应用的配置和开发过程,提高开发效率和应用性能。

# 探究starter

怎么编写一个自定义的starter,最好的方法,就是照着现有的starter研究一遍,然后依葫芦画瓢去实现。一开始功能可以简单一些,重点在于弄清流程是怎么样的。

通常SpringBoot项目中引入了很多很多的starter,那项目是如何将其配置成Bean的呢?

一切的关键要从启动类上的注解*@SpringBootApplication*说起。点开它你会发现,它是多个注解的组合,

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication{
  // .....
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

其中需要关注的是@EnableAutoConfiguration,字面意思就是允许自动装配。那自动装配咱们继续-点开看。

@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
  // ...
}
1
2
3
4
5
  • @AutoConfigurationPackage 主要是为了确定哪个包下的组件会被Spring Boot自动扫描和注册。
  • @Import({AutoConfigurationImportSelector.class}) 则是为了触发Spring Boot的自动配置过程,根据项目的依赖情况自动引入必要的配置类,从而简化开发者的工作量,使得项目可以“开箱即用”。也就是将pom坐标中,别人写好的starter注入到spring容器中。

我们引入pom坐标后,之所以能使用starter,通过bean的方式,就是靠的它,那我们继续看它——AutoConfigurationImportSelector.class.

AutoConfigurationImportSelector 类中的 getCandidateConfigurations 方法是 Spring Boot 自动配置机制的核心部分之一。它负责从项目的类路径中加载所有可能的自动配置类,这些配置类通常定义在 META-INF/spring.factories 文件中。

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
        List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
        Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
        return configurations;
    }
1
2
3
4
5

AutoConfigurationImportSelector 类中的 getCandidateConfigurations 方法是 Spring Boot 自动配置机制的核心部分之一。它负责从项目的类路径中加载所有可能的自动配置类,这些配置类通常定义在 META-INF/spring.factories 文件中。

AutoConfigurationImportSelector 是 Spring Boot 自动配置机制的关键部分,它的工作流程包括以下几个方面:

  1. 发现自动配置类:通过 getCandidateConfigurations 方法从所有依赖的 META-INF/spring.factories 文件中读取自动配置类的名字列表。这些自动配置类通常位于各个 starter 库中,并且它们被设计为在满足特定条件时自动配置相关的组件。
  2. 条件评估:虽然 getCandidateConfigurations 方法本身不执行条件评估,但它返回的自动配置类将会由 Spring Boot 进行进一步处理。Spring Boot 使用条件注解(如 @ConditionalOnClass, @ConditionalOnMissingBean, @ConditionalOnProperty 等)来决定哪些自动配置类应该被真正加载到应用上下文中。只有当这些条件都满足时,相应的自动配置类才会生效。
  3. 注册 Bean:一旦某个自动配置类被确定要加载,它就会像普通的 Spring 配置类一样工作,负责注册所需的 Bean 到 Spring 应用上下文中。这可能包括创建并配置数据源、设置 MVC 视图解析器、配置安全策略等。

然后,方法中的 SpringFactoriesLoader,有一个属性FACTORIES_RESOURCE_LOCATION,

public final class SpringFactoriesLoader {
    public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
    private static final Log logger = LogFactory.getLog(SpringFactoriesLoader.class);
    static final Map<ClassLoader, Map<String, List<String>>> cache = new ConcurrentReferenceHashMap();
// ....
}
1
2
3
4
5
6

SpringFactoriesLoader 类在 Spring Boot 中扮演了一个非常重要的角色,它负责从 META-INF/spring.factories 文件中加载配置类,并且这些配置类通常用于实现自动配置和扩展点。

换句话说,它是从类路径下的这个文件中,去找寻该类,并尝试为其实现自动配置。

按照这个思路,我们要定义一个starter也应该有一个META-INF/spring.factories文件,且其中有自动配置类的-全路径类名。

# 准备

Starter的核心概念

  • 自动配置模块:包含@Configuration类、条件注解和配置属性绑定。
  • Starter模块:一个空的Maven模块,仅用于聚合依赖(依赖自动配置模块和第三方库)

引入对应依赖

<!-- your-starter-autoconfigure/pom.xml -->
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-autoconfigure</artifactId>
        <version>3.1.5</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <version>3.1.5</version>
        <optional>true</optional>
    </dependency>
</dependencies>
1
2
3
4
5
6
7
8
9
10
11
12
13
14

配置类的编写

// YourServiceProperties.java
@ConfigurationProperties(prefix = "your.service")
public class YourServiceProperties {
    private String apiKey;
    private int timeout = 5000;

    // Getters and Setters
}
1
2
3
4
5
6
7
8

@ConfigurationProperties

作用:跟 对应的配置文件 yaml进行数据绑定

定义自动配置类

// YourServiceAutoConfiguration.java
@Configuration
@ConditionalOnClass(YourService.class) // 当类路径存在YourService时生效
@EnableConfigurationProperties(YourServiceProperties.class)
public class YourServiceAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean // 当容器中没有YourService时创建Bean
    public YourService yourService(YourServiceProperties properties) {
        return new YourService(properties.getApiKey(), properties.getTimeout());
    }
}
1
2
3
4
5
6
7
8
9
10
11
12

写入配置文件信息

在src/main/resources/META-INF/spring/目录下创建文件spring.factories:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.autoconfigure.YourServiceAutoConfiguration
1
2

# 命名规则

SpringBoot官方提供的starter以spring-boot-starter-xxx的方式命名

官方建议自定义的starter使用xxx-spring-boot-starter的方式命名。用以区分官方与三方。

# 实现

自定义starter,大致可以分为如下几步:

  1. 创建项目,在pom文件中引入autoconfigure包
  2. 编写自己的代码
  3. 进行 META-INF/spring.factories 配置文件的编写,使得项目启动能加载指定的自动配置类

第三点,SpringBoot 2.7之后的有改动

# 1.创建项目并引入对应架包

在创建项目,设置artifactId时,记得遵守上文说到的命名规则。

引入自动配置包

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
1
2
3
4

# 2 编写自己需要的代码

以下是简单的一个示例:

  • service包中的类:
public class HelloService {

    @Autowired
    HelloProperties helloProperties;

    public String sayHello(String name){
        return  name + helloProperties.getName();
    }
}
1
2
3
4
5
6
7
8
9

之所以不将其(HelloService)注入到容器中,是为了实现按需使用。可能你自定义的starter中有很多bean对象,但开发中可能不是每个都需要,于是我们将使用权交给使用者,关于它的配置我们交给自动配置类

  • Bean包中的配置类
@ConfigurationProperties(prefix = "man.sugar")
public class HelloProperties {

    @Value("loo")
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

与配置文件中的值进行绑定。

  • Config包中的自动配置类
@Configuration
@EnableConfigurationProperties(HelloProperties.class)
public class HelloServiceAutoConfiguration {

    @Bean
 // @ConditionalOnMissingBean ... 
    public HelloService helloService(){
        return new HelloService();
    }
}
1
2
3
4
5
6
7
8
9
10

在创建bean组件的时候,可以按照自己的需求,通过@ConditionalXXxx定义一些条件,实现根据条件创建。条件可以放在类上,也可以放在方法上。

使用@EnableConfigurationProperties(HelloProperties.class) 会将HelloProperties放到容器中,因为HelloService的创建,需要该属性

  • 配置文件application.properties
man.sugar.name = Drink plenty of water 
1

到此自定义starter基本实现完成,但还差最重要的一步。因为此时的自动配置类不会生效。根据自动配置原理可以了解到,我们还需要在配置META-INF/spring.factories文件中进行配置,这样才能使得项目在启动的时候加载指定的自动配置类。

# 3 配置文件的编写

在项目的资源文件中创建META-INF/spring.factories,并对spring.factories进行编写,将需要自动加载的类写入配置

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.sugar.demo1.config.HelloServiceAutoConfiguration
1
2
3

配置自己的自动配置类路径

提示

springboot在2.7及以后版本不推荐使用/META-INF/spring.factories文件,并且在Spring Boot 3将移除对/META-INF/spring.factories的支持。

新的写法是/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.sugar.demo1.config.HelloServiceAutoConfiguration
1
2

# 使用自定义starter

在将之前项目通过maven进行install后,即可开始使用。

# 引入自定义的starter

 <dependency>
   <groupId>com.sugar.demo1</groupId>
   <artifactId>use-custom-starter</artifactId>
   <version>0.0.1-SNAPSHOT</version>
</dependency>
1
2
3
4
5

成功引入后,即可在项目中使用对应的bean对象

@RestController
public class HepController {

    @Autowired
    HelloService helloService;

    @GetMapping("/hello")
    public String hello(){
        String sugar = helloService.sayHello("sugar");
        return "sth = "+sugar;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12

同时你也可以在配置文件中对helloService中的HelloProperties的值进行更改

man.sugar.name=like water
1
上次更新: 2025/04/23, 16:23:16
初步认识SpringBoot
一些常用注解

← 初步认识SpringBoot 一些常用注解→

最近更新
01
面向切面跟自定义注解的结合
05-22
02
时间跟其他数据的序列化
05-19
03
数据加密与安全
05-17
更多文章>
Theme by Vdoing | Copyright © 2023-2025 EffectTang
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式