SpringBoot高級-自動配置之自定義starter


前言:前面已經介紹了自動配置的很多原理,現在我們着手自己定義一個starter。

需求:自定義redis-starter,要求當導入redis坐標后,SpringBoot自動創建Jedis的Bean。正式開始之前,我們可以查看Mybatis的起步依賴是如果實現自動配置的。我這里就省略了,大家根據之前的分析文章,自己看源碼即可。

一、先創建一個SpringBoot工程redis-spring-boot-autoconfigure,該工程中添加jedis依賴,並且創建一個自動配置類RedisAutoConfigure,實現jedis實例(bean)注入到IOC容器中。

/**
 * @description:自定義自動配置類:將Jedis注入到IOC容器中
 * @date: 2020/10/10 15:08
 * @author: winson
 */
@Configuration
@EnableConfigurationProperties(RedisProperties.class)
public class RedisAutoConfigure {

    /**
     * 提供jedis的bean
     * @param redisProperties
     * @return
     */
    @Bean
    public Jedis jedis(RedisProperties redisProperties) {
        return new Jedis(redisProperties.getHost(), redisProperties.getPort());
    }

}

考慮到redis的有兩個參數(host、port)必須是可以動態賦值的,所以我們自定義一個屬性配置類RedisProperties,該屬性配置類從配置文件獲取屬性值,並設置host、port屬性的默認值,如下:

/**
 * @description:自定義屬性配置類
 * @date: 2020/10/10 15:11
 * @author: winson
 */
@ConfigurationProperties(prefix = "redis")
public class RedisProperties {

    private String host = "127.0.0.1";

    private int port = 6379;

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }
}

@EnableConfigurationProperties注解的作用:由於自動配置類RedisAutoConfigure中,注冊jedis的bean中參數需要使用到RedisProperties的bean,但無法獲取到RedisProperties的bean,所以我們可以通過這個注解,手動的將該bean注入到IOC容器中。

在resources目錄下按照SpringBoot自動配置目錄、文件名稱的規則,如下圖,新建一個自己的spring.factories文件

spring.factories文件內容:就是將自定義的自動配置類聲明為名稱為org.springframework.boot.autoconfigure.EnableAutoConfiguration的值,“\”的作用:換行,如果我們有多個自定義的自動配置類,這里可以用逗號分隔。

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.winson.jedis.config.RedisAutoConfigure

二、再創建一個SpringBoot工程redis-spring-boot-starter,引入redis-spring-boot-autoconfigure工程坐標。

<!--引入自定義的redis的starter-->
<dependency>
    <groupId>com.winson</groupId>
    <artifactId>redis-spring-boot-autoconfigure</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>

三、在測試類中引入自定義的starter,並修改引導類,做測試

        <!--引入自定義的起步依賴-->
        <dependency>
            <groupId>com.winson</groupId>
            <artifactId>redis-spring-boot-starter</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
//引導類
@SpringBootApplication
public class SpringbootEnableApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);

        Jedis jedis = context.getBean(Jedis.class);
        System.out.println(jedis);
    }
}

四、啟動程序,測試結果,自定義stater成功。

下面進行redis測試

一、首先啟動本機的redis服務

二、根據測試,修改引導類,向redis中存儲數據,並取值

@SpringBootApplication
public class SpringbootEnableApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);

        Jedis jedis = context.getBean(Jedis.class);
        jedis.set("username", "dufu");

        String username = jedis.get("username");
        System.out.println("username=" + username);
    }
}

三、啟動程序,測試結果,也成功。

下面測試修改redis連接信息,測試結果

一、測試類中添加redis的配置信息(根據屬性配置類 RedisProperties 的設置進行定義),將port的連接端口,故意寫錯,如下:

redis:
  host: 127.0.0.1
  port: 6666

二、啟動程序,測試結果:發現無法再連接到redis服務器了,說明我們設置的屬性配置類RedisProperties 是生效的

三、如果我們將連接信息修改正確,再啟動,也是沒有問題的

最后,我們可以使用Condition將我們自定義的自動配置類完善一下,使用@ConditionalOnClass(Jedis.class)與@ConditionalOnMissingBean(name = "jedis"),具體的釋義,我就不解釋。

/**
 * @description:自定義自動配置類:將Jedis注入到IOC容器中
 * @date: 2020/10/10 15:08
 * @author: winson
 */
@Configuration
@EnableConfigurationProperties(RedisProperties.class)
@ConditionalOnClass(Jedis.class)
public class RedisAutoConfigure {
    /**
     * 提供jedis的bean
     * @param redisProperties
     * @return
     */
    @Bean
    @ConditionalOnMissingBean(name = "jedis")
    public Jedis jedis(RedisProperties redisProperties) {
        return new Jedis(redisProperties.getHost(), redisProperties.getPort());
    }
}

小結:如此,我們並完成了自定義starter的示例


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM