自定义hello-spring-booter-starter
1概述
1.1 SpringBoot核心原理
springboot的核心有如下四点:
① 起步依赖
核心是依赖传递,官方集成的第三方框架,从而实现版本管理
② 自动配置管理
通过springboot自动配置管理特性将其实例化到(自定义)类中程序启动时,向Spring容器中导入很多配置,代替繁琐的xml或注入Bean。注解中加入EnableConfigurationProperties,application.yml中的所有配置文件都会指向实体类。如server.port对应的实体类ServerProperties(扫描包路径为:org.springframework.boot.autoconfigure),
@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
public class ServerProperties {
③ 运行监控管理Actuator
④ 命令行工具cli
可以使用SpringBoot快速的开发基于Spring框架的项目。由于围绕SpringBoot存在很多开箱即用的Starter依赖,使得我们在开发业务代码时能够非常方便的、不需要过多关注框架的配置,而只需要关注业务即可。
1.2 常用的几个注解说明
@Configuration:表明此类是一个配置类,将变为一个bean被spring进行管理。
@EnableConfigurationProperties:启用属性配置,将读取HelloServiceProperties里面的属性。
@ConditionalOnClass:当类路径下面有HelloServiceConfiguration此类时,自动配置。
@ConditionalOnProperty:判断指定的属性是否具备指定的值。
@ConditionalOnMissingBean:当容器中没有指定bean是,创建此bean。
@ConditionalOnBean:当容器中有指定的Bean的条件下
@ConditionalOnClass:当类路径下有指定的类的条件下
@ConditionalOnExpression:基于SpEL表达式作为判断条件
@ConditionalOnJava:基于JVM版本作为判断条件
@ConditionalOnJndi:在JNDI存在的条件下查找指定的位置
@ConditionalOnMissingBean:当容器中没有指定Bean的情况下
@ConditionalOnMissingClass:当类路径下没有指定的类的条件下
@ConditionalOnNotWebApplication:当前项目不是Web项目的条件下
@ConditionalOnProperty:指定的属性是否有指定的值
@ConditionalOnResource:类路径下是否有指定的资源
@ConditionalOnSingleCandidate:当指定的Bean在容器中只有一个,或者在有多个Bean的情况下,用来指定首选的Bean @ConditionalOnWebApplication:当前项目是Web项目的条件下
1.3 @EnableAutoC vs @ImportAutoConfiguration
使用@EnableAutoConfiguration时会扫描整个类路径下,包括依赖引入的jar包所有的自动配置类(被注解了@Configuration的类),尝试进行自动配置。比如,tomcat-embedded.jar。
而@ImportAutoConfiguration只运行在你注解中提供的配置类。
下面是一个Spring Boot入口方法中使用@ImportAutoConfiguration的列子:
@ComponentScan("path.to.your.controllers")
@ImportAutoConfiguration({
WebMvcAutoConfiguration.class,
DispatcherServletAutoConfiguration.class,
EmbeddedServletContainerAutoConfiguration.class,
ServerPropertiesAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class
})
public class App {
2自定义boot-starter
遵循springboot官方建议对于非官方的starter命名方式为xxx-spring-boot-starter,所以本工程名为hello-spring-boot-starter。
2.1实现原理
我们知道使用一个公用的starter的时候,只需要将相应的依赖添加的Maven的配置文件当中即可,免去了自己需要引用很多依赖类,并且SpringBoot会自动进行类的自动配置。那么 SpringBoot 是如何知道要实例化哪些类,并进行自动配置的呢,分如下三步骤:
1.SpringBoot 在启动时会去依赖的starter包中寻找 resources/META-INF/spring.factories 文件,然后根据文件中配置的Jar包去扫描项目所依赖的Jar包,这类似于 Java 的 SPI 机制。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.kikop.boot.HelloServiceAutoConfiguration
2.根据spring.factories配置加载AutoConfiguration类。
3.根据 @Conditional注解的条件,进行自动配置并将Bean注入Spring Context 上下文当中。我们也可以使用@ImportAutoConfiguration({HelloServiceAutoConfiguration.class}) 指定自动配置哪些类。
2.2实现步骤
2.2.1创建maven
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">
2.2.2配置文件读取类
package com.kikop.boot.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
@author kikop
@version 1.0
@project Name: hello-spring-bootstarter
@file Name: HelloServiceProperties
@desc 功能描述 配置文件读取类
对应yml配置文件总的属性,配置此注解可以自动导入application.properties配置文件中的属性
@date 2020/2/20
@time 7:33
@by IDE: IntelliJ IDEA
*/
@ConfigurationProperties(prefix = HelloServiceProperties.PREFIX,ignoreUnknownFields = true)
public class HelloServiceProperties {
public static final String PREFIX = "com.kikop.boot";
// 定义jar包中默认的配置属性:name
private String name = "hello";
// 定义jar包中默认的配置属性:hobby
private String hobby = "springboot";
// 定义jar包中默认的配置属性:place
private String place="nj";
public String getPlace() {
return place;
}
public void setPlace(String place) {
this.place = place;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getHobby() {
return hobby;
}
public void setHobby(String hobby) {
this.hobby = hobby;
}
}
2.2.3业务实体类
package com.kikop.boot.entity;
import org.springframework.util.StringUtils;
/**
@author kikop
@version 1.0
@project Name: hello-spring-bootstarter
@file Name: HelloServiceInfo
@desc 功能描述 Starter要实现的功能
已基于业务转化的包装类
@date 2020/2/20
@time 7:36
@by IDE: IntelliJ IDEA
*/
public class HelloServiceInfo {
//姓名
private String name;
//爱好(多个逗号分隔)
private String hobby;
//住址
private String place;
public String getPlace() {
return place;
}
public void setPlace(String place) {
this.place = place;
}
public String getName() {
return "name is " + name;
}
public String getHobby() {
return "hobby is " + hobby;
}
public void setName(String name) {
this.name = name;
}
public void setHobby(String hobby) {
this.hobby = hobby;
}
public String[] split(String separatorChar) {
return StringUtils.split(this.getHobby(), separatorChar);
}
@Override
public String toString() {
return "HelloServiceInfo{" +
"name='" + name + '\'' +
", hobby='" + hobby + '\'' +
", place='" + place + '\'' +
'}';
}
}
2.2.4自动配置类
package com.kikop.boot;
import com.kikop.boot.entity.HelloServiceInfo;
import com.kikop.boot.properties.HelloServiceProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
@author kikop
@version 1.0
@project Name: hello-spring-bootstarter
@file Name: HelloServiceAutoConfiguration
@desc 功能描述 自动配置类
@date 2020/2/20
@time 7:37
@by IDE: IntelliJ IDEA
*/
// 1.Configuration 表明此类是一个配置类,将变为一个bean被spring进行管理
@Configuration
// 2.当类路径下面有HelloServiceInfo此类时,自动配置
@ConditionalOnClass(HelloServiceInfo.class)
// 3.启用属性配置,将读取 HelloServiceProperties 里面的属性
@EnableConfigurationProperties(HelloServiceProperties.class)
//// 4.判断指定的属性是否具备指定的值(放类上)
//@ConditionalOnProperty(prefix = "com.kikop.boot", value = "enabled", matchIfMissing = true)
public class HelloServiceAutoConfiguration {
/**
* 注入读取的 HelloServiceProperties
*/
@Autowired
private HelloServiceProperties helloServiceProperties;
/**
* 注入Bean,已基于业务转化的包装类
* @return
*/
@Bean
@ConditionalOnMissingBean(HelloServiceInfo.class)
// 4.判断指定的属性是否具备指定的值(放Bean上)
// 当配置文件中 com.kikop.boot.enabled=true
@ConditionalOnProperty(prefix = "com.kikop.boot", value = "enabled",matchIfMissing = true)
public HelloServiceInfo helloServiceInfo() {
HelloServiceInfo helloServiceInfo=new HelloServiceInfo();
helloServiceInfo.setName(helloServiceProperties.getName());
helloServiceInfo.setHobby(helloServiceProperties.getHobby());
helloServiceInfo.setPlace(helloServiceProperties.getPlace());
return helloServiceInfo;
}
}
2.2.5spring.factories
文件位置:resorces\META-INF\spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.kikop.boot.HelloServiceAutoConfiguration
2.3测试
2.3.1加入依赖
com.kikop.boot
hello-spring-boot-starter
1.0-SNAPSHOT
org.springframework.boot
spring-boot-configuration-processor
true
2.3.2 controller
@Autowired
HelloServiceInfo helloServiceInfo;
@RequestMapping(value = "/hello")
public String hello() {
return helloServiceInfo.toString();
}
2.3.3 application.yml
com:
kikop:
boot:
enable: true
name: kikop11
hobby: tabletennis
place: nj
2.3.4调用
http://localhost:8762/hello
HelloServiceInfo{name='kikop', hobby='tabletennis', place='nj'}
参考
- Springcloud
https://spring.io/projects/spring-cloud
https://start.spring.io/
- SpringBoot启动过程分析
https://www.jianshu.com/p/603d125f21b3
- SpringBoot启动类图
https://www.processon.com/view/link/59812124e4b0de2518b32b6e
- 使用springboot自定义starter实例1
https://blog.csdn.net/qq_21150865/article/details/83504780
- 编写自己的SpringBoot-starter
https://www.cnblogs.com/yuansc/p/9088212.html