Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

实现一个简单的SpringBoot-Starter #13

Open
bitfishxyz opened this issue Aug 8, 2019 · 0 comments
Open

实现一个简单的SpringBoot-Starter #13

bitfishxyz opened this issue Aug 8, 2019 · 0 comments
Labels
SpringBoot SpringBoot

Comments

@bitfishxyz
Copy link
Member

实现一个简单的SpringBoot-Starter

我们使用 Spring Boot,基本上都是沉醉在它 Stater 的方便之中。Starter 为我们带来了众多的自动化配置,有了这些自动化配置,我们可以不费吹灰之力就能搭建一个生产级开发环境,有的小伙伴会觉得这个 Starter 好神奇呀!其实 Starter 也都是 Spring 中的基础知识点实现的,今天codeman就来带大家自己来实现一个 Starter ,慢慢揭开 Starter 的神秘面纱!

核心知识

一个starter一般包含下面的内容:

  • 一个被@ConfigurationProperties注解的配置类

    这个类用来动态的读取用户的配置信息

  • 一个开启自动配置的类

    SpringBoot将会通过这个配置类开启自动配置。
    具体的方法后面再说。然后我们一般都会给自动配置类添加一个@conditional注解,这样在符合某些条件时,开启自动配置,在某些情况下不开启自动配置。

  • 一个完成特定功能的类

    我们的starter最终还是要提供某些服务的。所以我们还要编写真正的提供服务的类,通常这个类会被注册为一个bean。

然后,如果你对我之前提到的几个注解不属性,可以看这里

https://github.com/codeman-cs/SpringBoot/wiki/An-overview-of-25-Spring-Boot-core-annotations

阅读下面的文章之前,你需要掌握这几个注解的用法。

实践

所谓的 Starter ,其实就是一个普通的 Maven 项目,因此我们自定义 Starter ,需要首先创建一个普通的 Maven 项目,创建完成后,添加 Starter 的自动化配置类即可,如下:

创建一个普通maven项目,添加下面的依赖。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-autoconfigure</artifactId>
    <version>2.1.4.RELEASE</version>
</dependency>

20190628163106

这就是我们项目的基本骨架。

创建我们的配置类

package com.github.codeman.mystarter;

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

@ConfigurationProperties(prefix = "codeman")
public class CodemanProperties {
    private static final String DEFAULT_NAME = "codeman";
    private static final String DEFAULT_MSG = "learn program in a better way";

    private String name = DEFAULT_NAME;
    private String msg = DEFAULT_MSG;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
}

这个配置类很简单,@ConfigurationProperties(prefix = "codeman")会自动读取application.properties里面的以codeman开头的配置属性。将来我们在applicaton.properties中配置的codeman.namecodeman.msg就会被读取进来并赋值给相应的属性。

创建我们的功能类

一个starter总是要完成特定的事情的,这里我就写一个最简单的服务类,实际的项目中这个可能非常复杂。

public class CodemanService {
    private String msg;
    private String name;
    public String sayHello() {
        return name + " say " + msg + " !";
    }
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

这个服务类也没有做什么特别的事情,等会我们在自动配置时,把它注册为一个bean就行了。

自动配置类

这里就是重点了,我们的自动配置类是这样的。

@Configuration
@EnableConfigurationProperties(CodemanProperties.class)
@ConditionalOnClass(CodemanService.class)
public class CodemanServiceAutoConfiguration {
    @Autowired
    CodemanProperties codemanProperties;

    @Bean
    CodemanService codemanService() {
        CodemanService codemanService = new CodemanService();
        codemanService.setMsg(codemanProperties.getMsg());
        codemanService.setName(codemanProperties.getName());
        return codemanService;
    }
}

20190628163712

  • @Configuration表明这是一个配置类

  • @EnableConfigurationProperties(CodemanProperties.class)

    因为我之前在CodemanProperties这个类中使用了ConfigurationProperties,所以我们这里要有一个配套的@EnableConfigurationProperties

  • 具体实现

    然后我们在配置类中将我们的CodemanService注册成了一个Bean,这样其他模块在使用我们这个模块是时候,就可以直接使用我们的CodemanService了。

不过你可能注意到了,我还写了这个注解
@ConditionalOnClass(CodemanService.class)

它的语义就是存在CodemanService.class这个类的时候,开启自动配置,否则这个类不发生作用。

当然你也可以添加下面这些注解:

  • @ConditionalOnProperty

    Combine @conditional annotations to enable configuration when the specified property has a specified value.

  • @ConditionalOnExpression

    Combine @conditional annotations to enable configuration when the SpEL expression is true.

当然,你可以不写任何的@conditional注解,如果这样的话,你的配置类总是会开启的。

注册配置类

最后一步,为了能让我们的自动配置类发挥作用,我们需要把它按照特定的方式注册。

SpringBoot约定:springboot会先检查META-INF这个文件夹里面的spring.factories文件,并读取下面这个字段。总之按照下面这样写就行了。

20190628164028

实践

编写完我们的配置类后,我们测试一下。

  1. 安装到本地
    直接在当前项目的根目录下执行这个命令,就可以将当前的模块打包成jar文件并安装到本地了
$ mvn install
  1. 创建一个新的项目,用来测试
    然后创建一个新的SpringBoot项目,然后添加这个依赖。
        <dependency>
            <groupId>com.github.codeman</groupId>
            <artifactId>mystarter</artifactId>
            <version>0.0.1</version>
        </dependency>
  1. 编写一个简单的服务。

20190628170603

  1. 再添加一些配置信息。

20190628171158

  1. 最后启动下我们的服务器

20190628162759

可以看到,我们的starter确实起到的作用,codemanService被自动注册到我们的项目中。

总结

然后对于如果你想编写自己的starter,你就应给修改:

  • CodemanService

    这是将是你真正工作的类。

  • CodemanProerties

    你将通过这个配置类读取用户的配置信息。

  • @Conditanal

    取决于你希望在什么情况下开启自动配置。

@bitfishxyz bitfishxyz added the SpringBoot SpringBoot label Aug 8, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
SpringBoot SpringBoot
Projects
None yet
Development

No branches or pull requests

1 participant