欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java SPI在數(shù)據(jù)庫(kù)驅(qū)動(dòng)、SpringBoot自動(dòng)裝配中的應(yīng)用方式

 更新時(shí)間:2025年05月07日 15:23:50   作者:心流時(shí)間  
這篇文章主要介紹了Java SPI在數(shù)據(jù)庫(kù)驅(qū)動(dòng)、SpringBoot自動(dòng)裝配中的應(yīng)用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

1. 初識(shí)SPI

  • Java SPI(Service Provider Interface)是Java提供的一種服務(wù)發(fā)現(xiàn)機(jī)制,允許第三方為某個(gè)接口或類庫(kù)提供實(shí)現(xiàn)。SPI的核心在于java.util.ServiceLoader類,它允許在運(yùn)行時(shí)查找和加載服務(wù)的實(shí)現(xiàn)。
  • 一般理解是:專門提供給服務(wù)提供者或者擴(kuò)展框架功能的開發(fā)者去使用的一個(gè)接口。

1.1 SPI的作用

  • SPI 的合作作用:解耦。
  • SPI 將服務(wù)接口和具體的服務(wù)實(shí)現(xiàn)分離開來,將服務(wù)調(diào)用方和服務(wù)實(shí)現(xiàn)者解耦,能夠提升程序的擴(kuò)展性、可維護(hù)性。修改或者替換服務(wù)實(shí)現(xiàn)并不需要修改調(diào)用方。
  • 很多框架都使用了 Java 的 SPI 機(jī)制,比如:Spring 框架、數(shù)據(jù)庫(kù)加載驅(qū)動(dòng)、日志接口、以及Dubbo 的擴(kuò)展實(shí)現(xiàn)等。

1.2 SPI的工作原理

  • 定義接口:首先,在API中定義一個(gè)接口或者抽象類作為服務(wù)接口,所有服務(wù)提供者都需要按照這個(gè)接口來實(shí)現(xiàn)其功能。
  • 創(chuàng)建配置文件:在jar包的META-INF/services目錄下,創(chuàng)建一個(gè)以服務(wù)接口全限定名命名的文本文件,該文件中每一行寫入一個(gè)實(shí)現(xiàn)了服務(wù)接口的具體類的全限定名。
  • 服務(wù)發(fā)現(xiàn)與加載:當(dāng)應(yīng)用程序需要使用某項(xiàng)服務(wù)時(shí),通過ServiceLoader.load(ServiceInterface.class)方法動(dòng)態(tài)加載服務(wù)接口的所有實(shí)現(xiàn)類,并將其實(shí)例化。這樣,系統(tǒng)就可以在運(yùn)行時(shí)根據(jù)不同的配置加載不同的服務(wù)實(shí)現(xiàn)。
  • SPI常用于框架擴(kuò)展、插件機(jī)制以及模塊間解耦等場(chǎng)景,使得系統(tǒng)的可擴(kuò)展性和靈活性大大增強(qiáng)。例如,數(shù)據(jù)庫(kù)驅(qū)動(dòng)的加載就是Java SPI的一個(gè)典型應(yīng)用案例。

對(duì)于 Java 原生 SPI,只需要滿足下面幾個(gè)條件:

  • 定義服務(wù)的通用接口,針對(duì)通用的服務(wù)接口,提供具體的實(shí)現(xiàn)類
  • 在 src/main/resources/META-INF/services 或者 jar包的 META-INF/services/ 目錄中,新建一個(gè)文件,文件名為 接口的全名。文件內(nèi)容為該接口的具體實(shí)現(xiàn)類的全名
  • 將 spi 所在 jar 放在主程序的 classpath 中
  • 服務(wù)調(diào)用方用java.util.ServiceLoader,用服務(wù)接口為參數(shù),去動(dòng)態(tài)加載具體的實(shí)現(xiàn)類到JVM中,然后就可以正常使用服務(wù)了

1.3 SPI的三個(gè)組件:Service、Service Provider、ServiceLoader

SPI其實(shí)是一種思想:約定大于配置

簡(jiǎn)單來說就是:jdk提供一個(gè)公共API,具體的實(shí)現(xiàn)由具體的應(yīng)用程序自己完成,并約定一套規(guī)則來讓java的類加載機(jī)制發(fā)現(xiàn)實(shí)現(xiàn)類所在位置

