SpringBoot:自定义Starter

一 概述

SpringBoot 个人感觉特点:

1)众多库的集合(各种Starter),方便快速构建应用系统。

2)自动配置spring(通过AutoConfiguration机制),简化配置,也方便扩展新的Starter。

3)内嵌web容器,无需WAR部署。

 

本文自定义一个helloworld-starter 揭示starter的定义过程,及Spring AutoConfiguration 自动配置方法。

 

注:

SpringBoot AutoConfiguration机制: 

    SpringBoot启动时,扫描 classpath 所有Jar中 META-INF/spring.factories文件,读取org.springframework.boot.autoconfigure.EnableAutoConfiguration 指定的Configuration,根据Configuration上的Conditional条件自动创建bean,注入容器。

 

Spring自动配置的Starter及自动配置能力,由如下包提供。

Xml代码  收藏代码

  1. <dependency>  
  2.     <groupId>org.springframework.boot</groupId>  
  3.     <artifactId>spring-boot-autoconfigure</artifactId>  
  4.     <version>1.5.9.RELEASE</version>  
  5. </dependency>  

 

关于Spring框架@Configuration使用,可参见博客《Spring:@Configuration 使用》

 

二 Demo 工程规划

(1)spring-boot-helloworld-starter项目—— 自定义Starter

实现 HelloWorldTemplate 自动配置,并根据classpath 中是否有FastJson包,决定格式化信息方式

 

 

(2)spring-boot-web 项目—— 调用Starter

依赖spring-boot-helloworld-starter项目HelloWorldTemplate,将格式化的信息返回客户端(信息包括application.yml中的 helloworld.author中信息,“Hello World”,调用的传入的对象信息)

 

 

三 spring-boot-helloworld-starter项目

(1)工程:

1)父 pom : 

其中:spring-boot-dependencies 提供了spring boot的依赖声明

 

Xml代码  收藏代码

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"  
  3.          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
  5.     <modelVersion>4.0.0</modelVersion>  
  6.   
  7.     <groupId>x.demo.springboot.starter</groupId>  
  8.     <artifactId>spring-boot-starter</artifactId>  
  9.     <version>1.0-SNAPSHOT</version>  
  10.     <packaging>pom</packaging>  
  11.     <modules>  
  12.         <module>module/spring-boot-helloworld-starter</module>  
  13.     </modules>  
  14.   
  15.     <properties>  
  16.         <java.version>1.8</java.version>  
  17.         <spring.boot.version>1.5.9.RELEASE</spring.boot.version>  
  18.         <fastjson.version>1.2.28</fastjson.version>  
  19.     </properties>  
  20.   
  21.     <dependencyManagement>  
  22.         <dependencies>  
  23.             <!-- spring boot 基础依赖 -->  
  24.             <dependency>  
  25.                 <groupId>org.springframework.boot</groupId>  
  26.                 <artifactId>spring-boot-dependencies</artifactId>  
  27.                 <version>${spring.boot.version}</version>  
  28.                 <type>pom</type>  
  29.                 <scope>import</scope>  
  30.             </dependency>  
  31.             <dependency>  
  32.                 <groupId>com.alibaba</groupId>  
  33.                 <artifactId>fastjson</artifactId>  
  34.                 <version>${fastjson.version}</version>  
  35.             </dependency>  
  36.         </dependencies>  
  37.     </dependencyManagement>  
  38.     <build>  
  39.         <pluginManagement>  
  40.             <plugins>  
  41.                 <plugin>  
  42.                     <groupId>org.apache.maven.plugins</groupId>  
  43.                     <artifactId>maven-compiler-plugin</artifactId>  
  44.                     <configuration>  
  45.                         <source>${java.version}</source>  
  46.                         <target>${java.version}</target>  
  47.                     </configuration>  
  48.                 </plugin>  
  49.             </plugins>  
  50.         </pluginManagement>  
  51.     </build>  
  52. </project>  

    

 

2)module: 

其中FastJson 使用,<optional>true</optional> ,指定客户端可以选择依赖该jar,用于实现如果classpath 中没有fastjson的jar,则不使用JSON FastJsonOutputFormater

 

