编写不易,转载请注明(http://shihlei.iteye.com/blog/2407689)!
一 概述
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及自动配置能力,由如下包提供。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> <version>1.5.9.RELEASE</version> </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 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>x.demo.springboot.starter</groupId> <artifactId>spring-boot-starter</artifactId> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging> <modules> <module>module/spring-boot-helloworld-starter</module> </modules> <properties> <java.version>1.8</java.version> <spring.boot.version>1.5.9.RELEASE</spring.boot.version> <fastjson.version>1.2.28</fastjson.version> </properties> <dependencyManagement> <dependencies> <!-- spring boot 基础依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring.boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>${fastjson.version}</version> </dependency> </dependencies> </dependencyManagement> <build> <pluginManagement> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>${java.version}</source> <target>${java.version}</target> </configuration> </plugin> </plugins> </pluginManagement> </build> </project>
2)module:
其中FastJson 使用,<optional>true</optional> ,指定客户端可以选择依赖该jar,用于实现如果classpath 中没有fastjson的jar,则不使用JSON FastJsonOutputFormater
<?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"> <parent> <artifactId>spring-boot-starter</artifactId> <groupId>x.demo.springboot.starter</groupId> <version>1.0-SNAPSHOT</version> <relativePath>../../pom.xml</relativePath> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>spring-boot-helloworld-starter</artifactId> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> </dependency> <!-- @ConfigurationProperties annotation processing (metadata for IDEs) --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <!-- 指定客户端可以选择依赖该jar,用于实现如果classpath 中没有fastjson的jar,则不使用JSON FastJsonOutputFormater--> <optional>true</optional> </dependency> </dependencies> </project>
(2)主要服务类:HelloWorldTemplate
实现组装配置文件中的作者信息、HelloWorld、用户传入的对象信息
package x.demo.springboot.starter.hw; import x.demo.springboot.starter.hw.autoconfiguration.HelloWorldProperties; import x.demo.springboot.starter.hw.outputformater.OutputFormater; /** * 配置文件中的作者信息 * HelloWorld * 对象信息 */ public class HelloWorldTemplate { private HelloWorldProperties helloWorldProperties; private OutputFormater outputFormater; public HelloWorldTemplate(HelloWorldProperties helloWorldProperties, OutputFormater outputFormater) { this.helloWorldProperties = helloWorldProperties; this.outputFormater = outputFormater; } /** * 打印作者信息 * 打印对象信息 * * @param obj 打印的对象 */ public <T> String generate(T obj) { StringBuilder message = new StringBuilder(); message.append("author: ").append(outputFormater.format(helloWorldProperties.getAuthor())).append("\n"); message.append("say: Hello World!").append("\n"); message.append("object: ").append(outputFormater.format(obj)).append("\n"); return message.toString(); } }
(3)HelloWorldProperties:映射application.yaml文件中的 helloworld.authors信息:
以通过@ConfigurationProperties(prefix = HelloWorldProperties.HELLOWORLD_PREFIX) 标识是属性映射类,同时指定了在主配置文件中的前缀。需要通过@EnableConfigurationProperties(HelloWorldProperties.class)开启。
package x.demo.springboot.starter.hw.autoconfiguration; import java.util.Map; import org.springframework.boot.context.properties.ConfigurationProperties; /** * 用于springboot 从配置文件 (application.yml) 中读取 helloworld配置 */ @ConfigurationProperties(prefix = HelloWorldProperties.HELLOWORLD_PREFIX) public class HelloWorldProperties { public static final String HELLOWORLD_PREFIX = "helloworld"; private Map<String, Object> author; public Map<String, Object> getAuthor() { return author; } public void setAuthor(Map<String, Object> author) { this.author = author; } }
(4)OutputFormater:输出格式化:
1)接口
package x.demo.springboot.starter.hw.outputformater; /** * 格式化工具 */ public interface OutputFormater { /** * 格式 * @param obj 对象 * @return 格式字符串 */ <T> String format(T obj); }
2)toString()实现
package x.demo.springboot.starter.hw.outputformater; import java.util.Objects; /** * 使用对象toString() 格式化 */ public class ToStringOutputFormater implements OutputFormater { /** * 格式 * * @param obj 对象 * @return 格式字符串 */ public <T> String format(T obj) { return "ToStringOutputFormater:" +Objects.toString(obj); } }
3)json 实现
package x.demo.springboot.starter.hw.outputformater; import com.alibaba.fastjson.JSON; /** * 使用fastjson格式化 */ public class FastJsonOutputFormater implements OutputFormater { /** * 格式 * * @param obj 对象 * @return 格式字符串 */ public <T> String format(T obj) { return "FastJsonOutputFormater: " + JSON.toJSONString(obj); } }
(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
package x.demo.springboot.starter.hw.autoconfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import x.demo.springboot.starter.hw.outputformater.FastJsonOutputFormater; import x.demo.springboot.starter.hw.outputformater.OutputFormater; import x.demo.springboot.starter.hw.outputformater.ToStringOutputFormater; @Configuration public class OutputFormaterAutoConfiguration { /** * @ConditionalOnMissingClass : classpath 中没有com.alibaba.fastjson.JSON 实例化,创建ToStringOutputFormater */ @ConditionalOnMissingClass("com.alibaba.fastjson.JSON") @Bean public OutputFormater toStringOutputFormater() { return new ToStringOutputFormater(); } /** * @ConditionalOnClass(name = "com.alibaba.fastjson.JSON") classpath 中有com.alibaba.fastjson.JSON 实例化 FastJsonOutputFormater */ @ConditionalOnClass(name = "com.alibaba.fastjson.JSON") @Bean public OutputFormater fastJsonOutputFormater() { return new FastJsonOutputFormater(); } }
2)HelloWorldAutoConfiguration:配置HelloWorldTemplate
package x.demo.springboot.starter.hw.autoconfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import x.demo.springboot.starter.hw.HelloWorldTemplate; import x.demo.springboot.starter.hw.outputformater.OutputFormater; @EnableConfigurationProperties(HelloWorldProperties.class) @Import(OutputFormaterAutoConfiguration.class) @Configuration public class HelloWorldAutoConfiguration { @Bean public HelloWorldTemplate helloWorldTemplate(HelloWorldProperties helloWorldProperties, OutputFormater outputFormater) { return new HelloWorldTemplate(helloWorldProperties, outputFormater); } }
(6)注册自动配置类:META-INF/spring.factories
# Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ x.demo.springboot.starter.hw.autoconfiguration.HelloWorldAutoConfiguration
四 spring-boot-web 项目
(1)工程:
1)父 pom : 继承了spring-boot-starter-parent
<?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>x.demo.springboot.starter</groupId> <artifactId>spring-boot-starter</artifactId> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging> <modules> <module>module/spring-boot-helloworld-starter</module> </modules> <properties> <java.version>1.8</java.version> <spring.boot.version>1.5.9.RELEASE</spring.boot.version> <fastjson.version>1.2.28</fastjson.version> </properties> <dependencyManagement> <dependencies> <!-- spring boot 基础依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring.boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>${fastjson.version}</version> </dependency> </dependencies> </dependencyManagement> <build> <pluginManagement> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>${java.version}</source> <target>${java.version}</target> </configuration> </plugin> </plugins> </pluginManagement> </build> </project>
2)module:
依赖下spring-boot-helloworld-starter,这里不依赖FastJson的包,则自定义Starter中实例化的是没 ToStringOutputFormater
<?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> <parent> <groupId>x.demo.springboot</groupId> <artifactId>spring-boot</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <artifactId>spring-boot-web</artifactId> <packaging>jar</packaging> <name>spring-boot-web</name> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>x.demo.springboot.starter</groupId> <artifactId>spring-boot-helloworld-starter</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies> </project>
(2)配置文件:application.yml
# 应用配置 server: port: 8080 # helloworld starter 配置 helloworld.author: name: foo roles: admin, developer email: foo@bar.com
(3)controller 调用 HelloWorldTemplate
package x.demo.springboot.web.controller; import javax.annotation.Resource; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import x.demo.springboot.starter.hw.HelloWorldTemplate; @RestController @RequestMapping("/helloworld") public class HelloWorldContorller { @Resource HelloWorldTemplate helloWorldTemplate; @GetMapping("/say") public String say() { String message = helloWorldTemplate.generate("------------"); return StringUtils.replace(message,"\n","<br/>"); } }
(4)springboot启动类:
注:@SpringBootApplication 同时添加重要的两个MetaAnnotation @EnableAutoConfiguration,@ComponentScan,启动了AutoConfiguration和包扫描。
由于:
web包:x.demo.springboot.web
starter包:x.demo.springboot.starter.hw
包不同,所以Starter不是包扫描注入的,是通过读取META-INF/spring.factories注入的
package x.demo.springboot.web; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class SpringBootWeb { public static void main(String[] args) { SpringApplication.run(SpringBootWeb.class, args); } }
五 结果
1)常规结果
2)添加FastJson依赖的结果
web module 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> <parent> <groupId>x.demo.springboot</groupId> <artifactId>spring-boot</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <artifactId>spring-boot-web</artifactId> <packaging>jar</packaging> <name>spring-boot-web</name> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>x.demo.springboot.starter</groupId> <artifactId>spring-boot-helloworld-starter</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> </dependency> </dependencies> </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:绑定外部配置
相关推荐
自定义完整的starter*demo,包含了import所有用法,selector,register,bean,class以及常规的scan用法
Java开发案例-springboot-66-自定义starter-源代码+文档.rar Java开发案例-springboot-66-自定义starter-源代码+文档.rar Java开发案例-springboot-66-自定义starter-源代码+文档.rar Java开发案例-springboot-66-...
我们可以参照 spring-boot-starter,我们发现其中没有代码,我们在看它的 pom 中的依赖中有个 springboot-starter: ```xml <groupId>org.springframework.boot <artifactId>spring-boot-starter ``` 我们再看看...
最后,自定义Starter的目的是为了提高代码的复用性和可维护性。当你有一个通用的功能或一组组件,希望在多个Spring Boot项目中使用时,创建一个Starter是一个明智的选择。通过遵循Spring Boot的设计原则和最佳实践,...
总结,本项目【study-springboot】是一个实践案例,展示了如何在Spring Boot项目中使用自定义Starter组件。这不仅简化了配置,提高了代码的可复用性,同时也使得项目的构建和维护变得更加高效。通过分析项目文件和...
现在,让我们按照以下步骤创建一个自定义Starter: 1. **初始化项目**:使用Spring Initializr或者通过Maven Archetype创建一个新的Spring Boot项目,选择适当的依赖(如Web、Data JPA等)。 2. **创建pom.xml**:...
这个压缩包文件 "SpringBoot启动配置原理_SpringBoot自定义starters.zip" 显然是关于理解 Spring Boot 启动配置以及如何自定义 Starters 的教程资料。 **Spring Boot 启动配置原理** Spring Boot 的核心之一是其...
理解并掌握自定义starter的创建过程,将有助于我们更好地利用Spring Boot的优势,实现高效开发。 首先,我们需要了解Spring Boot starter的基本结构。一个starter通常包含以下几部分: 1. **pom.xml**:这是项目的...
2. **命名规范**:自定义Starter的Maven模块名通常以`spring-boot-starter-`开头,如`spring-boot-starter-myapp`。 3. **`spring.factories`**:在Starter的`META-INF/spring.factories`文件中添加`org.spring...
SpringBoot自定义Starter的具体流程 SpringBoot自定义Starter是一种特殊的starter,它可以根据项目的需求进行自定义和配置,从而满足不同的业务需求。在 본节中,我们将详细介绍SpringBoot自定义Starter的具体流程...
项目打包(同时处理项目所依赖的包)mvn clean install -pl emily-spring-boot-starter -am或./mvnw clean install -pl emily-spring-boot-starter -am参数全程说明-pl--projects选项后可跟随{groupId}:{artifactId}...
在`my-starter`的`pom.xml`中,添加必要的依赖,这些依赖是你自定义starter所依赖的服务或库。例如,如果你的starter用于数据库操作,你可能需要添加`spring-boot-starter-data-jpa`和`mysql-connector-java`等。 ...
在自定义的`cwp-spring-boot-starter`项目中,我们可以深入理解SpringBoot Starter的工作原理以及如何根据需求构建自己的Starter。 首先,`cwp-spring-boot-starter`这个名字暗示这是一款定制的SpringBoot启动器,...
通过创建自定义Starter,我们可以将常见的配置、依赖和初始化逻辑打包,使得在新项目中使用这些功能时,只需添加一个Maven或Gradle依赖即可。 在创建自定义Starter时,通常包括以下几个关键步骤: 1. **定义Maven...
java8 源码 springboot 学习记录 记录springboot 整合个组件在项目中的使用 二、项目目录介绍 模块名称 模块介绍 备注 springboot-actuator springboot ...springboot-aop ...自定义starter springboot-d
springboot-javafx-support 文档地址:https://springboot-javafx-support.readthedocs.io/en/latest/ 集成参考:https://segmentfault.com/a/1190000014037443
这样,当项目引入自定义starter后,Spring Boot会自动加载这些配置,简化项目的配置工作。 3. **源码分析**: 压缩包中的源码部分可能包含以下内容: - 自定义配置类:这些类通常带有`@Configuration`注解,用于...
Spring Boot的自定义starter是开发人员扩展其功能和定制化应用的一种强大方式。本文将详细介绍创建自定义starter的完整步骤,以及如何利用starter模块来优化项目配置。 首先,理解starter的作用至关重要。starter是...
自定义springboot starter