自己实现一个spring-boot-starter

379 阅读2分钟

spring boot的自动配置功能拯救了无数程序员于配置地狱,我们通常通过spring-boot-starter的方式导入依赖,就可以便捷地使用其自动为我们注入的对象,那么spring-boot-starter是怎么实现的呢?

1、starter项目结构

image.png

需要我们实现的主要有是处:

  • AutoConfiguration类:将bean注入spring容器的自动配置类
  • properties(可选):提供yml、properties文件中的配置选项
  • service:要注入的对象的具体实现
  • spring.factories:提供信息以告知spring-boot自动配置类的路径

所使用的maven依赖:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <version>2.2.12.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-autoconfigure</artifactId>
        <version>2.2.12.RELEASE</version>
    </dependency>
</dependencies>

2、具体实现

先上图:

image.png

2.1、读取properties

先上代码:

@ConfigurationProperties(prefix = "kloein.hello")
public class GreetProperties {
    private String name;
    private String message;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

@ConfigurationProperties:spring提供的读取配置文件的注解,prefix即配置名的的前缀。

对于GreetProperties文件中的name和message字段,有了该注解便可以这样从yml中读取:

kloein:
  hello:
    name: kloein
    message: good morning

2.2、service实现

出于演示目的,仅仅定义简单的服务。

接口:

public interface GreetService {
    String greet();
}

实现

@Service
public class GreetServiceImpl implements GreetService {
    @Autowired
    private GreetProperties greetProperties;
    @Override
    public String greet() {
        return greetProperties.getName()+":"+greetProperties.getMessage();
    }
}

2.3、AutoConfiguration类的实现

事实上,AutoConfiguration依旧是基于 @Configuration实现的。

回顾我们spring boot对于自动配置的:只要导入starter,如果没有自己定义所需的bean,就会帮我们配置。因此我们需要 @ConditionalOnMissingBean()注解:没有bean才注入

此外,针对我们2.1读取配置的功能,也需要注解 @EnableConfigurationProperties()

代码如下:

@Configuration
@ConditionalOnMissingBean(GreetService.class)
@EnableConfigurationProperties(GreetProperties.class)
public class GreetServiceAutoConfiguration {
    @Bean
    public GreetService greetService() {
        GreetServiceImpl greetService = new GreetServiceImpl();
        return greetService;
    }
}

2.4、spring.factories

最后,我们还需要告知spring我们要读取上方的配置类,spring容器启动时,会读取 /resources/META-INF/spring.factories文件,因此我们需要在其中指定我们配置类的位置。下列配置文件的意义是当开启 @EnableAutoConfiguration注解时会自动扫描com.example.autoconfig. GreetServiceAutoConfiguration文件

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.autoconfig.GreetServiceAutoConfiguration

3.测试

3.1、将jar包装入本地maven仓库

clean->install

image.png

### 3.2、导入依赖 就像我们往常使用的那样,导入maven依赖 ``` com.example hello-spring-boot-starter 1.0-SNAPSHOT ```

3.3、配置yml

在application.yml中配置2.1中的properties信息

server:
  port: 8011
  
kloein:
  hello:
    name: kloein
    message: good morning

3.4、简单的controller

@RestController
public class GreetController {
    @Autowired
    private GreetService greetService;
    @RequestMapping("/greet")
    public String greet() {
        String greet = greetService.greet();
        return greet;
    }
}

3.5、验证结果

image.png