我们在使用springBoot项目的时候,经常会使用到各种名字为***-starter的Jar包
例如mybatis-spring-boot-starter,shiro-spring-boot-web-starter等等。
在使用这些服务时,我们感叹其神奇,只需简单几行配置便可以享受其带来的种种便利,那么这种服务是怎么写的呢?
今天我们从零来搭建一个这样的项目,来体会一下他的工作原理
其实starter的基本组成就是一个简单的springmvc项目,通过一系列的配置和注解,从而实现自动装配的神奇。
1:首先我们先创建一个基础springboot项目,起名my-starter
2:修改pom文件
首先我们先删除对于springboot的依赖
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.6.RELEASE</version> <relativePath/> <!-- lookup parent from repository --></parent>复制代码
然后再在dependencyManagement 标签下添加与上面删除的依赖相同版本的spring-boot-dependencies依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.1.6.RELEASE</version> <type>pom</type> <scope>import</scope></dependency>复制代码
那么经过我们修改过后的pom文件 应该为:
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" 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"> <modelVersion>4.0.0</modelVersion> <groupId>org.demo</groupId> <artifactId>my-starter</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>my-starter</name> <description>Demo project for Spring Boot</description> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.1.6.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build></project>复制代码
3:添加依赖
在上篇文章中,我们讲解了@SpringBootApplication,其中我们说到了一个注解@ConditionalOnClass
回顾一下他的作用:表示必须存在指定类,否则不解析该注解修饰的配置类。
那么我们借助他来实现自动装配的功能。他处于spring-boot-autoconfigure包下,所以我们添加依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId></dependency>复制代码
创建MyStarterProperties.java
package org.demo.mystarter; import org.springframework.boot.context.properties.ConfigurationProperties; @ConfigurationProperties(prefix = "my-starter") public class MyStarterProperties { private String name = "chuchen"; private String projectName = "my-starter"; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getProjectName() { return projectName; } public void setProjectName(String projectName) { this.projectName = projectName; } }复制代码
其中@ConfigurationProperties(prefix = "my-starter")的作用是将配置数据绑定到对象上
将来我们使用时,就是:
my-starter.name=*** my-starter.project-name=***复制代码
其中的属性我们可以设置默认值,也可以不设置,如果设置默认值,那么在使用时就可以不配置,反之则需要配置
创建MyStarterService.java
package org.demo.mystarter; public class MyStarterService { private String name; private String projectName; public String getMyStarterMsg(){ return "author is " + name + ",project_name is " + projectName; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getProjectName() { return projectName; } public void setProjectName(String projectName) { this.projectName = projectName; } }复制代码
package org.demo.mystarter; 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.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration @EnableConfigurationProperties(MyStarterProperties.class) @ConditionalOnClass(MyStarterService.class) public class MyStarterAutoConfiguration { @Autowired private MyStarterProperties myStarterProperties; @Bean @ConditionalOnMissingBean(MyStarterService.class) MyStarterService myStarterService() { MyStarterService myStarterService = new MyStarterService(); myStarterService.setName(myStarterProperties.getName()); myStarterService.setProjectName(myStarterProperties.getProjectName()); return myStarterService; } }复制代码
@EnableConfigurationProperties和@ConditionalOnClass上篇文章已经说过了
@ConditionalOnMissingBean的作用为仅当 BeanFactory 中不包含指定的 bean class 时条件创建bean
大家回想一下在@SpringBootApplication中,除了以上这些文件以外,还有一个很重要的文件是什么?
是META-INF目录下的spring.factories文件
在resources文件夹下创建 META-INF→spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration= org.demo.mystarter.MyStarterAutoConfiguration复制代码
选择项目,点击右侧的maven,然后选择Lifecycle下的install。
出现如下图提示为添加成功
1:再次创建一个springboot项目,pom文件中引入我们刚刚打包好的依赖
<dependency> <groupId>org.demo</groupId> <artifactId>my-starter</artifactId> <version>0.0.1-SNAPSHOT</version></dependency>复制代码
2:创建controller
package com.chuchen.teststarter; import org.demo.mystarter.MyStarterService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class TestContrsoller { @Autowired private MyStarterService myStarterService; @GetMapping("/test") public String test(){ return myStarterService.getMyStarterMsg(); } }复制代码
3:浏览器访问http://localhost:8080/test
4:修改配置文件
打开application.properties
my-starter.name=beany my-starter.project-name=testStarter复制代码
再次访问
我的关于springboot系列文章:
SpringBoot系列教程