通過這個(gè)約定,就不需要把服務(wù)放在代碼中了,通過模塊被裝配的時(shí)候就可以發(fā)現(xiàn)服務(wù)類了

  • Service:是一個(gè)公開的接口或抽象類,定義了一個(gè)抽象的功能模塊(文件名稱)
  • Service Provider:是Service的實(shí)現(xiàn)類(文件內(nèi)容)
  • ServiceLoader(java.util包下):是SPI機(jī)制中的核心組件,負(fù)責(zé)在運(yùn)行時(shí)發(fā)現(xiàn)并加載Service Provider

1.4 SPI使用場(chǎng)景

很多開源第三方j(luò)ar包都有基于SPI的實(shí)現(xiàn),在jar包META-INF/services中都有相關(guān)配置文件。

如下幾個(gè)常見的場(chǎng)景:

  • JDBC加載不同類型的數(shù)據(jù)庫(kù)驅(qū)動(dòng)
  • Slf4j日志框架
  • Dubbo框架

看看 Dubbo 的擴(kuò)展實(shí)現(xiàn),就知道 SPI 機(jī)制用的多么廣泛:

1.5 具體的SPI 源碼分析(SPI的核心就是ServiceLoader.load()方法)

  • 調(diào)用ServiceLoader.load(),創(chuàng)建一個(gè)ServiceLoader實(shí)例對(duì)象
  • 創(chuàng)建LazyIterator實(shí)例對(duì)象lookupIterator
  • 通過lookupIterator.hasNextService()方法讀取固定目錄META-INF/services/下面service全限定名文件,放在Enumeration對(duì)象configs中
  • 解析configs得到迭代器對(duì)象Iterator pending
  • 通過lookupIterator.nextService()方法初始化讀取到的實(shí)現(xiàn)類,通過Class.forName()初始化

從上面的步驟可以總結(jié)以下兩點(diǎn):

  • 實(shí)現(xiàn)類工程必須創(chuàng)建定目錄META-INF/services/,并創(chuàng)建service全限定名文件,文件內(nèi)容是實(shí)現(xiàn)類全限定名
  • 實(shí)現(xiàn)類必須有一個(gè)無參構(gòu)造函數(shù)

1.6 SPI 的優(yōu)缺點(diǎn)

優(yōu)點(diǎn):

  • 通過 SPI 機(jī)制能夠大大地提高接口設(shè)計(jì)的靈活性,可以另起jar實(shí)現(xiàn),不必寫在一個(gè)模塊中

缺點(diǎn):

  • 需要遍歷加載所有的實(shí)現(xiàn)類,不能做到按需加載,這樣效率還是相對(duì)較低的。
  • 當(dāng)多個(gè) ServiceLoader 同時(shí) load 時(shí),會(huì)有并發(fā)問題。
  • SPI 缺少實(shí)例的維護(hù),作用域沒有定義singleton和prototype的定義,不利于用戶自由定制。
  • ServiceLoader不像 Spring,只能一次獲取所有的接口實(shí)例, 不支持排序,隨著新的實(shí)例加入,會(huì)出現(xiàn)排序不穩(wěn)定的情況,作用域沒有定- 義singleton和prototype的定義,不利于用戶自由定制

2. API、SPI、JNDI釋義

  • API(Application Programming Interface)就是接口,比如java.util.List 是一個(gè)接口,是一個(gè)API
  • SPI(Service Provider Interface)是一種思想
  • JNDI(Java Naming and Directory Interface)

是Java平臺(tái)中的一種標(biāo)準(zhǔn)服務(wù),它提供了一組API,允許Java應(yīng)用程序查找和訪問命名以及目錄服務(wù)。

這個(gè)接口的設(shè)計(jì)目的是統(tǒng)一不同命名服務(wù)和目錄服務(wù)的訪問方式,使得開發(fā)人員無需關(guān)注具體的底層實(shí)現(xiàn)細(xì)節(jié),就能在分布式環(huán)境中查找、綁定和管理資源。

通過JNDI,開發(fā)者可以:

  • 命名:將對(duì)象與名稱關(guān)聯(lián)起來存儲(chǔ),并可以通過名稱來獲取這些對(duì)象。
  • 目錄服務(wù):除了基本的命名功能外,還支持屬性查詢,即根據(jù)對(duì)象的屬性信息進(jìn)行檢索。目錄服務(wù)中的條目類似于文件系統(tǒng)中的文件,每個(gè)條目都有名稱,并且可以攜帶多個(gè)屬性。

JNDI常用于以下場(chǎng)景:

  • 在Java EE應(yīng)用服務(wù)器中,配置數(shù)據(jù)源(DataSource)、EJB引用、JMS隊(duì)列和主題等資源,并通過統(tǒng)一的名字查找和使用它們。
  • 在企業(yè)級(jí)應(yīng)用中,定位網(wǎng)絡(luò)服務(wù)的位置或?qū)傩?,例如LDAP(輕量級(jí)目錄訪問協(xié)議)目錄服務(wù)中的用戶賬戶信息。
  • 簡(jiǎn)而言之,JNDI是一個(gè)抽象層,它隱藏了各種各樣的命名和目錄服務(wù)的具體實(shí)現(xiàn)細(xì)節(jié),為Java程序提供了統(tǒng)一、靈活且易于使用的編程接口。

3. SPI應(yīng)用舉例1:加載數(shù)據(jù)庫(kù)驅(qū)動(dòng)

依賴引用:

<dependency>
    <groupId>com.oracle.database.jdbc</groupId>
    <artifactId>ojdbc8</artifactId>
    <version>21.9.0.0</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.23</version>
</dependency>

SPI是JDK內(nèi)置的一種動(dòng)態(tài)擴(kuò)展點(diǎn)的實(shí)現(xiàn)。

簡(jiǎn)單來說,就是我們可以定義一個(gè)標(biāo)準(zhǔn)的接口,然后第三方的庫(kù)里面可以實(shí)現(xiàn)這個(gè)接口。

那么,程序在運(yùn)行的時(shí)候,會(huì)根據(jù)配置信息動(dòng)態(tài)加載第三方實(shí)現(xiàn)的類,從而完成功能的動(dòng)態(tài)擴(kuò)展機(jī)制。

  • 解釋圖1:

  • 解釋圖2:

在Java里面,SPI機(jī)制有一個(gè)非常典型的實(shí)現(xiàn)案例,就是數(shù)據(jù)庫(kù)驅(qū)動(dòng)java.jdbc.Driver,JDK里面定義了數(shù)據(jù)庫(kù)驅(qū)動(dòng)類Driver,它是一個(gè)接口,JDK并沒有提供實(shí)現(xiàn)。

具體的實(shí)現(xiàn)是由第三方數(shù)據(jù)庫(kù)廠商來完成的。在程序運(yùn)行的時(shí)候,會(huì)根據(jù)我們聲明的驅(qū)動(dòng)類型,來動(dòng)態(tài)加載對(duì)應(yīng)的擴(kuò)展實(shí)現(xiàn),從而完成數(shù)據(jù)庫(kù)的連接。

除此之外,在很多開源框架里面都借鑒了Java SPI的思想,提供了自己的SPI框架,比如Dubbo定義了ExtensionLoader,實(shí)現(xiàn)功能的擴(kuò)展。Spring提供了SpringFactoriesLoader,實(shí)現(xiàn)外部功能的集成。

當(dāng)服務(wù)的提供者,提供了服務(wù)接口的一種實(shí)現(xiàn)之后,在jar包的META-INF/services/目錄里同時(shí)創(chuàng)建一個(gè)以服務(wù)接口命名的文件。該文件里就是實(shí)現(xiàn)該服務(wù)接口的具體實(shí)現(xiàn)類。而當(dāng)外部程序裝配這個(gè)模塊的時(shí)候,就能通過該jar包META-INF/services/里的配置文件找到具體的實(shí)現(xiàn)類名,并裝載實(shí)例化,完成模塊的注入。通過這個(gè)約定,就不需要把服務(wù)放在代碼中了,通過模塊被裝配的時(shí)候就可以發(fā)現(xiàn)服務(wù)類了。

3.1 Jdbc連接數(shù)據(jù)庫(kù)示例代碼

有了SPI機(jī)制之后,Class.forName(“com.mysql.jdbc.Driver”);這條語句就不需要了,

java.util.ServiceLoader會(huì)負(fù)責(zé)到j(luò)ar包的META-INF/services/java.sql.Driver中獲取具體驅(qū)動(dòng)實(shí)現(xiàn)類

