Spring Boot Starterの分析と実践 | JD Cloudテクニカルチーム

序章

Java 開発者にとって、Spring フレームワークはほぼ必須です。これは、エンタープライズ アプリケーションの開発に広く使用されているオープンソースの軽量フレームワークです。近年では、従来の Spring フレームワークをベースに、Spring のすべての機能を提供するだけでなく、開発者にとって使いやすい Spring Boot が登場しました。Spring Boot を使用するとき、さまざまな Spring Boot Starter に遭遇することがよくあります spring-boot-starter-webこの依存関係をプロジェクトに追加するだけで、アプリケーションの開発を開始できます。インポート後 spring-boot-starter-data-jdbc 、データベースに接続するためのデータベース接続情報を構成ファイルに入力するだけです。さらに、ビジネス コードを変更せずに、データ ソース コンポーネントの依存関係を自由に切り替えることができます。Spring Boot Starter はどのように適応しますか? Spring Boot Starter を自分で実装できますか? この記事では、Spring Boot Starter の原理を分析し、カスタム Spring Boot Starter コンポーネントを実装します。

1. Spring Boot スターターとは何ですか?

Spring Boot Starter は Spring Boot の重要な概念であり、構成を簡素化するのに役立つ依存関係記述子です。Web アプリケーションを構築する必要がある場合、すべての依存パッケージを調べてプロジェクトの依存関係管理に 1 つずつ追加する必要はありません。次の例のように、必要な構成は 1 つだけです spring-boot-starter-web

上記の例から、かなり少量のコードで REST アプリケーションを作成しました。Spring では公式に多数のスターターが提供されており、サードパーティでもスターターをカスタマイズできますが、これらを区別するために、スターターは次のように標準化されています: ; サードパーティが提供するスターター名は次のとおりspring-boot-starter-xxxですxxx-spring-boot-starter

2. Spring Boot Starterの解析

Starter の概念と REST アプリケーションを迅速に作成する方法については前に紹介しました。REST インターフェイスの開発は、依存関係と数行のコードを追加するだけで実行できます。では、Spring Boot と Starter を使用せずにどうやって開発するのでしょうか? Spring Boot Starter はどのように機能しますか? 次に、例として Web サービスと Dubbo サービスを開発することで、純粋な Spring と Spring Boot Starter をそれぞれ分析します。

環境に依存する

  • JDK1.8

  • メイブン 3

  • Tomcat 8 (Web コンテナサーバーの起動が必要)

  • spring-webmvc 4.3.30.RELEASE

  • ダボ 2.7.23

開発プロセス

  1. 最初に紹介します。これは標準の Maven ディレクトリ構造と依存コンテンツです。 demo-service 

    <dependencies>
        <!-- SpringMVC -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>4.3.30.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
        </dependency>
        <!-- 此处需要导入databind包即可, jackson-annotations、jackson-core都不需要显示自己的导入了-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.8</version>
        </dependency>
    
        <!-- Dubbo -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo</artifactId>
            <version>2.7.23</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-x-discovery</artifactId>
            <version>5.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.8.0</version>
        </dependency>
    
        <!-- Demo API -->
        <dependency>
            <groupId>com.demo</groupId>
            <artifactId>demo-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
    
  2. Spring XML で実行するには依然として Java Web と Web コンテナに依存する必要があるため、Web 構成ファイルも必要であり、コンテンツは SpringMVC エントリを構成します。 web/WEB-INF/web.xml 

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
             version="4.0">
    
        <!-- Spring监听器 -->
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
    
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:dubbo.xml</param-value>
        </context-param>
    
        <servlet>
            <servlet-name>springmvc</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:mvc.xml</param-value>
            </init-param>
        </servlet>
    
        <servlet-mapping>
            <servlet-name>springmvc</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    </web-app>
    
  3. SpringMVC設定ファイルとDubbo設定ファイル mvc.xml  dubbo.xml

    <?xml version="1.0" encoding="utf-8" ?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:mvc="http://www.springframework.org/schema/mvc"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    
        <context:component-scan base-package="com.demo.controller"/>
    
        <!-- 开启 MVC 注解驱动 -->
        <mvc:annotation-driven/>
    
        <!-- 访问静态资源 -->
        <mvc:default-servlet-handler/>
    </beans>
    
    <?xml version="1.0" encoding="utf-8" ?>
    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
    
        <!-- Dubbo -->
        <dubbo:application name="demo-service"/>
        <dubbo:registry address="zookeeper://127.0.0.1:2181"/>
        <dubbo:protocol name="dubbo" port="20880"/>
        <bean id="demoServiceImpl" class="com.demo.provider.DemoServiceImpl"/>
        <dubbo:service interface="com.demo.api.DemoService" ref="demoServiceImpl"/>
    </beans>
    
  4. 書き込みコントローラー インターフェイスと Dubbo RPC インターフェイス

    package com.demo.controller;
    
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class HelloController {
    
        @GetMapping(value = "/say/hello")
        public HelloEntity sayHello() {
            return new HelloEntity("Hello World");
        }
    
    }
    
    package com.demo.provider;
    
    import com.demo.api.DemoService;
    import com.demo.dto.HelloEntity;
    
    public class DemoServiceImpl implements DemoService {
    
        @Override
        public HelloEntity sayHello() {
            return new HelloEntity("Hello World");
        }
    }
    
  5. 上記は独立して実行できません。実行するには、上記をパッケージ化してTomcat に入れる必要があります。 war 

分析する

上記の開発プロセスから、入り口はすべて にあることがわかります web.xml 。リスナーとサーブレット、および初期化パラメータ dubbo.xml と が ありますmvc.xmlSpring Boot が登場する前は、Spring は通常、XML 設定を使用して Bean を記述するか、アノテーション駆動型およびコンテキスト スキャン メソッドを設定して XML 内の Bean を解析していました。したがって、ここには 2 つの XML ファイルがあることがわかります。ソースコードを解析した結果、XMLタグ解析からBean解析までの流れを以下のように整理しました。次のように:

  1. Tomcat によってロードを開始し、Spring がリスナーとサーブレットを通じて XML をロードおよび解析できるようにします。 web.xml 

  2. カスタム タグが解析されるまで、 XML 名前空間が見つかるかタグが見つかります。 BeanDefinitionParserDelegate#parseCustomElement  mvc:xxx  dubbo:xxx 

  3. DefaultNamespaceHandlerResolver 処理ロジック: すべての jar を遅延読み込み方式(パスはこれである必要があります) でロードしてキャッシュし、名前空間 URI を通じて対応する処理クラスを見つけます。SpringMVC および Dubbo 名前空間処理クラスは次のとおりです。 META-INF/spring.handlers  handlerMappings  MvcNamespaceHandler  DubboNamespaceHandler

  4. MvcNamespaceHandler と でそれぞれメソッドを実装しました。内容は次のとおりです。このメソッドはSpringMVC タグと Dubbo タグを対応して  登録します  。前のステップでは、 label に従ってラベルが取得され 、対応する Bean が Spring IOC コンテナに登録されました。登録ロジックはこの記事の焦点では​​ないため、ここでは繰り返しません。ここまでで SpringMVC と Dubbo のロード処理が完了しました。 DubboNamespaceHandler  NamespaceHandler#init 


    init BeanDefinitionParserNamespaceHandlerSupport#parsersDefaultNamespaceHandlerResolverBeanDefinitionParser

上記の読み込みプロセスから、Spring Boot の前には Spring は主に XML 設定に依存して起動していたことがわかります。XML でカスタム タグをロードし、対応する名前空間を見つけて、クラスパスをスキャンして META-INF/spring.handlers名前空間処理クラスを見つけ、現在のタグを解析します。

スプリングブーツ

環境に依存する

  • JDK1.8

  • メイブン 3

  • スプリングブート 2.6.9

  • ダボ 2.7.23

開発プロセス

  1. ディレクトリ構造と Maven依存関係の内容 demo-spring-boot 

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    
        <!-- dubbo -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>2.7.23</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-x-discovery</artifactId>
            <version>5.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.8.0</version>
        </dependency>
    
        <dependency>
            <groupId>com.demo</groupId>
            <artifactId>demo-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
    
  2. 申請エントリー DemoSpringBootApplication

    @SpringBootApplication
    public class DemoSpringBootApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(DemoSpringBootApplication.class, args);
        }
    
    }
    
  3. application.yml ファイルの内容はDubboの設定のみです

    dubbo:
      application:
        name: demo-provider
      protocol:
        port: 20880
        name: dubbo
      registry:
        address: zookeeper://127.0.0.1:2181
    
  4. 書き込みコントローラー インターフェイスと Dubbo RPC インターフェイス

    package com.demo.controller;
    
    import com.demo.dto.HelloEntity;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class HelloController {
    
        @GetMapping(value = "/say/hello")
        public HelloEntity sayHello() {
            return new HelloEntity("Hello World");
        }
    
    }
    
    package com.demo.provider;
    
    import com.demo.api.DemoService;
    import com.demo.dto.HelloEntity;
    
    @DubboService 
    public class DemoServiceImpl implements DemoService {
    
        @Override
        public HelloEntity sayHello() {
            return new HelloEntity("Hello World");
        }
    }
    
  5. Tomcat が埋め込まれているため、メソッドを直接実行するだけでアプリケーションを実行できます。 spring-boot-starter-web  DemoSpringBootApplication#main 

分析する

開発プロセスからは、最初に分析エントリを見つける方法はありません。唯一のエントリは にあります。ソース コード分析後、次のフローが得られます。 DemoSpringBootApplication 

  1. アプリケーションクラスにはアノテーションがあり、アノテーションは次の 3 つのアノテーションで構成されます。 DemoSpringBootApplication  @SpringBootApplication 

    • @SpringBootConfiguration、現在のクラスを構成クラスとしてマークします。これはアノテーション関数と一貫性があり、アノテーションが付けられたクラスは Spring の XML バージョンのコンテナーに対応します。 @Configuration  @Configuration 

    • @EnableAutoConfiguration、自動配線を有効にするキーで、次構成されます。 @AutoConfigurationPackage  @Import(AutoConfigurationImportSelector.class)

    • @ComponentScan、現在のクラスパスに従って、などのアノテーションを含むクラスをスキャンします。これは Spring XML のものと同等です @Service@Controller context:component-scan

  2. Spring Boot はインポートされたクラスを自動アセンブルし、 ClassPath からすべての jar パッケージの内容をスキャンするように呼び出します。これは に渡されるため、キーの値のみを返し、完全修飾クラス名の文字列配列を取得します @EnableAutoConfiguration  AutoConfigurationImportSelector  SpringFactoriesLoader#loadFactoryNames  META-INF/spring.factories  EnableAutoConfiguration.class org.springframework.boot.autoconfigure.EnableAutoConfiguration  configurations

  3. configurations 重複排除と宣言的除外の後、次のフィルタリングと自動アセンブリが実行されます。

    configurations = getConfigurationClassFilter().filter(configurations)
    

    フィルタの取得とフィルタリングの実行の 2 つの部分に分かれています。

    • getConfigurationClassFilter()また、Key の値をSpringFactoriesLoader#loadFactoryNames 見つけることによって、現在フィルターは、および の3 つだけです。META-INF/spring.factories  org.springframework.boot.autoconfigure.AutoConfigurationImportFilterOnBeanConditionOnClassConditionOnClassCondition 

    • フィルタリングが実行されると、構成クラスの、、などを含む条件付きアノテーションに従って、一部の構成クラスがフィルタリングされます。たとえば、仕様を有効にするには、以下の。 @ConditionOnBean@ConditionalOnClass@ConditionalOnWebApplication  WebMvcAutoConfiguration  @ConditionOnWebApplication 

  4. さまざまな Configuration 構成クラスを導入した後、構成クラスを結合してSpring Bean の解析とインジェクションを完了すると同時に、Spring Boot は開発者向けに多くの柔軟なインジェクションも提供します。 @Bean  @ConditionalXXX 

以上がSpring Bootの自動組み立て処理です。Spring Boot は、  @Configuration Spring XML の代わりにアノテーション付き構成クラスを使用して Bean インジェクションを完了します。次に、SpringFactoriesLoader 最終ロード META-INF/spring.factories の自動構成クラスを実装して、自動アセンブリプロセスを実現します。「合意は設定よりも重要である」という考えに基づいて、開発されたスターターを有効にしたい場合は、Spring Boot 合意に従う必要があります。

まとめ

Spring と Spring Boot の開発プロセスを比較すると、Web と Dubbo の独立したアプリケーション開発を完了するときに Spring Boot が使用するコードと構成が比較的少ないことがわかります。これは、Spring Boot の主要機能である Spring Boot Starter の自動配線機能のおかげです。自動構成は、自動構成の一部である一部のクラスを定義する必要性を排除することで、開発プロセスを簡素化し、スピードアップするのに役立ちます。

SPI

上記の分析から、どちらも、インポートされた jar パッケージ内の設定ファイルをロードして、対応するクラス、つまりSPI (Service Provider Interface)をロードするメカニズムを使用していることがわかりました。  

SPI (Service Provider Interface) は、フレームワークのスケーラビリティを向上させる Java の組み込みサービス検出メカニズムです。

Java SPI

Java の組み込み SPI は、クラスパスおよび jar パッケージ ディレクトリの下にあるインターフェイスの完全修飾名で指定されたファイルをclass を通じて解析し、ファイル内で指定されたインターフェイス実装クラスをロードして呼び出しを完了します。 java.util.ServiceLoader  META-INF/services 

ただし、Java SPI には次のような欠点があります。

  • オンデマンドの読み込みは実現できないため、すべての実装を走査してインスタンス化し、ループ内で必要な実装を見つける必要があります。

  • クラスのインスタンスを複数同時にマルチスレッドで使用する場合は安全ではありません ServiceLoader 

  • 実装クラスをロードできない場合、本当の理由ではない例外がスローされ、エラーを特定するのが困難になります。

春のSPI

Spring SPIはJava SPIを踏襲していますが、Java SPIと実装に違いはありますが、コアの仕組みは同じであり、Springのソースコードを変更することなくSpringフレームワークの拡張開発を実現できます。

  • Spring XML では、 namespaceUri 名と NamespaceHandler 名のマッピングを解析して生成し、必要に応じてそれらをインスタンス化します。 DefaultNamespaceHandlerResolver  spring.handlers

  • Spring Boot では、ファイルを解析し、指定されたインターフェイスのすべての実装クラス/完全修飾クラス名を返す役割を果たします。 SpringFactoriesLoader  spring.factories 

スプリングブート 2.7.0

この記事では、Spring Boot 自動アセンブリは SPI を使用して指定された自動アセンブリ クラス名にロードしますが、 Spring Boot 2.7.0以降、自動アセンブリ SPI メカニズムは変更され、破棄されます。コードは削除され、変更は次のようになります。 EnableAutoConfiguration   META-INF/spring.factories 

  • 新しい注釈:@AutoConfiguration の代わりに @Configuration

  • 自動アセンブリを読み取るクラス ファイルの場所は次のように変更されMETA-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports、実装クラスの完全修飾クラス名は一度に 1 行になります。

  • 解析を担当します。 はインターフェイス名のプレースホルダーです org.springframework.boot.context.annotation.ImportCandidates#load  META-INF/spring/%s.imports  %s 

3. Spring Boot Staterの実践

データベース操作を使用するとき、またはデータベース操作を待機するときに、通常、次ようなデータベース データ ソース接続プールが導入されます。同時に、ビジネス コードを変更せずに依存関係を自由に切り替えることができるため、開発者は次の点に注意を払う必要はありません。ここでは、Starter もこの互換性を実装します。なぜなら、私たちは分散ロックスターターを開発しており、Zookeeper、Redis などの複数の実装を持っているからです。ここでは Spring Boot 2.6.9 バージョンを使用します。 spring-boot-starter-jdbc  spring-boot-starter-jpa HikariCPDBCP

開発する

プロジェクトの構造と Maven の依存関係

└── src
    ├── main
    │   ├── java
    │   │   └── com.demo.distributed.lock
    │   │      ├── api
    │   │      │   ├── DistributedLock.java
    │   │      │   └── LockInfo.java
    │   │      ├── autoconfigure
    │   │      │   ├── DistributedLockAutoConfiguration.java
    │   │      │   └── DistributedLockProperties.java
    │   │      ├── redis
    │   │      │   └── RedisDistributedLockImpl.java
    │   │      └── zookeeper
    │   │          └── ZookeeperDistributedLockImpl.java
    │   └── resources
    │       └── META-INF
    │           └── spring.factories
<dependencies>
    <!-- Spring Boot 自动装配注解 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-autoconfigure</artifactId>
    </dependency>

    <!-- 生成 META-INF/spring-configuration-metadata.json -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <optional>true</optional>
    </dependency>

    
    <!-- Zookeeper -->
    <dependency>
        <groupId>org.apache.curator</groupId>
        <artifactId>curator-framework</artifactId>
        <version>5.1.0</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.apache.curator</groupId>
        <artifactId>curator-recipes</artifactId>
        <version>5.1.0</version>
        <scope>provided</scope>
    </dependency>

    <!-- Redis -->
    <dependency>
        <groupId>org.redisson</groupId>
        <artifactId>redisson</artifactId>
        <version>3.23.1</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