Xml代码  收藏代码

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"  
  3.          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
  5.     <parent>  
  6.         <artifactId>spring-boot-starter</artifactId>  
  7.         <groupId>x.demo.springboot.starter</groupId>  
  8.         <version>1.0-SNAPSHOT</version>  
  9.         <relativePath>../../pom.xml</relativePath>  
  10.     </parent>  
  11.     <modelVersion>4.0.0</modelVersion>  
  12.   
  13.     <artifactId>spring-boot-helloworld-starter</artifactId>  
  14.   
  15.     <dependencies>  
  16.         <dependency>  
  17.             <groupId>org.springframework.boot</groupId>  
  18.             <artifactId>spring-boot-autoconfigure</artifactId>  
  19.         </dependency>  
  20.         <!-- @ConfigurationProperties annotation processing (metadata for IDEs) -->  
  21.         <dependency>  
  22.             <groupId>org.springframework.boot</groupId>  
  23.             <artifactId>spring-boot-configuration-processor</artifactId>  
  24.             <optional>true</optional>  
  25.         </dependency>  
  26.   
  27.         <dependency>  
  28.             <groupId>com.alibaba</groupId>  
  29.             <artifactId>fastjson</artifactId>  
  30.             <!-- 指定客户端可以选择依赖该jar,用于实现如果classpath 中没有fastjson的jar,则不使用JSON FastJsonOutputFormater-->  
  31.             <optional>true</optional>  
  32.         </dependency>  
  33.     </dependencies>  
  34.   
  35. </project>  

 

 

(2)主要服务类:HelloWorldTemplate

实现组装配置文件中的作者信息、HelloWorld、用户传入的对象信息

 

Java代码  收藏代码

  1. package x.demo.springboot.starter.hw;  
  2.   
  3. import x.demo.springboot.starter.hw.autoconfiguration.HelloWorldProperties;  
  4. import x.demo.springboot.starter.hw.outputformater.OutputFormater;  
  5.   
  6. /** 
  7.  * 配置文件中的作者信息 
  8.  * HelloWorld 
  9.  * 对象信息 
  10.  */  
  11. public class HelloWorldTemplate {  
  12.   
  13.     private HelloWorldProperties helloWorldProperties;  
  14.   
  15.     private OutputFormater outputFormater;  
  16.   
  17.     public HelloWorldTemplate(HelloWorldProperties helloWorldProperties, OutputFormater outputFormater) {  
  18.         this.helloWorldProperties = helloWorldProperties;  
  19.         this.outputFormater = outputFormater;  
  20.     }  
  21.   
  22.     /** 
  23.      * 打印作者信息 
  24.      * 打印对象信息 
  25.      * 
  26.      * @param obj 打印的对象 
  27.      */  
  28.     public <T> String generate(T obj) {  
  29.         StringBuilder message = new StringBuilder();  
  30.         message.append("author: ").append(outputFormater.format(helloWorldProperties.getAuthor())).append("\n");  
  31.         message.append("say: Hello World!").append("\n");  
  32.         message.append("object: ").append(outputFormater.format(obj)).append("\n");  
  33.         return message.toString();  
  34.     }  
  35. }  

 

 

(3)HelloWorldProperties:映射application.yaml文件中的 helloworld.authors信息:

以通过@ConfigurationProperties(prefix = HelloWorldProperties.HELLOWORLD_PREFIX) 标识是属性映射类,同时指定了在主配置文件中的前缀。需要通过@EnableConfigurationProperties(HelloWorldProperties.class)开启。

 

Java代码  收藏代码

  1. package x.demo.springboot.starter.hw.autoconfiguration;  
  2.   
  3. import java.util.Map;  
  4.   
  5. import org.springframework.boot.context.properties.ConfigurationProperties;  
  6.   
  7. /** 
  8.  * 用于springboot 从配置文件 (application.yml) 中读取 helloworld配置 
  9.  */  
  10. @ConfigurationProperties(prefix = HelloWorldProperties.HELLOWORLD_PREFIX)  
  11. public class HelloWorldProperties {  
  12.   
  13.     public static final String HELLOWORLD_PREFIX = "helloworld";  
  14.   
  15.     private Map<String, Object> author;  
  16.   
  17.     public Map<String, Object> getAuthor() {  
  18.         return author;  
  19.     }  
  20.   
  21.     public void setAuthor(Map<String, Object> author) {  
  22.         this.author = author;  
  23.     }  
  24. }  

 

 

(4)OutputFormater:输出格式化:

1)接口

 

