SpringBoot自动装配之写一个Starter

2,076 阅读4分钟
我们在使用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系列文章:

SpringBoot系列教程