import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class JdbcDriverManagerDemo {

    static final String MYSQL_JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";
    private static final String MYSQL_URL = "jdbc:mysql://localhost:3306/lelele?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC";
    private static final String USER = "root";
    private static final String PASSWORD = "admin123";


    public static void main(String[] args) {


        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;

        try {
            // 有了SPI機(jī)制之后,這條語句就不要了,
            // java.util.ServiceLoader會(huì)負(fù)責(zé)到j(luò)ar包的META-INF/services/java.sql.Driver中獲取具體驅(qū)動(dòng)實(shí)現(xiàn)類

            // Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection(MYSQL_URL, USER, PASSWORD);

            ps = conn.prepareStatement("select * from xin_stu_t_bak");
            rs = ps.executeQuery();

            while (rs.next()) {
                System.out.println(rs.getInt("id"));
            }

            // 處理查詢結(jié)果
            while (rs.next()) {
                int id = rs.getInt("id");
                String name = rs.getString("name");
                System.out.println("ID: " + id + ", Name: " + name);
            }

        } catch (SQLException se) {
            // 處理SQL錯(cuò)誤
            se.printStackTrace();
        } catch (Exception e) {
            // 處理其他異常
            e.printStackTrace();
        } finally {
            // 關(guān)閉資源,確保在任何情況下都能正確關(guān)閉
            try {
                if (rs != null)
                    rs.close();
                if (ps != null)
                    ps.close();
                if (conn != null)
                    conn.close();
            } catch (SQLException se2) {
                se2.printStackTrace();
            }
        }

        System.out.println("end!");
    }
}

3.2 為什么獲取連接前不用獲取驅(qū)動(dòng)了,是怎么獲取到驅(qū)動(dòng)的?

源碼分析參照 本文章1.5節(jié) 具體的SPI 源碼分析(SPI的核心就是ServiceLoader.load()方法)

下面是獲取連接對(duì)象代碼調(diào)試中的一些斷點(diǎn)截圖

  • 3.2.1 程序開始獲取連接

  • 3.2.2 DriverManager開始初始化驅(qū)動(dòng)

  • 3.2.3 調(diào)用ServiceLoader來發(fā)現(xiàn)驅(qū)動(dòng),使用類加載器加載jar中META-INF/services/下資源文件中的實(shí)現(xiàn)類

使用線程上下文類加載器(ContextClassLoader)加載

如果不做任何的設(shè)置,Java應(yīng)用的線程的上下文類加載器默認(rèn)就是AppClassLoader。在核心類庫(kù)使用SPI接口時(shí),傳遞的類加載器使用線程上下文類加載器,就可以成功的加載到SPI實(shí)現(xiàn)的類。線程上下文類加載器在很多SPI的實(shí)現(xiàn)中都會(huì)用到。通常我們可以通過Thread.currentThread().getClassLoader()和Thread.currentThread().getContextClassLoader()獲取線程上下文類加載器。

  • 3.2.3.1 oracle驅(qū)動(dòng)具體實(shí)現(xiàn)類oracle.jdbc.OracleDriver,實(shí)現(xiàn)了java.sql.Driver

  • 3.2.3.2 mysql驅(qū)動(dòng)具體實(shí)現(xiàn)類com.mysql.cj.jdbc.Driver,實(shí)現(xiàn)了java.sql.Driver

4. SPI應(yīng)用舉例2:SpringBoot自動(dòng)裝配

4.1 SpringBoot自動(dòng)裝配借鑒了SPI思想

Spring Factories自動(dòng)裝配借用了SPI機(jī)制,區(qū)別如圖:

Spring Boot的自動(dòng)裝配機(jī)制確實(shí)與SPI(Service Provider Interface)有關(guān)聯(lián),但并不是直接使用Java標(biāo)準(zhǔn)SPI來實(shí)現(xiàn)自動(dòng)裝配。Spring Boot借鑒了SPI的思想,在其內(nèi)部設(shè)計(jì)了一套更加靈活和強(qiáng)大的自動(dòng)配置體系。

在Spring Boot中,META-INF/spring.factories文件的使用方式類似于SPI的服務(wù)提供者配置文件(META-INF/services/下資源文件),它允許jar包聲明自己提供的自動(dòng)配置類。這些自動(dòng)配置類通過條件注解(如@ConditionalOnClass、@ConditionalOnBean等)來檢查應(yīng)用環(huán)境并決定是否生效,從而實(shí)現(xiàn)了根據(jù)項(xiàng)目依賴和運(yùn)行時(shí)環(huán)境進(jìn)行自動(dòng)裝配的功能。