Java代码  收藏代码

  1. package x.demo.springboot.starter.hw.outputformater;  
  2.   
  3. /** 
  4.  * 格式化工具 
  5.  */  
  6. public interface OutputFormater {  
  7.   
  8.     /** 
  9.      * 格式 
  10.      * @param obj 对象 
  11.      * @return 格式字符串 
  12.      */  
  13.     <T> String format(T obj);  
  14. }  

 

 

2)toString()实现

 

Java代码  收藏代码

  1. package x.demo.springboot.starter.hw.outputformater;  
  2.   
  3. import java.util.Objects;  
  4.   
  5. /** 
  6.  * 使用对象toString() 格式化 
  7.  */  
  8. public class ToStringOutputFormater implements OutputFormater {  
  9.     /** 
  10.      * 格式 
  11.      * 
  12.      * @param obj 对象 
  13.      * @return 格式字符串 
  14.      */  
  15.     public <T> String format(T obj) {  
  16.         return "ToStringOutputFormater:" +Objects.toString(obj);  
  17.     }  
  18. }  

 

 

3)json 实现

 

Java代码  收藏代码

  1. package x.demo.springboot.starter.hw.outputformater;  
  2.   
  3. import com.alibaba.fastjson.JSON;  
  4.   
  5. /** 
  6.  * 使用fastjson格式化 
  7.  */  
  8. public class FastJsonOutputFormater implements OutputFormater {  
  9.     /** 
  10.      * 格式 
  11.      * 
  12.      * @param obj 对象 
  13.      * @return 格式字符串 
  14.      */  
  15.     public <T> String format(T obj) {  
  16.         return "FastJsonOutputFormater: " + JSON.toJSONString(obj);  
  17.     }  
  18. }  

 

 

(5)自动配置类,用于向容器注册相应的对象:

关于Spring框架@Configuration使用,可参见博客《Spring:@Configuration 使用》

 

1)OutputFormaterAutoConfiguration:配置OutputFormater

 

这里通过@Conditional注解指定注册条件,主要用了:

 

@ConditionalOnMissingClass : classpath 中没有com.alibaba.fastjson.JSON 实例化,创建ToStringOutputFormater

@ConditionalOnClass(name = "com.alibaba.fastjson.JSON") classpath 中有com.alibaba.fastjson.JSON 实例化 FastJsonOutputFormater

Java代码  收藏代码

  1. package x.demo.springboot.starter.hw.autoconfiguration;  
  2.   
  3. import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;  
  4. import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;  
  5. import org.springframework.context.annotation.Bean;  
  6. import org.springframework.context.annotation.Configuration;  
  7. import x.demo.springboot.starter.hw.outputformater.FastJsonOutputFormater;  
  8. import x.demo.springboot.starter.hw.outputformater.OutputFormater;  
  9. import x.demo.springboot.starter.hw.outputformater.ToStringOutputFormater;  
  10.   
  11. @Configuration  
  12. public class OutputFormaterAutoConfiguration {  
  13.   
  14.     /** 
  15.      * @ConditionalOnMissingClass : classpath 中没有com.alibaba.fastjson.JSON 实例化,创建ToStringOutputFormater 
  16.      */  
  17.     @ConditionalOnMissingClass("com.alibaba.fastjson.JSON")  
  18.     @Bean  
  19.     public OutputFormater toStringOutputFormater() {  
  20.         return new ToStringOutputFormater();  
  21.     }  
  22.   
  23.     /** 
  24.      * @ConditionalOnClass(name = "com.alibaba.fastjson.JSON") classpath 中有com.alibaba.fastjson.JSON 实例化 FastJsonOutputFormater 
  25.      */  
  26.     @ConditionalOnClass(name = "com.alibaba.fastjson.JSON")  
  27.     @Bean  
  28.     public OutputFormater fastJsonOutputFormater() {  
  29.         return new FastJsonOutputFormater();  
  30.     }  
  31. }  

 

 

2)HelloWorldAutoConfiguration:配置HelloWorldTemplate

