自定义Starter:

  Starter会把所有用到的依赖都给包含进来,避免了开发者自己去引入依赖所带来的麻烦。Starter 提供了一种开箱即用的理念,其中核心就是springboot的自动配置原理相关,调用相关的注解实现条件判断,进而进行Bean的注入管理。

  基于SpringBoot自动配置原理的学习,现在我们来实现一下自定义starter。我们假设有一个格式化的,暂定两个实现,一个是Object-> String,一个是Object->JSON.

1.新建一个maven工程  format-spring-boot-starter,这里的命名在SpringBoot官网有建议:For example, assume that you are creating a starter for "acme" and that you name the auto-configure module acme-spring-boot-autoconfigure and the starter acme-spring-boot-starter. If you only have one module that combines the two, name it acme-spring-boot-starter. pom文件如下:

  1. <dependencies>
  2. <dependency>
  3. <groupId>junit</groupId>
  4. <artifactId>junit</artifactId>
  5. <version>4.11</version>
  6. <scope>test</scope>
  7. </dependency>
  8.  
  9. <dependency>
  10. <groupId>org.springframework.boot</groupId>
  11. <artifactId>spring-boot-starter</artifactId>
  12. <version>2.1..RELEASE</version>
  13. </dependency>
  14.  
  15. <dependency>
  16. <groupId>com.alibaba</groupId>
  17. <artifactId>fastjson</artifactId>
  18. <version>1.2.</version>
  19. <optional>true</optional><!--可选-->
  20. </dependency>
       <!--支持ConfigurationProperties-->
  21. <dependency>
  22. <groupId>org.springframework.boot</groupId>
  23. <artifactId>spring-boot-configuration-processor</artifactId>
  24. <version>2.1..RELEASE</version>
  25. <optional>true</optional>
  26. </dependency>
  27. </dependencies>

2.构建格式化接口并且定义实现,咱们这里想实现动态注入的想过,定义两个实现以做对比:

  1. public interface FormatProcessor {
  2. //定义一个格式化的方法
  3. <T> String format(T obj);
  4. }
  5. //实现1 JSON
  6. public class JsonFormatProcessor implements FormatProcessor{
  7. @Override
  8. public <T> String format(T obj) {
  9. return "JsonFormatProcessor:"+ JSON.toJSONString(obj);
  10. }
  11. }
  12. //实现2 String
  13. public class StringFormatProcessor implements FormatProcessor{
  14.  
  15. @Override
  16. public <T> String format(T obj) {
  17. return "StringFormatProcessor:"+Objects.toString(obj);
  18. }
  19. }

3.这里我们需要把这两个类根据  Conditional 注解动态注入到Spring 容器中,在springboot自动配置中我们说到有个 metadata 文件可以做过滤,而这里的 ConditionalOnClass 是一样的,只是方式不一样:

  1. @Configuration
  2. public class FormatAutoConfiguration {
  3. //metadata-auto....
  4. @ConditionalOnMissingClass("com.alibaba.fastjson.JSON")
  5. @Bean
  6. @Primary
  7. public FormatProcessor stringFormat(){
  8. return new StringFormatProcessor();
  9. }
  10.  
  11. @ConditionalOnClass(name = "com.alibaba.fastjson.JSON")
  12. @Bean
  13. public FormatProcessor jsonFormat(){
  14. return new JsonFormatProcessor();
  15. }
  16.  
  17. }

4.我们这里参照着  jdbcTemplate 的模板来实现我们这个需求:

  1. public class HelloFormatTemplate {
  2.  
  3. private FormatProcessor formatProcessor;public HelloFormatTemplate(FormatProcessor formatProcessor) {this.formatProcessor = formatProcessor;
  4. }
  5.    //定义一个格式化方法,具体的实现由FormatProcessor实现类实现
  6. public <T> String doFormat(T obj){
  7. StringBuilder stringBuilder=new StringBuilder();
  8. stringBuilder.append("begin:Execute format").append("<br/>");
  9. stringBuilder.append("Obj format result:").append(formatProcessor.format(obj)).append("<br/>");
  10. return stringBuilder.toString();
  11.  
  12. }
  13. }

5.然后我们需要动态的注入:

  1. @Import(FormatAutoConfiguration.class)
  2. @Configuration
  3. public class HelloAutoConfiguration {
  4.  
  5. @Bean
  6. public HelloFormatTemplate helloFormatTemplate(FormatProcessor formatProcessor){
  7. return new HelloFormatTemplate(formatProcessor);
  8. }
  9. }

6.接下去需要在classpath下的META-INF文件夹下创建一个文件 spring.factories:

  1. org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  2. com.wuzz.starter.autoconfiguration.HelloAutoConfiguration

  然后将该工程打成Jar,然后我们需要做的是在我们需要用到这个Starter的boot项目重中导入该starter

1.导入starter,我们会看到有些starter里面是空的,其实他做的仅仅是依赖传递,这样容器中存在某个类,这个时候符合另外一个类的加载,也能起到开箱即用的效果:

  1. <dependency>
  2. <groupId>com.wuzz.starter</groupId>
  3. <artifactId>format-spring-boot-starter</artifactId>
  4. <version>1.0-SNAPSHOT</version>
  5. </dependency>

2.定义一个实体类如下:

  1. public class User {
  2. private String name;
  3. private int age;
  4.    //省略 get set
  5. @Override
  6. public String toString() {
  7. return "User{" +
  8. "name='" + name + '\'' +
  9. ", age=" + age +
  10. '}';
  11. }
  12. }

3.我们写一个controller来测试效果:

  1. @RestController
  2. public class FormatController {
  3.  
  4. @Autowired
  5. HelloFormatTemplate helloFormatTemplate;
  6.  
  7. @GetMapping("/format")
  8. public String format(){
  9. User user=new User();
  10. user.setAge();
  11. user.setName("wuzz-starter");
  12. return helloFormatTemplate.doFormat(user);
  13. }
  14. }

  其他无需任何配置,我们直接启动该项目,通过  localhost:8080/format 来访问会看到以下效果:

  再来,我们导入以下依赖:

  1. <dependency>
  2. <groupId>com.alibaba</groupId>
  3. <artifactId>fastjson</artifactId>
  4. <version>1.2.</version>
  5. </dependency>

  重启项目再去访问:

  是不是很爽?这样子就实现了Starter的自定义,

SpringBoot外部配置:

  这个时候我们还存在另外一个问题没有解决,就类似于我们导入了Eureka的starter,那么这个时候我们可以在 application.properties 中可以配置很多的信息,这个就是springboot的外部配置,取决于注解 @ConfigurationProperties。

  我们是不是也能实现这样的效果呢?答案是当然咯,那么接下去我们就基于原来的工程进行再一次的改造。

1.增加我们自定义的Properties 类:

  1. @ConfigurationProperties(prefix="wuzz.hello.format")
  2. public class HelloProperties {
  3.  
  4. private String appOwner;
  5.  
  6. private Map<String,Object> info;
  7.  
  8. public String getAppOwner() {
  9. return appOwner;
  10. }
  11.  
  12. public void setAppOwner(String appOwner) {
  13. this.appOwner = appOwner;
  14. }
  15.  
  16. public Map<String, Object> getInfo() {
  17. return info;
  18. }
  19.  
  20. public void setInfo(Map<String, Object> info) {
  21. this.info = info;
  22. }
  23. }

2.修改HelloTemplate 如下:

  1. public class HelloFormatTemplate {
  2.  
  3. private FormatProcessor formatProcessor;
  4.  
  5. private HelloProperties helloProperties;
  6.  
  7. public HelloFormatTemplate(HelloProperties helloProperties, FormatProcessor formatProcessor) {
  8. this.helloProperties = helloProperties;
  9. this.formatProcessor = formatProcessor;
  10. }
  11.  
  12. public <T> String doFormat(T obj) {
  13.  
  14. StringBuilder stringBuilder = new StringBuilder();
  15. stringBuilder.append("begin:Execute format").append("<br/>");
  16. stringBuilder.append("HelloProperties:").append(helloProperties.getAppOwner()).append("<br/>")
  17. .append(formatProcessor.format(helloProperties.getInfo())).append("<br/>");
  18. stringBuilder.append("Obj format result:").append(formatProcessor.format(obj)).append("<br/>");
  19. return stringBuilder.toString();
  20.  
  21. }
  22. }

3.修改HelloAutoConfiguration如下:

  1. @Import(FormatAutoConfiguration.class)
  2. @EnableConfigurationProperties(HelloProperties.class)
  3. @Configuration
  4. public class HelloAutoConfiguration {
  5.  
  6. @Bean
  7. public HelloFormatTemplate helloFormatTemplate(HelloProperties helloProperties,FormatProcessor formatProcessor){
  8. return new HelloFormatTemplate(helloProperties,formatProcessor);
  9. }
  10. }

然后我们重新打个包,再在需要依赖的那个工程中更新导入一下maven。然后我们在application.properties中就可以实现我们的配置:

  配置两条配置项:wuzz.hello.format.app-owner=wuzz ,wuzz.hello.format.info.app=starter-demo

  然后启动项目我们再次访问:

  效果非常的好,在我们需要自定义的封装一些自定义组件的时候就可以使用这个拓展啦。

SpringBoot自定义Starter实现的更多相关文章

  1. SpringBoot --- 自定义 Starter

    SpringBoot --- 自定义 Starter 创建 1.需要创建一个新的空工程 2.新的工程需要引入两个模块 一个Maven 模块 作为启动器 一个SpringBoot 模块 作为自动配置模块 ...

  2. SpringBoot自定义starter及自动配置

    SpringBoot的核心就是自动配置,而支持自动配置的是一个个starter项目.除了官方已有的starter,用户自己也可以根据规则自定义自己的starter项目. 自定义starter条件 自动 ...

  3. springboot 自定义starter之AutoConfiguration【原】

    八.自定义starter AutoConfiguration: 1.这个场景需要使用到的依赖是什么? 没有特别依赖的配置 2.如何编写自动配置 @Configuration //指定这个类是一个配置类 ...

  4. SpringBoot自定义starter开发分布式任务调度实践

    概述 需求 在前面的博客<Java定时器演进过程和生产级分布式任务调度ElasticJob代码实战>中,我们已经熟悉ElasticJob分布式任务的应用,其核心实现为elasticjob- ...

  5. SpringBoot系列三:SpringBoot自定义Starter

    在前面两章 SpringBoot入门 .SpringBoot自动配置原理 的学习后,我们对如何创建一个 SpringBoot 项目.SpringBoot 的运行原理以及自动配置等都有了一定的了解.如果 ...

  6. springboot自定义starter

    1,创建一个空工程 2,new一个Modules  ---------------- maven (启动器) : springboottest-spring-boot-starter 3,new一个M ...

  7. Springboot自定义starter打印sql及其执行时间

    前面写到了通过实现mybatis提供的org.apache.ibatis.plugin.Interceptor接口实现了打印SQL执行时间,并格式化SQL及其参数,如果我们使用的是ssm还得再配置文件 ...

  8. Spring-Boot自定义Starter实践

    此文已由作者王慎为授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. disconf-spring-boot-starter 使用方法: 引入maven依赖: <depen ...

  9. SpringBoot之旅第六篇-启动原理及自定义starter

    一.引言 SpringBoot的一大优势就是Starter,由于SpringBoot有很多开箱即用的Starter依赖,使得我们开发变得简单,我们不需要过多的关注框架的配置. 在日常开发中,我们也会自 ...

随机推荐

  1. HDU-4810-wall Painting(二进制, 组合数)

    链接: https://vjudge.net/problem/HDU-4810 题意: Ms.Fang loves painting very much. She paints GFW(Great F ...

  2. <el-tree>文字显示不全解决办法(可以用省略号代替)

    地址: https://www.jianshu.com/p/229f96b794d3

  3. 【NOIP2016提高组复赛day2】天天爱跑步

    题目 小 C 同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏. <天天爱跑步>是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图可以看作一棵 ...

  4. quartz的配置文件说明

    # Default Properties file for use by StdSchedulerFactory # to create a Quartz Scheduler Instance, if ...

  5. django model序列化作用举例

    一直对使用DRF的了解停留在一知半解的状态,今天在实际操作中,感受到了DRF带来的方便 Django工程,其中两个model定义如下: AutomationHeadRaw: class Automat ...

  6. java语言课堂动手动脑

    1 运行 TestInherits.java 示例,观察输出,注意总结父类与子类之间构造方法的调用关系修改Parent构造方法的代码,显式调用GrandParent的另一个构造函数,注意这句调用代码是 ...

  7. Logger工具类

    org.slf4j.Logger的简单封装,传入所在类的class,和类名或全类名. public class LoggerFactory { public static Logger getLogg ...

  8. phpcms v9 更改首页

    phpcms v9的默认首页是(域名/index.php?m=content&c=index&a=init)那为什么你直接敲一个域名它就自己进 去了呢,其实在caches-->c ...

  9. sqli-labs(36)

    0X01发现又是‘’被过滤了 ?id=%df%%20and%=%23 错误 ?id=1%df%27%20and%201=1%23 正确   存在注入 0X01爆数据库 ?id=-%df%%20unio ...

  10. android系统时间格式转换工具类

    代码依旧非常简单,只不过因为这个方法极为常用,因此体现的还是封装的思想. package com.ctbri.weather.utils; import java.text.SimpleDateFor ...