因此,雖然Spring Boot沒有完全采用Java SPI的標(biāo)準(zhǔn)流程,但其自動(dòng)裝配過程中對(duì)第三方庫(kù)和服務(wù)的發(fā)現(xiàn)和加載機(jī)制受到了SPI思想的啟發(fā),并在此基礎(chǔ)上進(jìn)行了擴(kuò)展和創(chuàng)新。

另:

META-IF/spring.factories是在Maven引入的Jar包中,每一個(gè)Jar都有自己META-IF/spring.factories,所以SpringBoot是去每一個(gè)Jar包里面尋找META-IF/spring.factories,而不是我的項(xiàng)目中存在META-IF/spring.factories(當(dāng)然也可以存在,但是我項(xiàng)目的META-IF/spring.factories肯定沒有類似以下這些東西)

4.2 Spring Boot 的自動(dòng)裝配(Auto-configuration)原理

@SpringBootApplication注解作用圖:

好處:簡(jiǎn)化了配置

Springboot的SPI機(jī)制是怎么實(shí)現(xiàn)的?

  • 程序啟動(dòng),注冊(cè)配置類處理器
  • Spring刷新上下文,執(zhí)行配置類處理器
  • 掃描spring.factories將得到的BeanDefinition注冊(cè)到容器
  • spring實(shí)例化/初始化這些BeanDefinition

Spring Boot 的自動(dòng)裝配(Auto-configuration)原理(上面也是)

啟動(dòng)類與@SpringBootApplication注解:

  • Spring Boot應(yīng)用通常包含一個(gè)主入口類,上面會(huì)標(biāo)注@SpringBootApplication注解。
  • 這個(gè)注解包含了@Configuration、@EnableAutoConfiguration和@ComponentScan三個(gè)注解
  • 其中@EnableAutoConfiguration是開啟自動(dòng)裝配的關(guān)鍵。

@EnableAutoConfiguration:

  • @EnableAutoConfiguration注解指示Spring Boot根據(jù)項(xiàng)目的classpath和已存在的Bean來自動(dòng)配置應(yīng)用程序。
  • 它會(huì)掃描項(xiàng)目依賴中所有jar包的META-INF/spring.factories文件,這些文件定義了哪些自動(dòng)配置類應(yīng)該被應(yīng)用到當(dāng)前項(xiàng)目中。

spring.factories中的自動(dòng)配置類:

  • 各個(gè)Spring Boot Starter模塊在它們的jar包里都提供了一個(gè)spring.factories文件
  • 該文件中列出了一系列org.springframework.boot.autoconfigure.EnableAutoConfiguration對(duì)應(yīng)的實(shí)現(xiàn)類全名。

條件化裝配:

  • 自動(dòng)配置類本身使用了Spring Boot提供的條件化裝配機(jī)制,例如@ConditionalOnClass、@ConditionalOnMissingBean等注解。
  • 這意味著只有當(dāng)滿足特定條件時(shí)(如類路徑中有某個(gè)類、沒有用戶自定義的同類型Bean等),才會(huì)實(shí)例化并注冊(cè)相應(yīng)的自動(dòng)配置Bean。

覆蓋默認(rèn)配置:

  • 如果開發(fā)者想要自定義某部分配置或者完全禁用某個(gè)自動(dòng)配置,可以通過創(chuàng)建自己的配置類或在application.properties/application.yml中設(shè)置屬性值來實(shí)現(xiàn)。
  • Spring Boot會(huì)優(yōu)先考慮用戶自己定義的Bean或?qū)傩耘渲?,從而?shí)現(xiàn)了靈活的擴(kuò)展和配置覆蓋。

自定義自動(dòng)配置:

  • 開發(fā)者還可以編寫自己的自動(dòng)配置類,通過添加@Configuration注解,并利用條件裝配注解來自定義特定場(chǎng)景下的自動(dòng)化配置邏輯。

另:META-INF下另一個(gè)文件MANIFEST.MF的作用

  • MANIFEST.MF 是Java應(yīng)用程序和JAR文件中用于存儲(chǔ)元數(shù)據(jù)(metadata)的一個(gè)重要文件。它位于JAR文件的META-INF目錄下,包含了關(guān)于該JAR包及其組件的重要信息。
  • MANIFEST.MF是Java應(yīng)用打包和部署過程中不可或缺的一部分,為Java虛擬機(jī)(JVM)提供了有關(guān)如何加載和執(zhí)行JAR內(nèi)容的關(guān)鍵指導(dǎo)信息。

