我们在使用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>
二:添加Properties配置
创建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
六:打成jar包放到本地maven仓库
选择项目,点击右侧的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系列文章: