自定義starter:java
以咱們web場景啓動器的自動配置類WebMVCAutoConfiguration類爲例:web
@Configuration @ConditionalOnWebApplication( type = Type.SERVLET ) @ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class}) @ConditionalOnMissingBean({WebMvcConfigurationSupport.class}) @AutoConfigureOrder(-2147483638) @AutoConfigureAfter({DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class}) public class WebMvcAutoConfiguration {
在自動配置類中,常常能夠看到以下的註解:spring
@Configuration
指明這是一個配置類@ConditionalOnXXX
在指定條件成立的狀況下自動配置類生效@AutoConfigureAfter
指定自動配置類的順序@Bean
給容器中添加組件@ConfigurationPropertie
結合相關xxxProperties
類來綁定相關的配置@EnableConfigurationProperties
讓xxxProperties
生效加入到容器中並且,自動配置類要能加載,須要將他們配置在類路徑下的META-INF/spring.factories
.例如springBoot的apache
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\ org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
啓動器只用來作依賴導入,他是一個空jar文件,僅提供輔助性的依賴管理,這些依賴可能用於自動裝配或者其餘類庫。他是專門來寫一個自動配置模塊;啓動器依賴自動配置;別人只須要引入啓動器(starter)就能夠了。springboot
mybatis-spring-boot-starter;自定義啓動器名-spring-boot-startermybatis
<?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>com.zhaoyi.starter</groupId> <artifactId>hello-spring-boot-stater</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>com.zhaoyi.starter</groupId> <artifactId>hello-spring-boot-starter-autoconfigurer</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> </dependencies> </project>
其實就是引入另一個自動配置的座標信息便可,至此,啓動器模塊無需加入任何代碼,咱們接下來完善自動配置模塊。app
hello-spring-boot-stater
我這裏starter少寫一個r了,請僞裝他是有r的。maven
<?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>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.1.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.zhaoyi.starter</groupId> <artifactId>hello-spring-boot-starter-autoconfigurer</artifactId> <version>0.0.1-SNAPSHOT</version> <name>hello-spring-boot-starter-autoconfigurer</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> </dependencies> </project>
刪除一些其餘沒必要要的依賴,只須要springboot-starer
以及spring-boot-configuration-processor
,這是全部starer都須要的基本配置。spring-boot
下方的build也記得刪除,由於咱們會刪除主程序的啓動類,插件會報錯。測試
spring-boot-configuration-processor
是2.x必須引入的包。
在starter包路徑下添加三個以下類文件
package com.zhaoyi.starter; import org.springframework.boot.context.properties.ConfigurationProperties; @ConfigurationProperties(prefix = "zhaoyi.hello") public class HelloProperties { private String prefix; private String suffix; public String getPrefix() { return prefix; } public void setPrefix(String prefix) { this.prefix = prefix; } public String getSuffix() { return suffix; } public void setSuffix(String suffix) { this.suffix = suffix; } }
該類配置了Properties類,並強調了與配置文件的zhaoyi.hello前綴的配置關聯,支持prefix以及suffix兩項配置。
package com.zhaoyi.starter; public class HelloService { private HelloProperties helloProperties; public HelloProperties getHelloProperties() { return helloProperties; } public void setHelloProperties(HelloProperties helloProperties) { this.helloProperties = helloProperties; } public String sayHello(String name){ return helloProperties.getPrefix() + name + helloProperties.getSuffix(); } }
該服務類用於對外提供服務,咱們能夠看到他提供了一個方法,用於返回前綴+傳入參數+後綴這樣的字符串,同時提供了一個setter接口,用於HelloServiceAutoConfiguration進行Properties設置。
package com.zhaoyi.starter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration @ConditionalOnWebApplication @EnableConfigurationProperties(HelloProperties.class)//屬性文件生效 public class HelloServiceAutoConfiguration { @Autowired private HelloProperties helloProperties; @Bean public HelloService helloService(){ HelloService helloService = new HelloService(); helloService.setHelloProperties(helloProperties); return helloService; } }
該自動配置類和咱們以前查看的springboot的自動配置類的源碼很類似,他使用HelloProperties做爲注入屬性對象,同時往容器中注入一個名爲helloService
的bean,提供給用戶消費。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.zhaoyi.starter.HelloServiceAutoConfiguration
至此咱們的工做作完了:首先,咱們寫了自動配置類,這個類給容器中給容器中添加HelloService組件,該組件用到的屬性是和HelloProperties綁定的,而HelloProperties的值又是能夠經過從配置文件中進行配置(綁定了前綴zhaoyi.hello),咱們這裏支持兩個屬性即prefix和suffix。最後,咱們經過在resources即類路徑下新建META-INF/spring.factories
文件保證springboot啓動後配置類會加載生效。
接下來咱們將整個項目發佈到本地倉庫中(點擊maven install)。先install自動配置模塊,而後在install啓動器模塊(由於啓動器模塊是依賴於自動配置模塊的,所以在後面install)。
咱們會發現,兩個jar包已經被安裝在了咱們的本地倉庫中,接下來,咱們就寫一個測試網站來試試咱們本身的starter吧。
建立一個web項目,選擇web模塊,並在pom文件中引入咱們上一節中本身建立的starter,導入座標信息:
<?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>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.1.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>demo</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.zhaoyi.starter</groupId> <artifactId>hello-spring-boot-stater</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
還記得咱們的自定義starter嗎?他提供了兩個配置項,因而,咱們到配置文件中添加此配置。
server: port: 8085 zhaoyi: hello: prefix: this is prefix suffix: this is suffix
該配置文件指明瞭服務啓動端口8085,同時,設置了咱們自定義場景的配置:prefix以及suffix。好了,萬事俱備,接下來就是消費該場景啓動器提供給咱們的服務了。建立一個controller:
package com.example.demo.controller; import com.zhaoyi.starter.HelloService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class IndexController { @Autowired private HelloService helloService; @RequestMapping("/hello") public String index(){ String hello = helloService.sayHello("hello"); return hello; } }
在咱們springboot啓動的時候,springboot已經將helloService這個bean注入到了容器中,咱們直接注入到controller中就可使用了,而且咱們配置的值也會隨之裝配到HelloProperties對象上,接下來訪問http://localhost:8085/hello
,就能夠獲得如下的輸出:
this is prefixhellothis is suffix
也就在咱們傳入的參數先後分別添加配置的指定值。
至此,咱們的自定義starter完成了,在實際開發中,咱們本身編寫starter的場景其實並很少見,可是你也許會發現不少有趣的事情,若是能把一些經常使用的模塊這樣提取出來,供後來者使用,何嘗不是一種對本身的提高。