SpringBoot的基础介绍
SpringBoot是由Pivotal团队提出的全新框架,其出现的目的主要是为了简化Spring应用的搭建;
在使用SpringBoot之前,我们在使用Spring搭建项目时通常需要写一些xml对项目进行配置,通常还需要手动添加maven配置,框架搭建难度大,时间成本高;在对项目进行本地调试或者线上部署的时候,通常需要将项目编译成war包,然后部署到tomcat中;
SpringBoot的出现,改变了这种状况,SpringBoot具有自动装配的特性,另外SpringBoot内嵌容器,使我们免于安装Tomcat,直接通过运行main方法进行启动,非常方便;
提起SpringBoot的自动装配,我们不免想起在pom.xml中引用的spring-boot-starter-data-redis,spring-boot-starter-data-mongodb等,对于之前项目一直使用Spring的我来说,感觉非常的神奇,一个简单的配置竟然让spring整合redis,mongodb如此简单,所以我今天花了一些时间去学习了starter相关的知识,学习如何自定义starter;
自定义starter
首先我们需要创建一个Configuration类,这个类主要是为了配置参数,以及自动配置对外提供的功能;
@Configuration
@EnableConfigurationProperties(CourseProperties.class)
public class CourseAutoConfigure {
@Bean
public CourseClient courseClient(CourseProperties courseProperties){
return new CourseClient(courseProperties);
}
}
复制代码
上面代码表示我们对外提供一个CourseClient的对象,然后我们可以通过这个对象去实现一些功能,因为我们这里只是为了学习自定义starter的创建方式,所以我们肯定使用一些简单的demo去理解这个过程。
public class CourseClient {
private CourseProperties courseProperties;
public CourseClient(){
}
public CourseClient(CourseProperties courseProperties){
this.courseProperties = courseProperties;
}
public String getName(){
return courseProperties.getName();
}
}
复制代码
可以看到,我们对外暴露的功能就是我们CourseProperties对象的课程名称;
@Data
@ConfigurationProperties(prefix = "spring.course")
public class CourseProperties {
private String name;
}
复制代码
细心的小伙伴平时在使用SpringBoot的时候肯定注意到我们在yaml中或则properties写一些配置的时候idea总是会给我们一些提示,其实这个实现很简单啦,我们只需要在pom.xml中引入
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
复制代码
它的作用就是会解析我们的Properties类,然后根据属性,注释,返回值等,自动解析生成一个spring-configuration-metadata.json,帮助我们理解我们要做的功能,配置的意义;
starter集成应用
我们的功能写好了,那么我们怎么集成到我们的项目当中呢?这里分为两种方式,一种是主动生效,一种是被动生效;
主动生效是指:需要我们主动声明启用该starter才能生效,这里主要是用到@Import注解,将该注解标记到自定义的@Enable注解上;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({CourseAutoConfigure.class})
public @interface EnableCourseClient {
}
复制代码
被动生效是指:将starter组件集成到SpringBoot应用时就已经被应用可用。实现方面类似java的spi机制,新建META-INF/spring.factories写入
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.learn.springboot.starter.autoconfigure.CourseAutoConfigure
复制代码
集成应用测试
我们新建一个SpringBoot web应用,首先我们使用主动生效的方式进行测试的
@EnableCourseClient
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
复制代码
@RestController
public class CourseController {
@Autowired
private CourseClient courseClient;
@GetMapping("courseName")
public String getCourseName(){
return courseClient.getName();
}
}
复制代码
在application.properties中配置
spring.course.name=python
复制代码
浏览器访问:localhost:8080/courseName 可以正常返回python
如果我们去掉@EnableCourseClient注解,启动的时候会报错
2021-05-08 09:51:53.924 INFO 58146 --- [ main] ConditionEvaluationReportLoggingListener :
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2021-05-08 09:51:53.944 ERROR 58146 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
Field courseClient in com.learning.springboot.controller.CourseController required a bean of type 'com.learn.springboot.starter.autoconfigure.CourseClient' that could not be found.
The injection point has the following annotations:
- @org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'com.learn.springboot.starter.autoconfigure.CourseClient' in your configuration.
复制代码
下面我们使用被动生效的方式进行测试,去掉@EnableCourseClient注解,同时在META-INF/spring.factories写入
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.learn.springboot.starter.autoconfigure.CourseAutoConfigure
复制代码
浏览器访问:localhost:8080/courseName 可以正常返回python
其他补充
有时候我们想通过配置,动态控制starter是否可用,这个时候我们可以通过@Condition注解实现,比如
@Bean
@ConditionalOnProperty(prefix = "spring.course", value = "enabled", havingValue = "true")
public CourseClient courseClient(CourseProperties courseProperties){
return new CourseClient(courseProperties);
}
复制代码
配置如下:
spring.course.name=python
spring.course.enabled=true
复制代码
如果将true改为false,发现启动同样也会出现报错
学习过程中遇见的问题
在学习过程中,发现既不使用主动生效也不使用被动生效,starter都可以正常使用,主要因为starter项目的包名取得和应用包名一样,更改包名后恢复正常。