SpringBoot学习系列(十二)------自定义starters

前言

SpringBoot的使用方便了我们的开发,究其原因,还是因为我们使用了很多的的starters,在我们导入这些starters的依赖以后,SpringBoot会帮我们注入很多的自动配置,在这里,我们可以来研究一下starters,实现自己的starters.

正文

1. WebMvcAutoConfiguration

我们查看这个类,可以发现有几个需要注意的注解:

@Configuration	//指定这个类是一个配置类
@ConditionalOnWebApplication	//所有已ConditionalOnXXX开头的,都是在满足该条件的情况下,配置才生效
@AutoConfigureAfter	//指定自动配置类的顺序
@Bean	//给容器中添加组件
@ConfigurationProperties	//根据相关的Properties属性类来绑定相关的配置
@EnableConfigurationProperties //让Properties生效,并加入容器中

//要想在启动的时候自动配置类能被加载,还必须要将配置类放在META/INF/spring.factories中指定
//如下指定:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
2. SpringBoot默认的starters的模式
  • 启动器用来做依赖导入
  • 额外写一个自动配置的模块
  • 启动器依赖自动配置模块,在使用的时候只需要引入启动器(starter)即可
3. 实现自定义启动器
  • 创建一个空的工程模块,工程名为:spring-boot-starter
  • 在该工程下创建2个模块,一个作为启动器,一个作为自动配置模块:

springboot 实体类命名_spring

springboot 实体类命名_自定义starter_02

springboot 实体类命名_springboot 实体类命名_03

springboot 实体类命名_starter_04

springboot 实体类命名_自定义starter_05

springboot 实体类命名_SpringBoot自动配置_06

  • 我们在starter中引入starter-autoconfigurer:
<!--引入自动配置模块-->
    <dependencies>
        <dependency>
            <groupId>com.xiaojian.starter</groupId>
            <artifactId>xiaojian-spring-boot-starter-autoconfigurer</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>
  • 创建一个绑定配置文件属性的配置类,用@ConfigurationProperties来标注:
package com.xiaojian.starter;

import org.springframework.boot.context.properties.ConfigurationProperties;

/**
 * ConfigurationProperties注解表示将配置文件中前缀为xiaojian.hello的属性绑定到该类的属性中
 */
@ConfigurationProperties(prefix = "xiaojian.hello")
public class HelloProperties {

    private String prefix;

    private String suffix;

    public String getPrefix() {
        return prefix;
    }

    public void setPrefix(String prefix) {
        this.prefix = prefix;
    }

    public String getSuffix() {
        return suffix;
    }

    public void setSuffix(String suffix) {
        this.suffix = suffix;
    }
}
  • 接着我们定义一个service作为自动配置后主动执行的组件,在这个service中我们可以加入上一步中定义的HelloProperties,要注意,要想这个helloProperties被别的模块使用,需要加入get/set方法:
package com.xiaojian.starter;

public class HelloService {

    HelloProperties helloProperties;

    public HelloProperties getHelloProperties() {
        return helloProperties;
    }

    public void setHelloProperties(HelloProperties helloProperties) {
        this.helloProperties = helloProperties;
    }

    public String sayHello(String name) {
        return helloProperties.getPrefix() + "-"
                + name + "-" + helloProperties.getSuffix();
    }
}
//这样,我们在调用sayHello方法的时候,会根绝配置文件中配置的前缀和后缀2个属性,加上我们传入的name,返回给调用者
  • 编写自动配置类:
package com.xiaojian.starter;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * helloservice组件的自动配置类
 */
@Configuration  //指定这是一个配置类
@ConditionalOnWebApplication    //指定只有是web应用时,改配置才生效
@EnableConfigurationProperties(HelloProperties.class)   //激活和属性文件绑定的类
public class HelloServiceAutoConfiguration {

    @Autowired
    HelloProperties helloProperties;

    @Bean
    public HelloService helloService() {
        HelloService helloService = new HelloService();
        //在这里要把配置文件中的properties类设置到service中
        helloService.setHelloProperties(helloProperties);
        return helloService;
    }

}
  • 要在classpath下创建一个META-INF文件夹,并在该文件夹下创建文件spring.factories,在文件中指定自定义自动配置类的全路径:

至此,我们自定义的starter全部完成,我们一起来看一下我们做了什么:

  1. 我们编写了一个自动配置类HelloServiceAutoConfiguration,注解@Configuration指定了它是一个配置类,注解@ConditionalOnWebApplication限定它只有在web环境中生效,注解@EnableConfigurationProperties(HelloProperties.class)标注它在启用时,会激活属性类HelloProperties,并且绑定到自身.
  2. HelloServiceAutoConfiguration中我们注入了一个bean,并将配置文件中以xiaojian.hello开头的属性类设置到helloservice中.
  3. spring.factories中,我们将HelloServiceAutoConfiguration配置进去,这样在启动的时候,我们自定义的自动配置类就能加载了.
4. 测试自定的starter

在前面我们自定义好了自己的starter,现在我们可以来创建一个工程测试一下:

springboot 实体类命名_spring_07

springboot 实体类命名_自定义starter_08

我们创建好工程以后,在pom.xml文件中引入我们自定义的模块:

<!--引入自定义的starter-->
        <dependency>
            <groupId>com.xiaojian</groupId>
            <artifactId>xiaojian-spring-boot-starter</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

在工程中编写一个测试的controller:

@RestController
public class HelloController {

    @Autowired
    private HelloService helloService;

    @GetMapping("/hello")
    public String hello(){
        return helloService.sayHello("张三");
    }
}

在该工程的配置文件中定义前缀和后缀:

xiaojian.hello.prefix=亲爱的
xiaojian.hello.suffix=你好

现在我们访问http://localhost:8080/hello来测试:

springboot 实体类命名_SpringBoot自动配置_09

可以看到我们自定义的配置起作用了.

总结

自定义自动配置模块,能帮助我们理解SpringBoot的starter实现过程,在技术的学习上,我们不仅要会用,也要对每一门技术的由来和原理有一定的认识.