在JAR文件中,MANIFEST.MF 文件常見的用途包括:

Main-Class聲明:對(duì)于可執(zhí)行的JAR文件(也稱為Runnable JAR或Self-executable JAR),需要在MANIFEST.MF文件中指定一個(gè)主類(Main-Class)。例如:

Main-Class: com.example.Main

這樣,用戶可以直接通過命令行 java -jar myapp.jar 來運(yùn)行這個(gè)JAR程序。

Class-Path聲明:用于定義當(dāng)前JAR文件依賴的其他外部JAR文件的路徑。例如:

Class-Path: lib/library.jar lib/anotherlibrary.jar

這樣,當(dāng)運(yùn)行此JAR時(shí),Java會(huì)自動(dòng)加載指定路徑下的庫(kù)。

Sealed指示:可以用來表示JAR是否被密封(sealed),即所有包內(nèi)的類都必須來自同一個(gè)代碼源,以增強(qiáng)安全性。

簽名信息:如果JAR文件被數(shù)字簽名,那么相關(guān)的簽名證書、簽名者信息等也會(huì)記錄在MANIFEST.MF中。

服務(wù)提供者信息:在實(shí)現(xiàn)Java SPI(Service Provider Interface)時(shí),MANIFEST.MF也可以包含ServiceProvider-Impl條目,列出實(shí)現(xiàn)了某個(gè)接口的服務(wù)提供者的全限定類名。

OSGi Bundle信息:在OSGi框架中,每個(gè)Bundle都有自己的MANIFEST.MF文件,其中包含了Bundle的標(biāo)識(shí)符、版本、導(dǎo)入導(dǎo)出的包、激活器等重要信息。

5. Spring Boot Starter

  • Spring Boot Starter 是 Spring Boot 框架中的一種模塊化設(shè)計(jì),旨在簡(jiǎn)化項(xiàng)目的初始化和依賴管理。它們是一組預(yù)配置的依賴項(xiàng)集合,每個(gè)Starter都針對(duì)特定的功能場(chǎng)景,例如數(shù)據(jù)訪問、Web服務(wù)、安全控制等。
  • Spring Boot Starter通過預(yù)先集成并配置好了一系列功能組件,為開發(fā)者快速搭建應(yīng)用提供了極大便利。

使用Spring Boot Starter的主要優(yōu)點(diǎn)包括:

  • 統(tǒng)一入口:只需要在Maven或Gradle構(gòu)建文件中引入一個(gè)Starter依賴,就可以自動(dòng)獲得一組相關(guān)的庫(kù)以及對(duì)應(yīng)的默認(rèn)配置。
  • 約定優(yōu)于配置:Starter包含了基于最佳實(shí)踐的默認(rèn)配置,極大地減少了開發(fā)者在項(xiàng)目啟動(dòng)階段需要編寫的配置代碼量。
  • 易用性與一致性:無論開發(fā)何種功能的應(yīng)用程序,都可以遵循相同的模式來引入依賴,使得團(tuán)隊(duì)成員易于理解和操作。
  • 減少版本沖突:由于Starter中的所有依賴版本都已經(jīng)協(xié)調(diào)一致,因此可以避免不同組件之間的版本不兼容問題。

例如,spring-boot-starter-web 包含了開發(fā)Web應(yīng)用程序所需的所有基本依賴,如Spring MVC、Tomcat服務(wù)器等;而 spring-boot-starter-data-jpa 則包含了使用JPA進(jìn)行數(shù)據(jù)庫(kù)持久化的相關(guān)依賴。

6. 只有Spring Boot Starter有spring.factories文件嗎

并非只有Spring Boot Starter才有spring.factories文件。spring.factories 文件是Spring Boot框架為了實(shí)現(xiàn)自動(dòng)配置(Auto-Configuration)和SPI(Service Provider Interface)機(jī)制而使用的一種約定。雖然它通常與Spring Boot Starter一起使用,但并非Spring Boot Starter特有的。

