SpringBoot源码解析-自定义Starter
在SpringBoot学习的过程中,每当我们需要某个现有框架的功能时,都是通过引入对应的Starter,然后由SpringBoot帮我们完成自动装配。说白了,Starter就是个外部项目,就像项目A需要调用项目B,除了通过外部调用方式(比如远程调用),还可以直接内部集成B,直接本地调用。只是在SpringBoot项目中,需要遵循SpringBoot的规范而已。
Starter命名规范
Spring官方定义的Starter格式:
spring-boot-starter-{name}
非官方(自定义)定义的Starter格式:
{name}-spring-boot-starter
实现自定义Starter
需求
创建一个Starter,根据配置文件配置的name值,返回"Hello"+name。
创建Starter项目
创建一个名为javafamily-spring-boot-starter的SpringBoot项目
1.引入依赖
注意:spring-boot-configuration-processor并非加载xml或者properties配置啥的,该依赖是为了给自定义的配置类生成元数据信息的,在yml等配置文件中,比如server.port是可以直接点进去到配置类中的,如果没有该依赖,在配置文件直接书写是没有提示的,但是不影响项目运行。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency>// 为简化开发引入 非必须<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency>123456789101112复制代码类型:[java]
2.编写一个JavaFamilyService类
import lombok.AllArgsConstructor;@AllArgsConstructorpublic class JavaFamilyService { private String name; public String family() { return "Hello " + name; } }123456789101112复制代码类型:[java]
该类用于处理核心业务,这里的name由外部传入,family方法返回拼接后的字符串。
3.定义配置属性封装类
import lombok.Data;import org.springframework.boot.context.properties.ConfigurationProperties;@Data// 读取配置文件中以java.family为前缀的配置@ConfigurationProperties(prefix = "java.family")public class JavaFamilyServiceProperties { private String name; }12345678910复制代码类型:[java]
4.定义自动配置类
import com.javafamily.service.JavaFamilyService;import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;import org.springframework.boot.context.properties.EnableConfigurationProperties;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import javax.annotation.Resource;@Configuration// 当给定的类名在类路径上存在,则实例化当前Bean@ConditionalOnClass(JavaFamilyService.class)// 让使用@ConfigurationProperties注解的类生效,并且将该类注入到 IOC 容器中@EnableConfigurationProperties(JavaFamilyServiceProperties.class)public class JavaFamilyServiceAutoConfiguration { @Resource private JavaFamilyServiceProperties javaFamilyServiceProperties; @Bean // 被@ConditionalOnMissingBean注解修饰的同类型的Bean只能注册一个 注册多个时会报错 @ConditionalOnMissingBean public JavaFamilyService javaFamilyService() { // 传入从配置文件加载到的name属性 return new JavaFamilyService(javaFamilyServiceProperties.getName()); } }123456789101112131415161718192021222324252627复制代码类型:[java]
5.创建spring.factories文件
在resources文件夹下创建META-INF文件夹,在META-INF文件夹下创建spring.factories文件。
org.springframework.boot.autoconfigure.EnableAutoConfiguration= com.javafamily.config.JavaFamilyServiceAutoConfiguration12复制代码类型:[java]
这块内容在前面的源码中讲过,就是通过SPI技术实现我们的自动装配。
整体效果图如下:
6.引入自定义Starter
创建一个任意的SpringBoot工程,引入javafamily-spring-boot-starter依赖。
<dependency> <groupId>com.javafamily</groupId> <artifactId>javafamily-spring-boot-starter</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency>12345复制代码类型:[java]
在application.yml添加java.family.name配置,将值设置为JavaFamily。
创建HelloController,注入JavaFamilyService测试效果。
import com.javafamily.service.JavaFamilyService;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;@RestControllerpublic class HelloController { @Resource private JavaFamilyService javaFamilyService; @GetMapping("/test") public String test() { return javaFamilyService.family(); } }12345678910111213141516复制代码类型:[java]
访问localhost:8080/test查看效果。
至此,自定义Starter入门就完成了,相信大家看完本篇文章,对Starter会有更深入的理解,我们下期再见。