依存関係では、Zookeeper と Redis の依存関係がコンパイルとテストのフェーズで使用されるように設定されており、プロジェクトとともにリリースされないことがわかります。つまり、パッケージ化時に依存関係は持ち込まれません。この設定は Spring Boot Starter でより効果的です。 provided 

分散ロックのインターフェイスと実装

インターフェース

public interface DistributedLock {

    /**
     * 加锁
     */
    LockInfo tryLock(String key, long expire, long waitTime);

    /**
     * 释放锁
     */
    boolean release(LockInfo lock);

}

Redisの実装

public class RedisDistributedLockImpl implements DistributedLock {

    private final RedissonClient client;

    public RedisDistributedLockImpl(RedissonClient client) {
        this.client = client;
    }

    @Override
    public LockInfo tryLock(String key, long expire, long waitTime) {
        //do something
        return null;
    }

    @Override
    public boolean release(LockInfo lock) {
        //do something
        return true;
    }
}

Zookeeperの実装

public class ZookeeperDistributedLockImpl implements DistributedLock {

    private final CuratorFramework client;

    public ZookeeperDistributedLockImpl(CuratorFramework client) {
        this.client = client;
    }

    @Override
    public LockInfo tryLock(String key, long expire, long waitTime) {
        return null;
    }

    @Override
    public boolean release(LockInfo lock) {
        return false;
    }
} 

DistributedLockAutoConfiguration 構成クラス

@EnableConfigurationProperties(DistributedLockProperties.class)
@Import({DistributedLockAutoConfiguration.Zookeeper.class, DistributedLockAutoConfiguration.Redis.class})
public class DistributedLockAutoConfiguration {

    @Configuration
    @ConditionalOnClass(CuratorFramework.class)
    @ConditionalOnMissingBean(DistributedLock.class)
    @ConditionalOnProperty(name = "distributed.lock.type", havingValue = "zookeeper",
            matchIfMissing = true)
    static class Zookeeper {

        @Bean
        CuratorFramework curatorFramework(DistributedLockProperties properties) {
            //build CuratorFramework client
            return null;
        }


        @Bean
        ZookeeperDistributedLockImpl zookeeperDistributedLock(CuratorFramework client) {
            return new ZookeeperDistributedLockImpl(client);
        }
    }


    @Configuration
    @ConditionalOnClass(RedissonClient.class)
    @ConditionalOnMissingBean(DistributedLock.class)
    @ConditionalOnProperty(name = "distributed.lock.type", havingValue = "redis",
            matchIfMissing = true)
    static class Redis {

        @Bean
        RedissonClient redissonClient(DistributedLockProperties properties) {
            //build RedissonClient client
            return null;
        }

        @Bean
        RedisDistributedLockImpl redisDistributedLock(RedissonClient client) {
            return new RedisDistributedLockImpl(client);
        }
    }
}
  • @EnableConfigurationProperties(DistributedLockProperties.class) 構成クラスの「プロパティー」情報を開くと、構成ファイル内の情報がプロパティー・クラスに挿入されます。

  • @Configuration 設定メモ

  • @ConditionalOnClass(CuratorFramework.class) 条件付きアノテーションを有効にするには、現在の構成クラスが存在する必要があり、Redis のサブ構成クラスは同じです。 CuratorFramework 

  • @ConditionalOnMissingBean(DistributedLock.class) 条件付きアノテーション、 Bean の現在の構成クラスはSpring に存在せず、Redis のサブ構成クラスは同じです。 DistributedLock 

  • @ConditionalOnProperty(name = "distributed.lock.type", havingValue = "zookeeper", matchIfMissing = true) 条件付きアノテーション、ここでは設定ファイルが有効であると判断し、設定されていない場合はデフォルトとみなされ、Redisのサブ設定クラスが同じになります。 distributed.lock.type  zookeeper  zookeeper

  • @Bean メソッドによって返された Bean を Spring IOC コンテナに注入します。メソッドの入力パラメータには依存する Bean が含まれます。

春の工場

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.demo.distributed.lock.autoconfigure.DistributedLockAutoConfiguration

ファイルを置くだけで、Spring Boot によってロードされます。これは、コントラクトが構成よりも大きいという Spring Boot の考え方でもあります。 resource/META-INF/spring.factories 

使用

Maven の依存関係

<dependencies>
    <dependency>
        <groupId>com.demo</groupId>
        <artifactId>distributed-lock-spring-boot-starter</artifactId>
        <version>1.0.0-SNAPSHOT</version>
    </dependency>
</dependencies>

<profiles>
    <profile>
        <id>dev</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <dependencies>
            <!-- Redis -->
            <dependency>
                <groupId>org.redisson</groupId>
                <artifactId>redisson</artifactId>
                <version>3.23.1</version>
            </dependency>
        </dependencies>
    </profile>
    <profile>
        <id>test</id>
        <dependencies>
            <dependency>
                <groupId>org.apache.curator</groupId>
                <artifactId>curator-framework</artifactId>
                <version>5.1.0</version>
            </dependency>
            <dependency>
                <groupId>org.apache.curator</groupId>
                <artifactId>curator-recipes</artifactId>
                <version>5.1.0</version>
            </dependency>
        </dependencies>
    </profile>
</profiles>

ここでは、Maven プロファイル機能がさまざまな環境と組み合わされて、分散ロックのさまざまな基盤となる実装に依存します。同時に、Spring Boot は、さまざまな構成をロードするための Spring Boot プロファイルも提供します。開発、テスト、およびさまざまな基盤となるレイヤーを使用できます。運用環境と同時に、Maven プロファイルを仕様に従ってロードできます。異なる環境で異なる分散ロック実装を使用する問題を解決するために、異なる依存関係がパッケージ化されています。 -P 

コードの使用法

private final DistributedLock distributedLock;

public DemoServiceImpl(DistributedLock distributedLock) {
    this.distributedLock = distributedLock;
}

public void test() {
    LockInfo lock = null;
    try {
        lock = distributedLock.tryLock("demo", 1000, 1000);
        //do something
    } finally {
        if (lock != null) {
            distributedLock.release(lock);
        }
    }
}

ビジネス コードは Spring Boot Starter 条件付きアノテーション + Maven プロファイルと組み合わせたインターフェイスに依存しているため、どの分散ロック実装がそれに依存しているかに関係なく、コードを変更する必要はありません。

4. まとめ

この記事では、Spring Boot と Starter が登場する前は、従来の Spring XML を使用して Web アプリケーションを開発する場合、開発者は多くの依存関係を参照する必要があり、Bean とその依存関係を記述するために多くの XML コードを記述する必要があることを紹介します。また、SPI を使用してカスタム タグをロードし、Bean をロードして注入する方法も学習しました。@Configuration Spring Boot Starter は、より最新の構成メソッドを提供します。このメソッドは、SPI メカニズムを通じて自動アセンブリ構成クラスをロードし、 従来の Spring XML を置き換えて Bean インジェクションを完了し、それによって多数の XML 構成を排除します。最後に、一連の @ConditionalXXX アノテーションと Maven プロファイルを使用してカスタマイズして分散ロック Spring Boot Starter コンポーネントを開発し、開発を完了しました。このようにして、複数の分散ロック実装と互換性があり、ビジネス コードを変更することなく、異なる環境で異なる分散ロック実装を使用できます。

著者: JD Retail 陳延青

出典: JD Cloud 開発者コミュニティ

MyBatis-Flex の MyBatis-Plus 盗用に関する明確化 Chrome の代替品であると主張する Arc ブラウザ 1.0 が正式にリリース OpenAI が Android バージョンを正式にリリース ChatGPT VS Code で名前の難読化圧縮が最適化され、組み込み JS が 20% 削減されました。 LK-99: 最初の室温常圧超伝導体? マスク氏は「ゼロ元で購入」し、@x Twitter アカウントを強奪したPython 運営委員会は PEP 703 提案を受け入れる予定で、 グローバル インタープリタ ロックをオプションにする . システムのオープンソースで無料のパケット キャプチャ ソフトウェアへのアクセス数Stack Overflow大幅に下落し、マスク氏はLLMに取って代わられたと述べた
{{名前}}
{{名前}}

おすすめ

転載: my.oschina.net/u/4090830/blog/10092132