Java代码  收藏代码

  1. package x.demo.springboot.starter.hw.autoconfiguration;  
  2.   
  3. import org.springframework.boot.context.properties.EnableConfigurationProperties;  
  4. import org.springframework.context.annotation.Bean;  
  5. import org.springframework.context.annotation.Configuration;  
  6. import org.springframework.context.annotation.Import;  
  7. import x.demo.springboot.starter.hw.HelloWorldTemplate;  
  8. import x.demo.springboot.starter.hw.outputformater.OutputFormater;  
  9.   
  10.   
  11. @EnableConfigurationProperties(HelloWorldProperties.class)  
  12. @Import(OutputFormaterAutoConfiguration.class)  
  13. @Configuration  
  14. public class HelloWorldAutoConfiguration {  
  15.   
  16.     @Bean  
  17.     public HelloWorldTemplate helloWorldTemplate(HelloWorldProperties helloWorldProperties, OutputFormater outputFormater) {  
  18.         return new HelloWorldTemplate(helloWorldProperties, outputFormater);  
  19.     }  
  20. }  

  

(6)注册自动配置类:META-INF/spring.factories

 

Properties代码  收藏代码

  1. # Auto Configure  
  2. org.springframework.boot.autoconfigure.EnableAutoConfiguration=\  
  3. x.demo.springboot.starter.hw.autoconfiguration.HelloWorldAutoConfiguration  

 

四 spring-boot-web 项目

(1)工程:

1)父 pom : 继承了spring-boot-starter-parent

 

Xml代码  收藏代码

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"  
  3.          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
  5.     <modelVersion>4.0.0</modelVersion>  
  6.   
  7.     <groupId>x.demo.springboot.starter</groupId>  
  8.     <artifactId>spring-boot-starter</artifactId>  
  9.     <version>1.0-SNAPSHOT</version>  
  10.     <packaging>pom</packaging>  
  11.     <modules>  
  12.         <module>module/spring-boot-helloworld-starter</module>  
  13.     </modules>  
  14.   
  15.     <properties>  
  16.         <java.version>1.8</java.version>  
  17.         <spring.boot.version>1.5.9.RELEASE</spring.boot.version>  
  18.         <fastjson.version>1.2.28</fastjson.version>  
  19.     </properties>  
  20.   
  21.     <dependencyManagement>  
  22.         <dependencies>  
  23.             <!-- spring boot 基础依赖 -->  
  24.             <dependency>  
  25.                 <groupId>org.springframework.boot</groupId>  
  26.                 <artifactId>spring-boot-dependencies</artifactId>  
  27.                 <version>${spring.boot.version}</version>  
  28.                 <type>pom</type>  
  29.                 <scope>import</scope>  
  30.             </dependency>  
  31.             <dependency>  
  32.                 <groupId>com.alibaba</groupId>  
  33.                 <artifactId>fastjson</artifactId>  
  34.                 <version>${fastjson.version}</version>  
  35.             </dependency>  
  36.         </dependencies>  
  37.     </dependencyManagement>  
  38.     <build>  
  39.         <pluginManagement>  
  40.             <plugins>  
  41.                 <plugin>  
  42.                     <groupId>org.apache.maven.plugins</groupId>  
  43.                     <artifactId>maven-compiler-plugin</artifactId>  
  44.                     <configuration>  
  45.                         <source>${java.version}</source>  
  46.                         <target>${java.version}</target>  
  47.                     </configuration>  
  48.                 </plugin>  
  49.             </plugins>  
  50.         </pluginManagement>  
  51.     </build>  
  52. </project>  

 

2)module: 

依赖下spring-boot-helloworld-starter,这里不依赖FastJson的包,则自定义Starter中实例化的是没 ToStringOutputFormater

Java代码  收藏代码

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  3.          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
  4.     <modelVersion>4.0.0</modelVersion>  
  5.   
  6.     <parent>  
  7.         <groupId>x.demo.springboot</groupId>  
  8.         <artifactId>spring-boot</artifactId>  
  9.         <version>0.0.1-SNAPSHOT</version>  
  10.     </parent>  
  11.   
  12.     <artifactId>spring-boot-web</artifactId>  
  13.     <packaging>jar</packaging>  
  14.   
  15.     <name>spring-boot-web</name>  
  16.   
  17.     <dependencies>  
  18.         <dependency>  
  19.             <groupId>org.springframework.boot</groupId>  
  20.             <artifactId>spring-boot-starter-web</artifactId>  
  21.         </dependency>  
  22.         <dependency>  
  23.             <groupId>x.demo.springboot.starter</groupId>  
  24.             <artifactId>spring-boot-helloworld-starter</artifactId>  
  25.             <version>1.0-SNAPSHOT</version>  
  26.         </dependency>  
  27.     </dependencies>  
  28. </project>  

 

(2)配置文件:application.yml

