一 概述
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代码
- <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代码
- <?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代码
- <?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、用户传入的对象信息
Java代码
- 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)开启。
Java代码
- 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)接口
Java代码
- package x.demo.springboot.starter.hw.outputformater;
- /**
- * 格式化工具
- */
- public interface OutputFormater {
- /**
- * 格式
- * @param obj 对象
- * @return 格式字符串
- */
- <T> String format(T obj);
- }
2)toString()实现
Java代码
- 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 实现
Java代码
- 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
Java代码
- 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
Java代码
- 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
Properties代码
- # 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代码
- <?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
Java代码
- <?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
Java代码
- # 应用配置
- server:
- port: 8080
- # helloworld starter 配置
- helloworld.author:
- name: foo
- roles: admin, developer
- email: foo@bar.com
(3)controller 调用 HelloWorldTemplate
Java代码
- 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注入的
Java代码
- 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代码
- <?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:绑定外部配置
转载地址:http://shihlei.iteye.com/blog/2407689