Spring Boot Starter是什么? 依赖管理是任何复杂项目的关键部分。以手动的方式来实现依赖管理不太现实,你得花更多时间,同时你在项目的其他重要方面能付出的时间就会变得越少。
Spring Boot starter 就是为了解决这个问题而诞生的。Starter POM 是一组方便的依赖描述符,您可以将其包含在应用程序中。您可以获得所需的所有 Spring 和相关技术的一站式服务,无需通过示例代码搜索和复制粘贴依赖。
揭开Spring Boot自动装配的神秘面纱 Auto Configuration 类 当Spring Boot启动时,它会在类路径中查找名为spring.factories
的文件。该文件位于META-INF
目录中。让我们看一下spring-boot-autoconfigure
项目中这个文件的片段:
1 2 3 4 5 org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\ org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\ org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\ org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
此文件定义了一些Spring Boot将尝试运行的自动装配类。例如以上的代码片段,Spring Boot将尝试运行RabbitMQ,Cassandra,MongoDB和Hibernate的所有配置类。这些类是否实际运行将取决于类路径上是否存在依赖类。例如,如果在类路径中找到MongoDB
的类,则将运行MongoAutoConfiguration
,并初始化所有与mongo相关的bean。此条件初始化由@ConditionalOnClass
注释启用。让我们看一下MongoAutoConfiguration
类的代码片段,看看它的用法:
1 2 3 4 5 6 7 @Configuration @ConditionalOnClass(MongoClient.class) @EnableConfigurationProperties(MongoProperties.class) @ConditionalOnMissingBean(type = "org.springframework.data.mongodb.MongoDbFactory") public class MongoAutoConfiguration { }
如果存在MongoClient
类,将运行该自动装配类初始化MongoClient
相关bean。
在application.properties
自定义配置 Spring Boot使用一些预先配置的默认值初始化bean。要覆盖这些默认值,我们通常会在application.properties
文件中使用某个特定名称声明它们。Spring Boot容器会自动获取这些属性。 在MongoAutoConfiguration
的代码片段中,@EnableConfigurationProperties(MongoProperties.class)
表示,使用MongoProperties
类来声明自定义属性:
1 2 3 4 5 6 7 @ConfigurationProperties(prefix = "spring.data.mongodb") public class MongoProperties { private String host; }
@ConfigurationProperties(prefix = "spring.data.mongodb")
定义了配置前缀,我们可以在application.properties
这样来使用它:
1 spring.data.mongodb.host = localhost
这样,初始化的时候,localhost
将被注入到host
属性中
自定义Spring Boot Starter
Spring Boot自动装配虽然神奇,但是编写起来却异常简单,我们只需要按部就班的执行以下两个流程:
编写属性容器*Properties
,并编写对应的*AutoConfiguration
自动装配类
一个pom文件,用于定义引入库和自动装配类的依赖项
概念解析 用于*Properties
的注解
@ConfigurationProperties(prefix = "spring.data.mongodb")
:用于指定配置前缀
用于*AutoConfiguration
的注解
@Configuration:标记为配置类,由Spring容器初始化并接管
@EnableConfigurationProperties:注入配置属性容器
@ConditionalOnBean:条件装配
重点说下条件装配,以@ConditionalOnBean
为例,当Spring容器中存在指定Bean的时候装配
1 2 3 4 5 6 7 @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @Conditional(OnBeanCondition.class) public @interface ConditionalOnBean{ }
@Conditional(OnBeanCondition.class)
指定了实现条件装配的逻辑代码
OnBeanCondition
声明如下:
1 class OnBeanCondition extends SpringBootCondition implements ConfigurationCondition {}
所以,我们自己也可以继承SpringBootCondition
并实现ConfigurationCondition
来自定义条件装配注解。
比较常用的几个条件装配注解:
@ConditionalOnBean:当Spring容器中存在指定Bean时装配
@ConditionalOnClass:当存在指定Class时装配
@ConditionalOnMissingBean:当Spring容器中不存在指定Bean时装配
@ConditionalOnMissingClass:当不存在指定Class时装配
小试牛刀
我们将自动配置模块称为greeter-spring-boot-autoconfigure
。该模块将有两个主要类,即GreeterPropertie
s,它将通过application.properties
文件和GreeterAutoConfiguartion
设置自定义属性,并为greeter库创建bean。
准备,创建假想的一个第三方工程:Greet
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 public class Greeter { private GreetingConfig greetingConfig; public Greeter (GreetingConfig greetingConfig) { this .greetingConfig = greetingConfig; } public String greet (LocalDateTime localDateTime) { String name = greetingConfig.getProperty(USER_NAME); int hourOfDay = localDateTime.getHour(); if (hourOfDay >= 5 && hourOfDay < 12 ) { return String.format("Hello %s, %s" , name, greetingConfig.get(MORNING_MESSAGE)); } else if (hourOfDay >= 12 && hourOfDay < 17 ) { return String.format("Hello %s, %s" , name, greetingConfig.get(AFTERNOON_MESSAGE)); } else if (hourOfDay >= 17 && hourOfDay < 20 ) { return String.format("Hello %s, %s" , name, greetingConfig.get(EVENING_MESSAGE)); } else { return String.format("Hello %s, %s" , name, greetingConfig.get(NIGHT_MESSAGE)); } } public String greet () { return greet(LocalDateTime.now()); } } public class GreeterConfigParams { public static final String USER_NAME = "user.name" ; public static final String MORNING_MESSAGE = "morning.message" ; public static final String AFTERNOON_MESSAGE = "afternoon.message" ; public static final String EVENING_MESSAGE = "evening.message" ; public static final String NIGHT_MESSAGE = "night.message" ; } public class GreetingConfig extends Properties { private static final long serialVersionUID = 5662570853707247891L ; }
编写Properties和AutoConfiguration:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 @ConfigurationProperties(prefix = "gcdd1993.greeter") public class GreeterProperties { private String userName; private String morningMessage; private String afternoonMessage; private String eveningMessage; private String nightMessage; } @Configuration @ConditionalOnClass(Greeter.class) @EnableConfigurationProperties(GreeterProperties.class) public class GreeterAutoConfiguration { @Autowired private GreeterProperties greeterProperties; @Bean @ConditionalOnMissingBean public GreetingConfig greeterConfig () { String userName = greeterProperties.getUserName() == null ? System.getProperty("user.name" ) : greeterProperties.getUserName(); GreetingConfig greetingConfig = new GreetingConfig(); greetingConfig.put(USER_NAME, userName); if (greeterProperties.getMorningMessage() != null ) { greetingConfig.put(MORNING_MESSAGE, greeterProperties.getMorningMessage()); } if (greeterProperties.getAfternoonMessage() != null ) { greetingConfig.put(AFTERNOON_MESSAGE, greeterProperties.getAfternoonMessage()); } if (greeterProperties.getEveningMessage() != null ) { greetingConfig.put(EVENING_MESSAGE, greeterProperties.getEveningMessage()); } if (greeterProperties.getNightMessage() != null ) { greetingConfig.put(NIGHT_MESSAGE, greeterProperties.getNightMessage()); } return greetingConfig; } @Bean @ConditionalOnMissingBean public Greeter greeter (GreetingConfig greetingConfig) { return new Greeter(greetingConfig); } }
然后在src/main/resources/META-INF
目录下创建spring.factories
文件
1 2 org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.gcdd.autoconfigure.GreeterAutoConfiguration
测试一下:
创建配置文件application.properties
:
1 2 gcdd1993.greeter.userName=gcdd1993 gcdd1993.greeter.eveningMessage=good evening
使用Greeter bean
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @SpringBootApplication public class GreeterSampleApplication implements CommandLineRunner { @Autowired private Greeter greeter; public static void main (String[] args) { SpringApplication.run(GreeterSampleApplication.class, args); } @Override public void run (String... args) throws Exception { String message = greeter.greet(); System.out.println(message); } }
执行main方法,将会输出一行:
1 Hello gcdd1993, good evening
为配置类添加提示 我们知道,在Idea中,编写配置文件的时候,有智能提示
其实这不是Idea搞的鬼,是由META-INF/spring-configuration-metadata.json
文件配置好的,Idea只是负责解析这个文件,提供我们智能化的提示信息。
想要达到这个目的很简单,添加依赖org.springframework.boot:spring-boot-configuration-processor
就行了。
Maven
1 2 3 4 5 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-configuration-processor</artifactId > <version > 2.1.6.RELEASE</version > </dependency >
Gradle
1 compile group : 'org.springframework.boot' , name: 'spring-boot-configuration-processor' , version: '2.1.6.RELEASE'
总结 以上就是Spring Boot Starter
的全部内容了,如果要发布到maven仓库,供别人使用,可以使用mvn install
打包发布至maven仓库。
👉 本文代码地址