Java代码  收藏代码

  1. # 应用配置  
  2. server:  
  3.   port: 8080  
  4.   
  5. # helloworld starter 配置  
  6. helloworld.author:  
  7.   name: foo  
  8.   roles: admin, developer  
  9.   email: foo@bar.com  

 

(3)controller 调用 HelloWorldTemplate

Java代码  收藏代码

  1. package x.demo.springboot.web.controller;  
  2.   
  3.   
  4. import javax.annotation.Resource;  
  5.   
  6. import org.springframework.util.StringUtils;  
  7. import org.springframework.web.bind.annotation.GetMapping;  
  8. import org.springframework.web.bind.annotation.RequestMapping;  
  9. import org.springframework.web.bind.annotation.RestController;  
  10. import x.demo.springboot.starter.hw.HelloWorldTemplate;  
  11.   
  12. @RestController  
  13. @RequestMapping("/helloworld")  
  14. public class HelloWorldContorller {  
  15.   
  16.     @Resource  
  17.     HelloWorldTemplate helloWorldTemplate;  
  18.   
  19.     @GetMapping("/say")  
  20.     public String say() {  
  21.         String message = helloWorldTemplate.generate("------------");  
  22.         return StringUtils.replace(message,"\n","<br/>");  
  23.     }  
  24. }  

 

(4)springboot启动类:

注:@SpringBootApplication 同时添加重要的两个MetaAnnotation @EnableAutoConfiguration,@ComponentScan,启动了AutoConfiguration和包扫描。

 

由于:

web包:x.demo.springboot.web

starter包:x.demo.springboot.starter.hw

 

包不同,所以Starter不是包扫描注入的,是通过读取META-INF/spring.factories注入的

 

Java代码  收藏代码

  1. package x.demo.springboot.web;  
  2.   
  3. import org.springframework.boot.SpringApplication;  
  4. import org.springframework.boot.autoconfigure.SpringBootApplication;  
  5.   
  6. @SpringBootApplication  
  7. public class SpringBootWeb {  
  8.   
  9.     public static void main(String[] args) {  
  10.         SpringApplication.run(SpringBootWeb.class, args);  
  11.     }  
  12. }  

 

五 结果

1)常规结果

 

 

2)添加FastJson依赖的结果

web module pom:

 

Xml代码  收藏代码

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  3.          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
  4.     <modelVersion>4.0.0</modelVersion>  
  5.   
  6.     <parent>  
  7.         <groupId>x.demo.springboot</groupId>  
  8.         <artifactId>spring-boot</artifactId>  
  9.         <version>0.0.1-SNAPSHOT</version>  
  10.     </parent>  
  11.   
  12.     <artifactId>spring-boot-web</artifactId>  
  13.     <packaging>jar</packaging>  
  14.   
  15.     <name>spring-boot-web</name>  
  16.   
  17.     <dependencies>  
  18.         <dependency>  
  19.             <groupId>org.springframework.boot</groupId>  
  20.             <artifactId>spring-boot-starter-web</artifactId>  
  21.         </dependency>  
  22.         <dependency>  
  23.             <groupId>x.demo.springboot.starter</groupId>  
  24.             <artifactId>spring-boot-helloworld-starter</artifactId>  
  25.             <version>1.0-SNAPSHOT</version>  
  26.         </dependency>  
  27.         <dependency>  
  28.             <groupId>com.alibaba</groupId>  
  29.             <artifactId>fastjson</artifactId>  
  30.         </dependency>  
  31.     </dependencies>  
  32. </project>  

 



  

六 涉及注解说明

1) 配置

@Configuration,@Import,@Bean:《Spring:@Configuration 使用》

 

2) 条件组装

@ConditionalOnBean:Spring容器中存在指定实例时

@ConditionalOnClass:类加载器中存在指定类时

@ConditionalOnExpression:指定表达式成立时

@ConditionalOnMissingBean:Spring容器总缺少指定实例时

@ConditionalOnMissingClass:类加载器中不存在指定类时

@ConditionalOnNotWebApplication:非Web应用时

@ConditionalOnResource:存在指定资源文件时

@ConditionalOnWebApplication:Web应用时

 

3)读取属性

@EnableConfigurationProperties:开始扫描处理@ConfigurationProperties注解的Bean

@ConfigurationProperties:绑定外部配置

 

 

 

转载地址:http://shihlei.iteye.com/blog/2407689

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值