在任何Java項(xiàng)目中,只要符合Spring Boot的自動(dòng)裝配規(guī)則,都可以創(chuàng)建自己的META-INF/spring.factories文件來聲明自定義的自動(dòng)配置類或者其他擴(kuò)展點(diǎn)。這意味著即使不是官方提供的Spring Boot Starter模塊,開發(fā)者也可以編寫自己的模塊,并在其jar包中包含spring.factories文件來提供額外的自動(dòng)配置服務(wù)。

所以,spring.factories文件不僅限于Spring Boot Starter,而是所有遵循Spring Boot規(guī)范并希望通過這種方式進(jìn)行擴(kuò)展的模塊都可能包含的一個(gè)核心配置文件。

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java Bean與Map之間相互轉(zhuǎn)化的實(shí)現(xiàn)方法

    Java Bean與Map之間相互轉(zhuǎn)化的實(shí)現(xiàn)方法

    這篇文章主要介紹了Java Bean與Map之間相互轉(zhuǎn)化的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • Java實(shí)戰(zhàn)項(xiàng)目 圖書管理系統(tǒng)

    Java實(shí)戰(zhàn)項(xiàng)目 圖書管理系統(tǒng)

    這篇文章主要介紹了使用java SSM jsp mysql maven設(shè)計(jì)實(shí)現(xiàn)的精品圖書管理系統(tǒng),是一個(gè)很好的實(shí)例,對(duì)大家的學(xué)習(xí)和工作具有借鑒意義,建議收藏一下
    2021-09-09
  • SpringBoot讀取配置文件的五種方法總結(jié)

    SpringBoot讀取配置文件的五種方法總結(jié)

    這篇文章主要為大家詳細(xì)介紹了SpringBoot讀取配置文件的五種方法,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)SpringBoot有一定幫助,需要的可以參考一下
    2022-08-08
  • Java求兩個(gè)正整數(shù)的最大公約數(shù)和最小公倍數(shù)

    Java求兩個(gè)正整數(shù)的最大公約數(shù)和最小公倍數(shù)

    這篇文章主要介紹了輸入兩個(gè)正整數(shù)m和n,求其最大公約數(shù)和最小公倍數(shù),需要的朋友可以參考下
    2017-02-02
  • Java中將File轉(zhuǎn)化為MultipartFile的操作

    Java中將File轉(zhuǎn)化為MultipartFile的操作

    這篇文章主要介紹了Java中將File轉(zhuǎn)化為MultipartFile的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-10-10
  • Feign調(diào)用可重試的最佳方案分享

    Feign調(diào)用可重試的最佳方案分享

    通過spring-retry框架集合Feign去實(shí)現(xiàn)重試機(jī)制,可以為每個(gè)調(diào)用實(shí)現(xiàn)不同的重試機(jī)制,那這究竟是如何做到的呢,本文將為大家詳細(xì)講講
    2023-01-01
  • 從dubbo zookeeper注冊(cè)地址提取出zookeeper地址的方法

    從dubbo zookeeper注冊(cè)地址提取出zookeeper地址的方法

    今天小編就為大家分享一篇關(guān)于從dubbo zookeeper注冊(cè)地址提取出zookeeper地址的方法,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2018-12-12
  • java如何讀取resources目錄和同級(jí)目錄文件

    java如何讀取resources目錄和同級(jí)目錄文件

    介紹了Java中讀取resources目錄和同級(jí)目錄文件的方法,并討論了在IDE和發(fā)布環(huán)境中可能遇到的問題,通過測(cè)試發(fā)現(xiàn),執(zhí)行目錄可能會(huì)影響文件讀取,建議在使用`user.dir`時(shí)注意jar包的運(yùn)行目錄問題
    2024-12-12
  • Java實(shí)現(xiàn)讀取設(shè)置pdf屬性信息

    Java實(shí)現(xiàn)讀取設(shè)置pdf屬性信息

    這篇文章主要為大家詳細(xì)介紹了如何使用Java實(shí)現(xiàn)讀取設(shè)置pdf屬性信息,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-01-01
  • Java實(shí)現(xiàn)輸出數(shù)字三角形實(shí)例代碼

    Java實(shí)現(xiàn)輸出數(shù)字三角形實(shí)例代碼

    大家好,本篇文章主要講的是Java實(shí)現(xiàn)輸出三角形實(shí)例代碼,感興趣的同學(xué)趕快來看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽
    2022-01-01

最新評(píng)論