springboot构建自己的starter

前言

下面我们来通过示例来构建自己的starter pom并完成自动配置,以此来更深入的理解spring boot的工作原理。

需求

该starter提供PersonService,并实现自动配置PersonService

一、新建一个Maven工程

工程pom依赖如下:

[java] view plain copy
  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.     <groupId>com.chhliu.springboot.starter.helloworld</groupId>  
  7.     <artifactId>springboot-starter-helloworld</artifactId>  
  8.     <version>0.0.1-SNAPSHOT</version>  
  9.     <packaging>jar</packaging>  
  10.     <properties>  
  11.         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
  12.         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>  
  13.         <java.version>1.8</java.version>  
  14.     </properties>  
  15.   
  16.     <dependencies>  
  17.         <dependency><!-- 以下两个依赖是自动配置的依赖 -->  
  18.             <groupId>org.springframework.boot</groupId>  
  19.             <artifactId>spring-boot-autoconfigure</artifactId>  
  20.             <version>1.4.3.RELEASE</version>  
  21.         </dependency>  
  22.           
  23.         <dependency>  
  24.             <groupId>org.springframework.boot</groupId>  
  25.             <artifactId>spring-boot-configuration-processor</artifactId>  
  26.             <version>1.4.3.RELEASE</version>  
  27.             <optional>true</optional>  
  28.         </dependency>  
  29.     </dependencies>  
  30.   
  31.     <build>  
  32.         <plugins>  
  33.             <plugin>  
  34.                 <groupId>org.springframework.boot</groupId>  
  35.                 <artifactId>spring-boot-maven-plugin</artifactId>  
  36.             </plugin>  
  37.         </plugins>  
  38.     </build>  
  39. </project>  
二、创建自动配置类

有对这部分不了解的,可以参考我的另一篇博客spring boot中多环境配置支持

[java] view plain copy
  1. package com.chhliu.springboot.starter.helloworld;  
  2.   
  3. import org.springframework.boot.context.properties.ConfigurationProperties;  
  4.   
  5. /** 
  6.  * 描述:人员信息自动配置属性类 
  7.  * @author chhliu 
  8.  * 创建时间:2017年2月13日 下午9:05:34 
  9.  * @version 1.2.0 
  10.  */  
  11. @ConfigurationProperties(prefix="person.proterties.set")// 定义application.properties配置文件中的配置前缀  
  12. public class PersonServiceProperties {  
  13.       
  14.     // 姓名  
  15.     private String name;  
  16.     // 年龄  
  17.     private int age;  
  18.     // 性别,不配置的时候默认为person.proterties.set=man  
  19.     private String sex = "man";  
  20.     // 身高  
  21.     private String height;  
  22.     // 体重  
  23.     private String weight;  
  24.   
  25.     ……省略getter,setter方法……  
  26. }  
三、编写服务类

[java] view plain copy
  1. package com.chhliu.springboot.starter.helloworld.service;  
  2.   
  3. import com.chhliu.springboot.starter.helloworld.PersonServiceProperties;  
  4.   
  5. public class PersonService {  
  6.       
  7.     private PersonServiceProperties properties;  
  8.       
  9.     public PersonService(PersonServiceProperties properties){  
  10.         this.properties = properties;  
  11.     }  
  12.       
  13.     public PersonService(){  
  14.           
  15.     }  
  16.       
  17.     public String getPersonName(){  
  18.         return properties.getName();  
  19.     }  
  20.       
  21.     public int getPersonAge(){  
  22.         return properties.getAge();  
  23.     }  
  24.       
  25.     public String getPersonSex(){  
  26.         return properties.getSex();  
  27.     }  
  28. }  
四、自动配置类

