Springboot系列-自定义starter

Springboot系列-自定义starter

前言:用过springboot的各位应该都知道,Springboot相对于Spring/SpringMVC要方便的多,为什么呢?这主要还是归功于Starter,其实Starter也是基于Spring/SpringMVC基础上实现的,因为Starter带来了许多的自动化配置,所以在我们开发的时候省了不少力

理解Starter

那么Starter是基于什么才能够实现众多自动化配置的呢?其实Starter的核心注解就是@Conditional,当classpath下面存在某一个class时,这个配置才会生效


自定义Starter

定义Starter

1.首先创建一个普通的新的maven项目,创建完成之后添加Starter的自动化配置类如下:

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

配置完之后其实我们可以通过源码看到,好多自动化配置已经引入进来了
在这里插入图片描述

2.配置完成之后创建一个DemoProperties类,用来接收application.properties中注入的值,如下:

@ConfigurationProperties(prefix = "test")
public class DemoProperties {
    private String name = "王先森";
    private String hobby = "Coding";

    public String getName() {
        return name;
    }

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

    public String getHobby() {
        return hobby;
    }

    public void setHobby(String hobby) {
        this.hobby = hobby;
    }
}

以上这个DemoProperties配置类的意思就是直接将application.properties里面的属性值注入到该实例中,@ConfigurationProperties 类型安全的属性注入,即将 application.properties 文件中前缀为 javaboy 的属性注入到这个类对应的属性上

application.prpoerties配置文件内容如下:

test.name = wxy
test.hobby = basketball

3.配置完DemoProperties之后,在定义一个DemoService类并定义个方法如下:

public class DemoService {
    private String name;
    private String hobby;

    public String doSomething() {
        return name + " do " + hobby + " !";
    }

    public String getName() {
        return name;
    }

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

    public String getHobby() {
        return hobby;
    }

    public void setHobby(String hobby) {
        this.hobby = hobby;
    }
}

上面这个DemoService意思就是很简单的一个类,添加了个doSomething方法,之后再对应文件将该类注入之后,传入属性值调用该方法

4.接下来要做的是非常关键,就是关于自动配置的定义,因为之前我们可能用的都是别人定义的,所以这次需要自己去定义

@Configuration
@EnableConfigurationProperties(DemoProperties.class)
@ConditionalOnClass(DemoService.class)
public class DemoServiceAutoConfiguration {

    @Autowired
    DemoProperties demoProperties;

    @Bean
    DemoService demoService(){
        DemoService demoService = new DemoService();
        demoService.setName(demoProperties.getName());
        demoService.setHobby(demoProperties.getHobby());
        return demoService;
    }
}

针对以上一段自动配置,解释如下:

  • Configuration:表示这是一个配置类
  • EnableConfigurationProperties:此注解是为了使之前配置的@ConfigurationProperties 生效
  • @ConditionalOnClass :表示项目当前classpath下存在DemoService时,后面的配置才会生效
  • 自动配置类中首先注入 DemoProperties ,该实例中有在 application.properties 中配置的相关数据
  • 提供一个 DemoService 的实例,将 DemoProperties 中的值注入进去

5.自动化配置类基本完成,接下来还需要一个 spring.factories 文件,那么这个文件是干什么用的呢?我们知道Springboot项目中有一个启动类,该启动类包含了@SpringBootApplication 注解,这个注解的定义如下:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {}

根据上面我们可以看出其实SpringBootApplication 是一个组合注解,它包含了如上注解,其最重要和关键的三个注解并解释如下:

  • @SpringBootConfiguration:此注解为Springboot配置注解,如下又在该注解中又包含如下注解:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
}
  • @EnableAutoConfiguration:开启自动配置注解,只有开启了这个自动配置之后自动配置才会生效,其注解又包含如下注解:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
  • @ComponentScan:这个注解在有一个主要的功能就是配置注解扫描,可以自定义去配置扫描的范围

6.在 Maven 项目的 resources 目录下创建一个名为 META-INF 的文件夹,然后在文件夹中创建一个名为 spring.factories 的文件,文件内容如下:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.wxy.entity.DemoServiceAutoConfiguration

动化配置类的路径配置完成,如此之后我们的自动化配置类就算完成了

本地安装

我们将我们写好的Starter项目进行打包,如下:

在这里插入图片描述

双击完成后,这个 Starter 就安装到我们本地仓库了,其实这个时候我们从该路径可以发现他打包成了一个jar包,如下:
在这里插入图片描述
那么如何使用它呢?


使用Starter

新建一个普通的 Spring Boot 工程,创建成功之后,加入自定义 Starter 的依赖,如下:

<dependency>
    <groupId>com.example</groupId>
    <artifactId>emptyMavenProject</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

此时我们引入了上面自定义的 Starter ,也就是说项目中现在有一个默认的 DemoService 实例可以使用,关于此实例的数据,可以在 application.properties 中进行配置,如下:

test.name = Wang sir
test.hobby = Coding

配置完成后,可选择在单元测试方法中注入 DemoSerivce 实例来使用,代码如下:

@SpringBootTest(classes = App.class)
class TeststarterApplicationTests {

    @Autowired
    DemoService demoService;
    @Test
    public void contextLoads() {
        System.out.println(demoService.doSomething());
    }
}

执行运行结果如下:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.2.1.RELEASE)
2019-12-03 15:16:57.423  INFO 19712 --- [           main] c.e.t.TeststarterApplicationTests        : Starting TeststarterApplicationTests on Wangxinyao with PID 19712 (started by Administrator in E:\IDEAWorkSpace\teststarter)
2019-12-03 15:16:57.430  INFO 19712 --- [           main] c.e.t.TeststarterApplicationTests        : No active profile set, falling back to default profiles: default
2019-12-03 15:17:00.216  INFO 19712 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2019-12-03 15:17:00.754  INFO 19712 --- [           main] c.e.t.TeststarterApplicationTests        : Started TeststarterApplicationTests in 4.157 seconds (JVM running for 6.18)
Wang sir do Coding !
2019-12-03 15:17:01.054  INFO 19712 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'

结语:基本上对于自定义Starter配置的讲解就到这里了,通过自定义Starter,可以把之前的项目通过打包注入到新的项目中,便捷开发

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章