1. 程式人生 > >Spring Boot中的自定義起步依賴

Spring Boot中的自定義起步依賴

1.在pom檔案新增自動配置依賴:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-autoconfigure</artifactId>
</dependency>

2.如果是某一個jar存在,才能進行配置,則需要新增上該依賴。此處新增 httpclient:

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
</dependency>

3.編寫預設配置類:

package com.springboot.autoconfig;

import org.springframework.boot.context.properties.ConfigurationProperties;

//在application.properties中進行配置,將覆蓋下方的預設值
@ConfigurationProperties(prefix = "spring.httpclient")
public class HttpClientProperties {
    private Integer connectTimeOut = 1000;

    private Integer socketTimeOut = 10000;

    private String agent = "agent";

    private Integer maxConnPerRoute = 10;

    private Integer maxConnTotaol = 50;

    public Integer getConnectTimeOut() {
        return connectTimeOut;
    }

    public void setConnectTimeOut(Integer connectTimeOut) {
        this.connectTimeOut = connectTimeOut;
    }

    public Integer getSocketTimeOut() {
        return socketTimeOut;
    }

    public void setSocketTimeOut(Integer socketTimeOut) {
        this.socketTimeOut = socketTimeOut;
    }

    public String getAgent() {
        return agent;
    }

    public void setAgent(String agent) {
        this.agent = agent;
    }

    public Integer getMaxConnPerRoute() {
        return maxConnPerRoute;
    }

    public void setMaxConnPerRoute(Integer maxConnPerRoute) {
        this.maxConnPerRoute = maxConnPerRoute;
    }

    public Integer getMaxConnTotaol() {
        return maxConnTotaol;
    }

    public void setMaxConnTotaol(Integer maxConnTotaol) {
        this.maxConnTotaol = maxConnTotaol;
    }
}

4.編寫配置自動配置類。該類將讀取之前編寫的預設配置類在沒有配置的情況下,建立預設配置的例項:

package com.springboot.autoconfig;

import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClientBuilder;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.io.IOException;

@Configuration//註明該類是一個Java配置類
@ConditionalOnClass({HttpClient.class})//當HttpClient存在時,才進行自動配置
@EnableConfigurationProperties(HttpClientProperties.class)//讀取預設配置
public class HttpClientAutoConfiguration {

    private final HttpClientProperties properties;

    //在application.properties中進行配置,將使用其建立好的配置
    public HttpClientAutoConfiguration(HttpClientProperties properties){
        this.properties = properties;
    }

    @Bean//宣告為bean,才能自動注入
    @ConditionalOnMissingBean(HttpClient.class)//當不存在建立好的HttpClient例項,將使用該方法進行建立
    public HttpClient httpClient(){
        //構建requestConfig
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectTimeout(properties.getConnectTimeOut())//設定連線超時時間,預設1秒
                .setSocketTimeout(properties.getSocketTimeOut()).build();//設定讀超時時間,預設10秒
        HttpClient client = HttpClientBuilder.create()
                .setDefaultRequestConfig(requestConfig) //設定requestConfig
                .setUserAgent(properties.getAgent())//設定User-Agent
                .setMaxConnPerRoute(properties.getMaxConnPerRoute())//設定一個遠端IP最大的連線數
                .setMaxConnTotal(properties.getMaxConnTotaol())//設定總的連線數
                .build();
        return client;
    }

    @Bean
    @ConditionalOnBean(name="httpClient",value=HttpClient.class)//已存在HttpClient例項httpClient
    @ConditionalOnProperty(name = "spring.httpclient.testConfig", havingValue = "true")//讀取配置是否設定該屬性為true
    public HttpClient httpClient1(HttpClient httpClient) throws IOException {
        Long contentLength=httpClient.execute(new HttpGet("https://www.taobao.com")).getEntity().getContentLength();
        if(contentLength>10){
            System.out.println("test success..");
        }else{
            System.out.println("test fail..");
        }
        return httpClient;
    }
}

    @ConditionalOnMissingBean:若使用者沒有自定義某個bean,才會構建這個bean

    @ConditionalOnProperty:若使用者沒有開啟某一個屬性,則不會構建。只有開啟才會構建

    @ConditionalOnClass:某個類存在的情況下,才會去構建。

 

5.編寫測試類:

package com.springboot;

import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.util.EntityUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.io.IOException;

@RunWith(SpringRunner.class)
@SpringBootTest
public class SelfStarterApplicationTests {

    /**
     * 檢測我們編寫的自動配置HttpClientAutoConfiguration有沒有生效
     */
    @Autowired
    private HttpClient httpClient;

    @Autowired
    private HttpClient httpClient1;

    /**
     * httpclient bean 的定義
     * 有三種方式都可以讓HttpClientAutoConfiguration這個自動配置生效
     * 1.通過將自動配置所在package成為註解了@SpringBootApplication啟動類的子package
     * 2.通過定義META-INF/spring.factories檔案,裡面新增EnableAutoConfiguration與自動配置的對映關係
     * 3.通過在啟動類中添加註解EnableHttpClient,EnableHttpClient要@Import(HttpClientAutoConfiguration.class)
     * @return
     */
    @Test
    public void testHttclient() throws IOException {
        //訪問百度,輸出百度網頁
        System.out.println(EntityUtils.toString(httpClient.execute(new HttpGet("http://www.baidu.com")).getEntity()));
    }

    @Test
    public void testHttclient1() throws IOException {
        //訪問百度,輸出百度網頁
        System.out.println(EntityUtils.toString(httpClient1.execute(new HttpGet("http://www.baidu.com")).getEntity()));
    }
}

 

6.此時,由於當前package在應用程式入口類之下,所以將直接自動掃描註解@Configuration:

    執行測試類方法,可以成功返回結果。

 

    若當前package不在應用程式入口類之下,也就是正常情況下,釋出到外部作為第三方依賴時。此時將無法自動掃描到註解,解決方案有兩個:

    方案一.建立自定義註解

package com.springboot.autoconfig;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.context.annotation.Import;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(HttpClientAutoConfiguration.class)
public @interface EnableHttpClient {
}

    在註解中,使用@Import(HttpClientAutoConfiguration.class) 引入了HttpClientAutoConfiguration 配置。此時,只需要將應用程式入口新增上自定義註解即可:

package com.springboot;

import com.springboot.autoconfig.EnableHttpClient;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@EnableHttpClient
@SpringBootApplication
public class SelfStarterApplication {
    public static void main(String[] args) {
        SpringApplication.run(SelfStarterApplication.class, args);
    }
}

    方案二.建立spring.factories,定義掃描類

    spring.factories:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.springboot.autoconfig.HttpClientAutoConfiguration

    檔案放在resources目錄下的META-INF下:

    

 

    兩者的使用辨析:

  1.     使用方案二時,在添加了依賴之後,就一定會去自動掃描配置;
  2.     使用方案一時,在添加了依賴之後,還需要在應用入口新增自定義註解才能開啟自動掃描配置。

    這兩種方案在實際使用過程是都有使用的。

 

7.後續操作:使用mvn命令將專案打成Jar包,添加了本地倉庫,即可在其他專案引入其依賴並完成相關的自動配置:

<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.springboot</groupId> <artifactId>self-starter</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> </dependencies> 

 

    相關程式:https://gitee.com/LangWangHuangShiFu/self-starter