[java] view plain copy
  1. package com.chhliu.springboot.starter.helloworld.configuration;  
  2.   
  3. import org.springframework.beans.factory.annotation.Autowired;  
  4. import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;  
  5. import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;  
  6. import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;  
  7. import org.springframework.boot.context.properties.EnableConfigurationProperties;  
  8. import org.springframework.context.annotation.Bean;  
  9. import org.springframework.context.annotation.Configuration;  
  10.   
  11. import com.chhliu.springboot.starter.helloworld.PersonServiceProperties;  
  12. import com.chhliu.springboot.starter.helloworld.service.PersonService;  
  13.   
  14. @Configuration // 配置注解  
  15. @EnableConfigurationProperties(PersonServiceProperties.class// 开启指定类的配置  
  16. @ConditionalOnClass(PersonService.class)// 当PersonService这个类在类路径中时,且当前容器中没有这个Bean的情况下,开始自动配置  
  17. @ConditionalOnProperty(prefix="person.proterties.set", value="enabled", matchIfMissing=true)// 指定的属性是否有指定的值  
  18. public class PersonServiceAutoConfiguration {  
  19.     @Autowired  
  20.     private PersonServiceProperties properties;  
  21.       
  22.     @Bean  
  23.     @ConditionalOnMissingBean(PersonService.class)// 当容器中没有指定Bean的情况下,自动配置PersonService类  
  24.     public PersonService personService(){  
  25.         PersonService personService = new PersonService(properties);  
  26.         return personService;  
  27.     }  
  28. }  
五、注册配置

1、在src/main/resources新建META-INF文件夹

2、在META-INF文件夹下新建spring.factories文件

注意:spring.factories并非是必须的,可以在启动类上添加如下注解进行自动配置

[java] view plain copy
  1. @ImportAutoConfiguration({PersonServiceAutoConfiguration.class})  

3、注册配置自动配置类

[java] view plain copy
  1. org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.chhliu.springboot.starter.helloworld.configuration.PersonServiceAutoConfiguration  

六、将上面构建的starter安装到本地

[java] view plain copy
  1. 安装命令如下:  
  2. mvn clean install  
七、新建spring boot项目,并将上面的starter作为依赖

[html] view plain copy
  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.     <groupId>com.chhliu.springboot.starter.person</groupId>  
  7.     <artifactId>springboot-starter-person</artifactId>  
  8.     <version>0.0.1-SNAPSHOT</version>  
  9.     <packaging>jar</packaging>  
  10.     <parent>  
  11.         <groupId>org.springframework.boot</groupId>  
  12.         <artifactId>spring-boot-starter-parent</artifactId>  
  13.         <version>1.5.1.RELEASE</version>  
  14.         <relativePath /> <!-- lookup parent from repository -->  
  15.     </parent>  
  16.   
  17.     <properties>  
  18.         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
  19.         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>  
  20.         <java.version>1.8</java.version>  
  21.     </properties>  
  22.   
  23.     <dependencies>  
  24.         <dependency>  
  25.             <groupId>org.springframework.boot</groupId>  
  26.             <artifactId>spring-boot-starter</artifactId>  
  27.         </dependency>  
  28.           
  29.         <dependency>  
  30.             <groupId>org.springframework.boot</groupId>  
  31.             <artifactId>spring-boot-starter-web</artifactId>  
  32.         </dependency>  
  33.   
  34.         <dependency><!-- 引入自己的starter -->  
  35.             <groupId>com.chhliu.springboot.starter.helloworld</groupId>  
  36.             <artifactId>springboot-starter-helloworld</artifactId>  
  37.             <version>0.0.1-SNAPSHOT</version>  
  38.         </dependency>  
  39.   
  40.         <dependency>  
  41.             <groupId>org.springframework.boot</groupId>  
  42.             <artifactId>spring-boot-starter-test</artifactId>  
  43.             <scope>test</scope>  
  44.         </dependency>  
  45.     </dependencies>  
  46.   
  47.     <build>  
  48.         <plugins>  
  49.             <plugin>  
  50.                 <groupId>org.springframework.boot</groupId>  
  51.                 <artifactId>spring-boot-maven-plugin</artifactId>  
  52.             </plugin>  
  53.         </plugins>  
  54.     </build>  
  55. </project>  
八、添加属性到application.properties配置文件中

[java] view plain copy
  1. person.proterties.set.name=chhliu  
  2. person.proterties.set.age=28  
  3. person.proterties.set.sex=woman  
  4. person.proterties.set.height=160  
  5. person.proterties.set.weight=50kg  
九、编写Controller

[java] view plain copy
  1. package com.chhliu.springboot.starter.person.controller;  
  2.   
  3. import org.springframework.beans.factory.annotation.Autowired;  
  4. import org.springframework.web.bind.annotation.GetMapping;  
  5. import org.springframework.web.bind.annotation.RestController;  
  6.   
  7. import com.chhliu.springboot.starter.helloworld.service.PersonService;  
  8.   
  9. @RestController  
  10. public class PersonServiceController {  
  11.     @Autowired // 自动注入PersonService  
  12.     private PersonService personService;  
  13.       
  14.     @GetMapping("get/name")  
  15.     public String getPersonName(){  
  16.         return personService.getPersonName();// 调用PersonService服务的方法  
  17.     }  
  18.       
  19.     @GetMapping("get/sex")  
  20.     public String getPersonSex(){  
  21.         return personService.getPersonSex();  
  22.     }  
  23. }  
十、测试

在浏览器中输入http://localhost:8080/get/sex

测试结果如下:

[java] view plain copy
  1. woman  
发现我们在使用我们自定义的starter过程中,并没有创建PersonService实例对象,直接通过@Autowired注解就实现了自动注入,而真正的自动注入过程则是在starter中实现的,通过上面的几个步骤,就实现了自己构建自己的starter,在spring boot中,除了官方提供的starter之外,第三方也提供了不少的starter,通过这种方式,极大的对spring boot进行的扩展

十一、延伸知识

在构建starter的过程中,涉及到一些注解,这里也做一个统一的说明

[java] view plain copy
  1. @ConditionalOnBean:当容器中有指定的Bean的条件下  
  2. @ConditionalOnClass:当类路径下有指定的类的条件下  
  3. @ConditionalOnExpression:基于SpEL表达式作为判断条件  
  4. @ConditionalOnJava:基于JVM版本作为判断条件  
  5. @ConditionalOnJndi:在JNDI存在的条件下查找指定的位置  
  6. @ConditionalOnMissingBean:当容器中没有指定Bean的情况下  
  7. @ConditionalOnMissingClass:当类路径下没有指定的类的条件下  
  8. @ConditionalOnNotWebApplication:当前项目不是Web项目的条件下  
  9. @ConditionalOnProperty:指定的属性是否有指定的值  
  10. @ConditionalOnResource:类路径下是否有指定的资源  
  11. @ConditionalOnSingleCandidate:当指定的Bean在容器中只有一个,或者在有多个Bean的情况下,用来指定首选的Bean  
  12. @ConditionalOnWebApplication:当前项目是Web项目的条件下  
阅读更多

没有更多推荐了,返回首页