[SpringBoot de l'entrée à la compétence] Chapitre 3 Démarreur Springboot, conteneur, analyse d'annotation commune

Trois, analyse Springboot

3.1 Méthode d'importation

3.1.1 Hériter du projet parent

spring-boot-starter-parentIl peut être hérité dans le projet .

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>${springboot.version}</version>
</parent>

spring-boot-starter-parentÀ l'intérieur , le projet hérite également d'un autre projet parent spring-boot-dependencies.

insérez la description de l'image ici

3.1.2 Gestion des dépendances

Introduisez les dépendances de Springboot via la gestion des dépendances spring-boot-dependencies.

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>${springboot.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

3.2 Numéro de version

3.2.1 Numéro de version par défaut

Déclarez les numéros de version de presque toutes les dépendances couramment utilisées dans le développement dans spring-boot-starter-parentle projet parent de . spring-boot-dependenciesPar conséquent, il n'est pas nécessaire de prêter attention au numéro de version dans le projet Springboot et la correspondance de version est automatique.

<properties>
    <activemq.version>5.16.5</activemq.version>
    <antlr2.version>2.7.7</antlr2.version>
    <appengine-sdk.version>1.9.97</appengine-sdk.version>
    <artemis.version>2.19.1</artemis.version>
    <aspectj.version>1.9.7</aspectj.version>
    <assertj.version>3.21.0</assertj.version>
    <atomikos.version>4.0.6</atomikos.version>
    <awaitility.version>4.1.1</awaitility.version>
    <build-helper-maven-plugin.version>3.2.0</build-helper-maven-plugin.version>
    <byte-buddy.version>1.11.22</byte-buddy.version>
    <caffeine.version>2.9.3</caffeine.version>
    <cassandra-driver.version>4.13.0</cassandra-driver.version>
    <classmate.version>1.5.1</classmate.version>
    <commons-codec.version>1.15</commons-codec.version>
    <commons-dbcp2.version>2.9.0</commons-dbcp2.version>
    <commons-lang3.version>3.12.0</commons-lang3.version>
    <commons-pool.version>1.6</commons-pool.version>
    <commons-pool2.version>2.11.1</commons-pool2.version>
    <couchbase-client.version>3.2.7</couchbase-client.version>
    <db2-jdbc.version>11.5.7.0</db2-jdbc.version>
    <dependency-management-plugin.version>1.0.11.RELEASE</dependency-management-plugin.version>
    <derby.version>10.14.2.0</derby.version>
    <dropwizard-metrics.version>4.2.10</dropwizard-metrics.version>
    <ehcache.version>2.10.9.2</ehcache.version>
    <ehcache3.version>3.9.9</ehcache3.version>
    <elasticsearch.version>7.15.2</elasticsearch.version>
    <embedded-mongo.version>3.0.0</embedded-mongo.version>
    <flyway.version>8.0.5</flyway.version>
    <freemarker.version>2.3.31</freemarker.version>
    <git-commit-id-plugin.version>4.9.10</git-commit-id-plugin.version>
    <glassfish-el.version>3.0.4</glassfish-el.version>
    <glassfish-jaxb.version>2.3.6</glassfish-jaxb.version>
    <glassfish-jstl.version>1.2.6</glassfish-jstl.version>
    <groovy.version>3.0.11</groovy.version>
    <gson.version>2.8.9</gson.version>
    <h2.version>1.4.200</h2.version>
    <hamcrest.version>2.2</hamcrest.version>
    <hazelcast.version>4.2.5</hazelcast.version>
    <hazelcast-hibernate5.version>2.2.1</hazelcast-hibernate5.version>
    <hibernate.version>5.6.9.Final</hibernate.version>
    <hibernate-validator.version>6.2.3.Final</hibernate-validator.version>
    <hikaricp.version>4.0.3</hikaricp.version>
    <hsqldb.version>2.5.2</hsqldb.version>
    <htmlunit.version>2.54.0</htmlunit.version>
    <httpasyncclient.version>4.1.5</httpasyncclient.version>
    <httpclient.version>4.5.13</httpclient.version>
    <httpclient5.version>5.1.3</httpclient5.version>
    <httpcore.version>4.4.15</httpcore.version>
    <httpcore5.version>5.1.3</httpcore5.version>
    <infinispan.version>12.1.12.Final</infinispan.version>
    <influxdb-java.version>2.22</influxdb-java.version>
    <jackson-bom.version>2.13.3</jackson-bom.version>
    <jakarta-activation.version>1.2.2</jakarta-activation.version>
    <jakarta-annotation.version>1.3.5</jakarta-annotation.version>
    <jakarta-jms.version>2.0.3</jakarta-jms.version>
    <jakarta-json.version>1.1.6</jakarta-json.version>
    <jakarta-json-bind.version>1.0.2</jakarta-json-bind.version>
    <jakarta-mail.version>1.6.7</jakarta-mail.version>
    <jakarta-management.version>1.1.4</jakarta-management.version>
    <jakarta-persistence.version>2.2.3</jakarta-persistence.version>
    <jakarta-servlet.version>4.0.4</jakarta-servlet.version>
    <jakarta-servlet-jsp-jstl.version>1.2.7</jakarta-servlet-jsp-jstl.version>
    <jakarta-transaction.version>1.3.3</jakarta-transaction.version>
    <jakarta-validation.version>2.0.2</jakarta-validation.version>
    <jakarta-websocket.version>1.1.2</jakarta-websocket.version>
    <jakarta-ws-rs.version>2.1.6</jakarta-ws-rs.version>
    <jakarta-xml-bind.version>2.3.3</jakarta-xml-bind.version>
    <jakarta-xml-soap.version>1.4.2</jakarta-xml-soap.version>
    <jakarta-xml-ws.version>2.3.3</jakarta-xml-ws.version>
    <janino.version>3.1.7</janino.version>
    <javax-activation.version>1.2.0</javax-activation.version>
    <javax-annotation.version>1.3.2</javax-annotation.version>
    <javax-cache.version>1.1.1</javax-cache.version>
    <javax-jaxb.version>2.3.1</javax-jaxb.version>
    <javax-jaxws.version>2.3.1</javax-jaxws.version>
    <javax-jms.version>2.0.1</javax-jms.version>
    <javax-json.version>1.1.4</javax-json.version>
    <javax-jsonb.version>1.0</javax-jsonb.version>
    <javax-mail.version>1.6.2</javax-mail.version>
    <javax-money.version>1.1</javax-money.version>
    <javax-persistence.version>2.2</javax-persistence.version>
    <javax-transaction.version>1.3</javax-transaction.version>
    <javax-validation.version>2.0.1.Final</javax-validation.version>
    <javax-websocket.version>1.1</javax-websocket.version>
    <jaxen.version>1.2.0</jaxen.version>
    <jaybird.version>4.0.6.java8</jaybird.version>
    <jboss-logging.version>3.4.3.Final</jboss-logging.version>
    <jdom2.version>2.0.6.1</jdom2.version>
    <jedis.version>3.7.1</jedis.version>
    <jersey.version>2.35</jersey.version>
    <jetty-el.version>9.0.52</jetty-el.version>
    <jetty-jsp.version>2.2.0.v201112011158</jetty-jsp.version>
    <jetty-reactive-httpclient.version>1.1.11</jetty-reactive-httpclient.version>
    <jetty.version>9.4.48.v20220622</jetty.version>
    <jmustache.version>1.15</jmustache.version>
    <johnzon.version>1.2.18</johnzon.version>
    <jolokia.version>1.7.1</jolokia.version>
    <jooq.version>3.14.16</jooq.version>
    <json-path.version>2.6.0</json-path.version>
    <json-smart.version>2.4.8</json-smart.version>
    <jsonassert.version>1.5.0</jsonassert.version>
    <jstl.version>1.2</jstl.version>
    <jtds.version>1.3.1</jtds.version>
    <junit.version>4.13.2</junit.version>
    <junit-jupiter.version>5.8.2</junit-jupiter.version>
    <kafka.version>3.0.1</kafka.version>
    <kotlin.version>1.6.21</kotlin.version>
    <kotlin-coroutines.version>1.5.2</kotlin-coroutines.version>
    <lettuce.version>6.1.8.RELEASE</lettuce.version>
    <liquibase.version>4.5.0</liquibase.version>
    <log4j2.version>2.17.2</log4j2.version>
    <logback.version>1.2.11</logback.version>
    <lombok.version>1.18.24</lombok.version>
    <mariadb.version>2.7.5</mariadb.version>
    <maven-antrun-plugin.version>3.0.0</maven-antrun-plugin.version>
    <maven-assembly-plugin.version>3.3.0</maven-assembly-plugin.version>
    <maven-clean-plugin.version>3.1.0</maven-clean-plugin.version>
    <maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
    <maven-dependency-plugin.version>3.2.0</maven-dependency-plugin.version>
    <maven-deploy-plugin.version>2.8.2</maven-deploy-plugin.version>
    <maven-enforcer-plugin.version>3.0.0</maven-enforcer-plugin.version>
    <maven-failsafe-plugin.version>2.22.2</maven-failsafe-plugin.version>
    <maven-help-plugin.version>3.2.0</maven-help-plugin.version>
    <maven-install-plugin.version>2.5.2</maven-install-plugin.version>
    <maven-invoker-plugin.version>3.2.2</maven-invoker-plugin.version>
    <maven-jar-plugin.version>3.2.2</maven-jar-plugin.version>
    <maven-javadoc-plugin.version>3.3.2</maven-javadoc-plugin.version>
    <maven-resources-plugin.version>3.2.0</maven-resources-plugin.version>
    <maven-shade-plugin.version>3.2.4</maven-shade-plugin.version>
    <maven-source-plugin.version>3.2.1</maven-source-plugin.version>
    <maven-surefire-plugin.version>2.22.2</maven-surefire-plugin.version>
    <maven-war-plugin.version>3.3.2</maven-war-plugin.version>
    <micrometer.version>1.8.7</micrometer.version>
    <mimepull.version>1.9.15</mimepull.version>
    <mockito.version>4.0.0</mockito.version>
    <mongodb.version>4.4.2</mongodb.version>
    <mssql-jdbc.version>9.4.1.jre8</mssql-jdbc.version>
    <mysql.version>8.0.29</mysql.version>
    <nekohtml.version>1.9.22</nekohtml.version>
    <neo4j-java-driver.version>4.4.6</neo4j-java-driver.version>
    <netty.version>4.1.78.Final</netty.version>
    <netty-tcnative.version>2.0.53.Final</netty-tcnative.version>
    <okhttp3.version>3.14.9</okhttp3.version>
    <oracle-database.version>21.3.0.0</oracle-database.version>
    <pooled-jms.version>1.2.4</pooled-jms.version>
    <postgresql.version>42.3.6</postgresql.version>
    <prometheus-client.version>0.12.0</prometheus-client.version>
    <quartz.version>2.3.2</quartz.version>
    <querydsl.version>5.0.0</querydsl.version>
    <r2dbc-bom.version>Arabba-SR13</r2dbc-bom.version>
    <rabbit-amqp-client.version>5.13.1</rabbit-amqp-client.version>
    <rabbit-stream-client.version>0.4.0</rabbit-stream-client.version>
    <reactive-streams.version>1.0.4</reactive-streams.version>
    <reactor-bom.version>2020.0.20</reactor-bom.version>
    <rest-assured.version>4.4.0</rest-assured.version>
    <rsocket.version>1.1.2</rsocket.version>
    <rxjava.version>1.3.8</rxjava.version>
    <rxjava-adapter.version>1.2.1</rxjava-adapter.version>
    <rxjava2.version>2.2.21</rxjava2.version>
    <saaj-impl.version>1.5.3</saaj-impl.version>
    <selenium.version>3.141.59</selenium.version>
    <selenium-htmlunit.version>2.54.0</selenium-htmlunit.version>
    <sendgrid.version>4.7.6</sendgrid.version>
    <servlet-api.version>4.0.1</servlet-api.version>
    <slf4j.version>1.7.36</slf4j.version>
    <snakeyaml.version>1.29</snakeyaml.version>
    <solr.version>8.8.2</solr.version>
    <spring-amqp.version>2.4.6</spring-amqp.version>
    <spring-batch.version>4.3.6</spring-batch.version>
    <spring-data-bom.version>2021.1.5</spring-data-bom.version>
    <spring-framework.version>5.3.21</spring-framework.version>
    <spring-hateoas.version>1.4.4</spring-hateoas.version>
    <spring-integration.version>5.5.13</spring-integration.version>
    <spring-kafka.version>2.8.7</spring-kafka.version>
    <spring-ldap.version>2.3.8.RELEASE</spring-ldap.version>
    <spring-restdocs.version>2.0.6.RELEASE</spring-restdocs.version>
    <spring-retry.version>1.3.3</spring-retry.version>
    <spring-security.version>5.6.6</spring-security.version>
    <spring-session-bom.version>2021.1.3</spring-session-bom.version>
    <spring-ws.version>3.1.3</spring-ws.version>
    <sqlite-jdbc.version>3.36.0.3</sqlite-jdbc.version>
    <sun-mail.version>1.6.7</sun-mail.version>
    <thymeleaf.version>3.0.15.RELEASE</thymeleaf.version>
    <thymeleaf-extras-data-attribute.version>2.0.1</thymeleaf-extras-data-attribute.version>
    <thymeleaf-extras-java8time.version>3.0.4.RELEASE</thymeleaf-extras-java8time.version>
    <thymeleaf-extras-springsecurity.version>3.0.4.RELEASE</thymeleaf-extras-springsecurity.version>
    <thymeleaf-layout-dialect.version>3.0.0</thymeleaf-layout-dialect.version>
    <tomcat.version>9.0.64</tomcat.version>
    <unboundid-ldapsdk.version>4.0.14</unboundid-ldapsdk.version>
    <undertow.version>2.2.18.Final</undertow.version>
    <versions-maven-plugin.version>2.8.1</versions-maven-plugin.version>
    <webjars-locator-core.version>0.48</webjars-locator-core.version>
    <wsdl4j.version>1.6.3</wsdl4j.version>
    <xml-maven-plugin.version>1.0.2</xml-maven-plugin.version>
    <xmlunit2.version>2.8.4</xmlunit2.version>
</properties>

On peut donc conclure des dépendances du fichier pom ci-dessus :

Pour les dépendances qui existent dans dependencies, lorsque nous importons le projet, la dépendance n'a pas besoin d'écrire le numéro de version par défaut ; tandis que les dependenciesdépendances qui ne sont pas gérées dans celui-ci doivent naturellement déclarer le numéro de version.

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
</dependencies>

insérez la description de l'image ici

3.2.2 Modifier le numéro de version par défaut

Introduisez la configuration suivante dans le projet actuel pour écraser la configuration dans le projet parent afin de modifier le numéro de version de mysql.

<properties>
    <mysql.version>5.1.49</mysql.version>
</properties>

insérez la description de l'image ici

3.3 Lanceur

Que sont les Starters du projet Springboot ?

**Springboot extrait tous les scénarios fonctionnels et crée les Starters (starters) un par un. Il vous suffit d'importer toutes les dépendances de ces scénarios liés aux Starters dans le projet. ** Importez le lanceur de n'importe quelle scène que vous souhaitez utiliser.

Tous les starters officiels suivent une convention de nommage similaire : spring-boot-starter-*, où *est un type spécifique d'application.

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

spring-boot-starter-web : aidez-nous à importer les composants dont dépend le module Web pour un fonctionnement normal.

Les noms de démarrage tiers ne doivent pas spring-bootcommencer par , car il s'agit d'une règle réservée aux composants officiels de Spring Boot. Par exemple, il existe un projet de démarrage tiers appelé thirdpartyproject, qui devrait normalement être nommé thirdpartyproject-spring-boot-starter.

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.1.10</version>
</dependency>

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.2.2</version>
</dependency>

Le niveau de dépendance le plus bas de tous les activateurs de scène spring-boot-starter.

insérez la description de l'image ici

Introduction aux starters dans les documents officiels

3.4 Configuration automatique

Le lanceur se compose de deux cœurs :

  1. Importer les dépendances liées au module ;
  2. configuration automatique ;

La configuration automatique est l'une des fonctions principales de Spring Boot, qui élimine ou réduit de nombreuses configurations indépendantes de l'entreprise dont nous avons besoin lors du développement d'applications Spring.

Et l'idée derrière n'est pas nouvelle, il utilise un principe appelé convention sur configuration (convention sur configuration), il fait des hypothèses raisonnables (c'est-à-dire des conventions) à l'avance, tant que vous suivez ses conventions, vous n'avez pas besoin Avec une configuration supplémentaire, la fonctionnalité qu'il fournit peut être utilisée directement, éliminant ainsi le besoin d'une configuration explicite. Par exemple, maven supposera que le répertoire du code source est le répertoire src/main/java sous le répertoire racine du projet par défaut. Si vous suivez cette structure de répertoires, vous n'avez pas besoin de dire à maven quel est le répertoire du code source. Ce principe est souvent utilisé par divers frameworks, car les frameworks font souvent des configurations correspondantes selon ces conventions. Si ces configurations répondent à nos besoins, nous n'avons rien à faire, il suffit de les accepter et de les utiliser facilement. Seulement quand Quand ces configurations ne le font pas répondre à nos besoins, nous devons faire des ajustements.

Ensuite, prenez spring-boot-starter-web comme exemple pour voir quelles configurations automatisées ont été faites.

3.4.1 Conteneur Tomcat

  • Introduire les dépendances Tomcat intégrées ;
  • Configurez Tomcat ;

3.4.2 SpringMVC

  • Introduire un ensemble complet de composants SpringMVC ;
  • Configurer les composants communs SpringMVC ;
    • Front Controller dispatcherServlet
    • Mappeur de gestionnaires requestMappingHandlerMapping
    • Demande d'adaptateur de gestionnaireMappingHandlerAdapter
    • vue résolveur
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class Springboot02BootApplication {
    
    

    public static void main(String[] args) {
    
    
        //获取SpringIOC容器,ConfigurableApplicationContext是ApplicationContext接口的子接口
        ConfigurableApplicationContext context = SpringApplication.run(Springboot02BootApplication.class, args);

        //获取Spring容器中所有Bean的名称
        String[] beanDefinitionNames = context.getBeanDefinitionNames();
        for (String name : beanDefinitionNames) {
    
    
            System.out.println(name);
        }
    }
}

3.4.3 Fonction Web

  • Introduire les fonctions Web courantes ;
  • Configurez les fonctionnalités Web :
    • télécharger multipartResolver
    • Mappage de traitement JSONJackson2HttpMessageConverter
    • Gestion des exceptions handlerExceptionResolver
    • Vérification des données d'arrière-plan mvcValidator
    • Filtre de codage de caractères characterEncodingFilter

3.4.4 Balayage des composants

Il n'est pas nécessaire de configurer l'analyse des composants. Le package d'analyse des composants par défaut est le package dans lequel se trouve la classe de démarrage, ce qui signifie que les composants du package dans lequel se trouve la classe de démarrage et tous les sous-packages en dessous seront analysés par défaut.

Si vous devez modifier le package d'analyse, ajoutez simplement l'élément de configuration scanBasePackages dans l'annotation @SpringBootApplication de la classe de démarrage ou spécifiez le chemin d'analyse via l'annotation @ComponentScan.

@SpringBootApplication(scanBasePackages = "com.newcapec")

3.4.5 Configurer les valeurs par défaut

La configuration par défaut est finalement mappée à une certaine classe, telle que : DataSourceProperties.

3.4.6 Charger les éléments de configuration automatique à la demande

Il existe de nombreux démarreurs dans Springboot, chacun avec des éléments de configuration automatiques, et toutes les fonctions de configuration automatiques se trouvent dans le package spring-boot-autoconfigure.

insérez la description de l'image ici

Remarque : Springboot ne charge pas tous les éléments de configuration automatique au démarrage, mais ouvre les éléments de configuration automatique correspondants en fonction du démarreur introduit.

3.5 Conteneur Springboot

3.5.1 @Configuration+@Bean

La configuration du bean est effectuée via les annotations @Configuration et @Bean dans le projet Springboot.

3.5.1.1 Classe de haricot

Classe de clients :

public class Customers {
    
    

    private String name;
    private Integer age;

    public Customers() {
    
    
    }

    public Customers(String name, Integer age) {
    
    
        this.name = name;
        this.age = age;
    }

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    public Integer getAge() {
    
    
        return age;
    }

    public void setAge(Integer age) {
    
    
        this.age = age;
    }

    @Override
    public String toString() {
    
    
        return "Customers{" +
            "name='" + name + '\'' +
            ", age=" + age +
            '}';
    }
}

Classe de commandes :

public class Orders {
    
    

    private String name;
    private Customers customers;

    public Orders() {
    
    
    }

    public Orders(String name) {
    
    
        this.name = name;
    }

    public Orders(String name, Customers customers) {
    
    
        this.name = name;
        this.customers = customers;
    }

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    public Customers getCustomers() {
    
    
        return customers;
    }

    public void setCustomers(Customers customers) {
    
    
        this.customers = customers;
    }

    @Override
    public String toString() {
    
    
        return "Orders{" +
            "name='" + name + '\'' +
            ", customers=" + customers +
            '}';
    }
}

3.5.1.2 Classe de configuration

@Configuration
public class MyConfig {
    
    

    @Bean
    public Customers getCustomers(){
    
    
        return new Customers("Tom", 20);
    }

    @Bean
    public Orders getOrders(){
    
    
        //在@Configuration注解的配置类中,如果直接调用@Bean标注的方法,相当于从IOC容器中获取该bean并依赖注入
        return new Orders("Tom's Order", getCustomers());
    }
}

3.5.1.3 Essais

public static void main(String[] args) {
    
    
    //获取SpringIOC容器,ConfigurableApplicationContext是ApplicationContext接口的子接口
    ConfigurableApplicationContext context = SpringApplication.run(Springboot02BootApplication.class, args);

    //获取Spring中加载的Bean
    String[] beanDefinitionNames = context.getBeanDefinitionNames();
    for (String name : beanDefinitionNames) {
    
    
        System.out.println(name);
    }

    Customers customers = context.getBean(Customers.class);
    System.out.println(customers);

    Orders orders = context.getBean(Orders.class);
    System.out.println(orders);
    
    System.out.println("是否单例:" + (customers == orders.getCustomers()));
}

insérez la description de l'image ici

  1. Le nom de la méthode de l'annotation @Bean est le nom du bean par défaut, et l'élément de configuration de la valeur de @Bean peut modifier le nom du bean .
  2. L'annotation @Bean est utilisée dans la classe de configuration pour enregistrer les composants du conteneur sur la méthode, qui est également une instance unique par défaut .
  3. Lorsque l'élément de configuration proxyBeanMethods de l'annotation @Configuration est false, le bean n'est pas un mode singleton et la valeur par défaut est true .

3.5.2 @Importer

  • L'annotation @Import implémente l'ajout d'instances au conteneur IOC de Spring via une importation rapide.
  • @Import peut être utilisé pour importer des packages tiers, et bien sûr les annotations @Bean peuvent également être utilisées, mais la façon dont les annotations @Import sont rapidement importées est plus pratique.
  • Les trois usages de @Import incluent principalement :
    1. Méthode de tableau de classe ;
    2. Méthode ImportSelector ;
    3. Méthode ImportBeanDefinitionRegistrar ;

3.5.2.1 Tableau de classes

Remplissez directement le tableau de classe et le tableau de classe peut contenir 0 ou plus.

Classe de haricot :

public class Dog {
    
    
}

public class Cat {
    
    
}

Importer dans la classe de configuration :

@Configuration
@Import({
    
    Dog.class, Cat.class})
public class MyConfig {
    
    

    @Bean
    public Customers getCustomers(){
    
    
        return new Customers("Tom", 20);
    }

    @Bean
    public Orders getOrders(){
    
    
        return new Orders("Tom's Order", getCustomers());
    }
}

insérez la description de l'image ici

Les beans importés correspondants seront ajoutés au conteneur Spring et les noms de bean dans le conteneur sont les noms de classe complets de la classe .

3.5.2.2 Sélecteur d'importation

La classe d'implémentation de l'interface ImportSelector est importée via l'annotation @Import et l'objet Bean qui doit être enregistré est défini dans sa méthode abstraite selectImports.

Classe de haricot :

public class Student {
    
    
}

public class Teacher {
    
    
}

La classe d'implémentation de l'interface ImportSelector :

public class MyImportSelector implements ImportSelector {
    
    
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
    
    
        return new String[]{
    
    "com.newcapec.bean.Student", "com.newcapec.bean.Teacher"};
    }
}

La méthode selectImports de l'interface ImportSelector :

  • Valeur de retour String[] : un tableau de chaînes représentant le nom de classe complet du composant enregistré dans le conteneur .
  • Paramètre AnnotationMetadata : indique toutes les informations d'annotation actuellement annotées par @Import.

Importer dans la classe de configuration :

@Configuration
@Import({
    
    Dog.class, Cat.class, MyImportSelector.class})
public class MyConfig {
    
    

    @Bean
    public Customers getCustomers(){
    
    
        return new Customers("Tom", 20);
    }

    @Bean
    public Orders getOrders(){
    
    
        return new Orders("Tom's Order", getCustomers());
    }
}

insérez la description de l'image ici

Il convient de noter que la méthode selectImports peut renvoyer un tableau vide mais ne peut pas renvoyer null, sinon une exception de pointeur null sera signalée.

3.5.2.3 ImportBeanDefinitionRegistrar

La classe d'implémentation de l'interface ImportBeanDefinitionRegistrar est importée via l'annotation @Import, et les objets Bean qui doivent être enregistrés sont définis dans sa méthode abstraite registerBeanDefinitions. Semblable à l'utilisation de ImportSelector, sauf que cette utilisation peut personnaliser le bean enregistré.

Classe de haricot :

public class Users {
    
    
}

La classe d'implémentation de l'interface ImportBeanDefinitionRegistrar :

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    
    

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    
    

        //指定Bean定义信息
        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Users.class);
        //注册一个Bean指定bean名称
        registry.registerBeanDefinition("users", rootBeanDefinition);
    }
}

La méthode registerBeanDefinitions de l'interface ImportBeanDefinitionRegistrar :

  • Paramètre AnnotationMetadata : indique toutes les informations d'annotation actuellement annotées par @Import.
  • Paramètre BeanDefinitionRegistry : indique qu'un bean est défini pour l'enregistrement.

Importer dans la classe de configuration :

@Configuration
@Import({
    
    Dog.class, Cat.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class MyConfig {
    
    

    @Bean
    public Customers getCustomers(){
    
    
        return new Customers("Tom", 20);
    }

    @Bean
    public Orders getOrders(){
    
    
        return new Orders("Tom's Order", getCustomers());
    }
}

3.5.3 @Conditionnel

L'annotation @Conditional peut être utilisée sur n'importe quel type ou méthode. Certains jugements conditionnels peuvent être configurés via l'annotation @Conditional. Lorsque toutes les conditions sont remplies, la cible marquée par @Conditional sera traitée par le conteneur Spring.

3.5.3.1 Annotations dérivées

insérez la description de l'image ici

3.5.3.2 Analyse de l'utilisation

@Annotation dérivée conditionnelle Fonction (les deux jugent si les conditions spécifiées sont remplies)
@ConditionnelSurJava Si la version Java du système répond aux exigences
@ConditionalOnBean Il existe une classe Bean spécifiée
@ConditionalOnMissingBean aucune classe de bean spécifiée
@ConditionalOnExpression correspond à l'expression SpEL spécifiée
@ConditionnelSurClasse a une classe spécifiée
@ConditionalOnMissingClass aucune classe spécifiée
@ConditionalOnSingleCandidate Le conteneur n'a qu'un seul bean spécifié, ou ce bean est le bean préféré
@ConditionalOnProperty L'attribut de propriété spécifié a la valeur spécifiée
@ConditionalOnResource La ressource spécifiée existe sous le chemin
@ConditionalOnWebApplication L'environnement système est l'environnement Web
@ConditionalOnNotWebApplication L'environnement système n'est pas un environnement Web
@ConditionnelOnjndi L'élément spécifié existe dans JNDI

3.5.3.3 Cas

Classe de haricot :

public class Color {
    
    
}

public class Red {
    
    
}

public class Green {
    
    
}

Classe de configuration :

@Configuration
@Import({
    
    Dog.class, Cat.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class MyConfig {
    
    

    @Bean
    public Customers getCustomers(){
    
    
        return new Customers("Tom", 20);
    }

    @Bean
    public Orders getOrders(){
    
    
        return new Orders("Tom's Order", getCustomers());
    }

    @Bean("color")
    public Color getColor(){
    
    
        return new Color();
    }

    @ConditionalOnBean(name = "color")
    @Bean("red")
    public Red getRed(){
    
    
        return new Red();
    }

    @ConditionalOnMissingBean(name = "color")
    @Bean("green")
    public Green getGreen(){
    
    
        return new Green();
    }
}

test:

public static void main(String[] args) {
    
    
    //获取SpringIOC容器,ConfigurableApplicationContext是ApplicationContext接口的子接口
    ConfigurableApplicationContext context = SpringApplication.run(Springboot02BootApplication.class, args);

    //获取Spring中加载的Bean
    String[] beanDefinitionNames = context.getBeanDefinitionNames();
    for (String name : beanDefinitionNames) {
    
    
        System.out.println(name);
    }

    Customers customers = context.getBean(Customers.class);
    System.out.println(customers);

    Orders orders = context.getBean(Orders.class);
    System.out.println(orders);

    System.out.println("是否单例:" + (customers == orders.getCustomers()));

    boolean color = context.containsBean("color");
    System.out.println("容器中是否包含color组件:" + color);

    boolean red = context.containsBean("red");
    System.out.println("容器中是否包含red组件:" + red);

    boolean green = context.containsBean("green");
    System.out.println("容器中是否包含green组件:" + green);
}

Lorsque la couleur Bean existe :

容器中是否包含color组件:true
容器中是否包含red组件:true
容器中是否包含green组件:false

Lorsque la couleur Bean n'existe pas :

容器中是否包含color组件:false
容器中是否包含red组件:false
容器中是否包含green组件:true

3.6 Analyse de démarrage de Springboot

3.6.1 Programme principal

L'ajout d'une annotation @SpringBootApplication à une classe Java ordinaire l'identifiera automatiquement comme une application Springboot, et la méthode principale de cette classe est également la méthode d'entrée du programme Springboot.

@SpringBootApplication
public class MainApplication {
    
    

    public static void main(String[] args) {
    
    
        SpringApplication.run(MainApplication.class, args);
    }
}

3.6.2 @SpringBootApplication

L'annotation de programme principale du programme SpringBoot, la classe actuelle est également la classe de configuration principale de SpringBoot.

Code source de l'annotation @SpringBootApplication :

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
    
     @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
        @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
    
    

}

Trois annotations @SpringBootConfiguration, @ComponentScan et @EnableAutoConfiguration sont impliquées ici.

3.6.3 @SpringBootConfiguration

@SpringBootConfiguration est l'annotation de classe de configuration du programme Springboot.

Code source de l'annotation @SpringBootConfiguration :

@Target({
    
    ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
@Indexed
public @interface SpringBootConfiguration {
    
    

}

Code source de l'annotation @Configuration :

@Target({
    
    ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
    
    

}

analyser:

  • L'annotation @Configuration est une annotation fournie par le framework Spring pour identifier une classe en tant que classe de configuration.
  • @SpringBootConfiguration est une annotation fournie par Springboot, indiquant qu'il s'agit d'une classe de configuration Springboot.
  • La classe de configuration est également un composant dans le conteneur, qui est le rôle de l'annotation @Component.

3.6.4 @ComponentScan

Code source de l'annotation @ComponentScan :

@Retention(RetentionPolicy.RUNTIME)
@Target({
    
    ElementType.TYPE})
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
    
    

}

analyser:

  • Spécifie d'analyser le package et d'analyser les classes sous le package et ses sous-packages.
  • @Repeatable(ComponentScans.class) : indique que dans les annotations sans annotations @Repeatable, une erreur sera signalée lors de l'utilisation des mêmes annotations au même endroit. Avec les annotations marquées avec cette méta-annotation, vous pouvez utiliser les mêmes annotations dans le même lieu. L'annotation @ComponentScan peut être utilisée plusieurs fois dans l'annotation @ComponentScans.

3.6.5 @EnableAutoConfiguration

Activez la fonction de configuration automatique.

Dans l'ère Spring précédente, le contenu xml devait être configuré ; maintenant Springboot nous aide à le configurer automatiquement, et @EnableAutoConfiguration dit à SpringBoot d'activer la fonction de configuration automatique.

Code source de l'annotation @EnableAutoConfiguration :

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
    
    

}

Deux annotations @AutoConfigurationPackage et @Import(AutoConfigurationImportSelector.class) sont impliquées ici.

3.6.6 @AutoConfigurationPackage

Package de configuration automatique, spécifiant les règles de package par défaut.

Code source de l'annotation @AutoConfigurationPackage :

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {
    
    

}

Ici encore, l'annotation @Import(AutoConfigurationPackages.Registrar.class) est impliquée.

3.6.7 @Import(AutoConfigurationPackages.Registrar.class)

Utilisez l'annotation @Import pour importer une classe AutoConfigurationPackages.Registrar afin d'enregistrer une série de composants dans le conteneur.

Code source de AutoConfigurationPackages.Registrar :

static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
    
    

    @Override
    public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
    
    
        register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));
    }

    @Override
    public Set<Object> determineImports(AnnotationMetadata metadata) {
    
    
        return Collections.singleton(new PackageImports(metadata));
    }
}

À l'aide de la fonction de débogage de point d'arrêt, vous pouvez connaître le package dans lequel se trouve la classe marquée avec l'annotation @SpringBootApplication et toutes les classes sous le sous-package, et l'analyser et l'enregistrer automatiquement dans le conteneur Spring. Dans le fichier xml utilisé lors de l'apprentissage de Spring auparavant, la fonction du package de base d'analyse des composants est la même.

insérez la description de l'image ici

3.6.8 @Import(AutoConfigurationImportSelector.class)

Utilisez l'annotation @Import pour importer une classe AutoConfigurationImportSelector afin d'enregistrer une série de composants dans le conteneur.

Une partie du code source d'AutoConfigurationImportSelector :

public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
        ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
    
    
    
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
    
    
        if (!isEnabled(annotationMetadata)) {
    
    
            return NO_IMPORTS;
        }
        AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
        return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
    }
            
    protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
    
    
        if (!isEnabled(annotationMetadata)) {
    
    
            return EMPTY_ENTRY;
        }
        AnnotationAttributes attributes = getAttributes(annotationMetadata);
        List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
        configurations = removeDuplicates(configurations);
        Set<String> exclusions = getExclusions(annotationMetadata, attributes);
        checkExcludedClasses(configurations, exclusions);
        configurations.removeAll(exclusions);
        configurations = getConfigurationClassFilter().filter(configurations);
        fireAutoConfigurationImportEvents(configurations, exclusions);
        return new AutoConfigurationEntry(configurations, exclusions);
    }
    
    protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    
    
        List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
                getBeanClassLoader());
        Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
                + "are using a custom packaging, make sure that file is correct.");
        return configurations;
    }
}

3.6.8.1 Méthode selectImports

A la ligne 99 du code source, getAutoConfigurationEntry(annotationMetadata);certains composants sont importés dans le conteneur par lots.

3.6.8.2 Méthode getAutoConfigurationEntry

A la ligne 123 du code source, l'appel List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);récupère tous les composants prêts à être importés dans le conteneur. Ces composants sont des classes de configuration automatiques, qui doivent importer tous les composants requis par une certaine scène (Starter) dans le conteneur et configurer ces composants. Avec la classe de configuration automatique, cela nous évite le travail d'écriture manuelle des composants de la fonction d'injection de configuration, etc.

insérez la description de l'image ici

3.6.8.3 Chargeur d'usine

A la ligne 178 du code source, SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());tous les composants sont obtenus en chargeant la fabrique.

3.6.8.4 fichier spring.factories

Le code source de la méthode loadFactoryNames() dans la classe SpringFactoriesLoader :

public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
    
    
    ClassLoader classLoaderToUse = classLoader;
    if (classLoader == null) {
    
    
        classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
    }

    String factoryTypeName = factoryType.getName();
    return (List)loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
}

private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
    
    
    Map<String, List<String>> result = (Map)cache.get(classLoader);
    if (result != null) {
    
    
        return result;
    } else {
    
    
        HashMap result = new HashMap();

        try {
    
    
            Enumeration urls = classLoader.getResources("META-INF/spring.factories");

            while(urls.hasMoreElements()) {
    
    
                URL url = (URL)urls.nextElement();
                UrlResource resource = new UrlResource(url);
                Properties properties = PropertiesLoaderUtils.loadProperties(resource);
                Iterator var6 = properties.entrySet().iterator();

                while(var6.hasNext()) {
    
    
                    Entry<?, ?> entry = (Entry)var6.next();
                    String factoryTypeName = ((String)entry.getKey()).trim();
                    String[] factoryImplementationNames = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
                    String[] var10 = factoryImplementationNames;
                    int var11 = factoryImplementationNames.length;

                    for(int var12 = 0; var12 < var11; ++var12) {
    
    
                        String factoryImplementationName = var10[var12];
                        ((List)result.computeIfAbsent(factoryTypeName, (key) -> {
    
    
                            return new ArrayList();
                        })).add(factoryImplementationName.trim());
                    }
                }
            }

            result.replaceAll((factoryType, implementations) -> {
    
    
                return (List)implementations.stream().distinct().collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
            });
            cache.put(classLoader, result);
            return result;
        } catch (IOException var14) {
    
    
            throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var14);
        }
    }
}

Vérifiez le code source pour savoir que Springboot charge le fichier META-INF/spring.factories sous le chemin de classe par défaut.

insérez la description de l'image ici

Recherchez le fichier META-INF/spring.factories dans le package spring-boot-autoconfigure-2.6.9.jar.

De la ligne 25 à la ligne 158, il y a un total de 133 composants à importer, ce qui est cohérent avec le nombre affiché dans le débogage.

insérez la description de l'image ici

3.6.8.5 Activer la configuration automatique à la demande

Bien que 130 configurations automatiques soient chargées par défaut, Springboot va quand même assembler les règles @Conditional selon les conditions, et enfin les configurer à la demande. Lorsque le code est exécuté jusqu'à la ligne 129, nous pouvons voir qu'il n'y a que 24 classes de configuration automatique qui doivent être importées.

insérez la description de l'image ici

3.6.8.6 Modifier la configuration par défaut

@Bean
@ConditionalOnBean(MultipartResolver.class)
@ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME)
public MultipartResolver multipartResolver(MultipartResolver resolver) {
    
    
    // Detect if the user has created a MultipartResolver but named it incorrectly
    return resolver;
}
  • Springboot configurera tous les composants en bas par défaut, mais si l'utilisateur le configure lui-même, la priorité de l'utilisateur sera donnée.
  • Les paramètres formels de la méthode annotée @Bean peuvent rechercher le composant dans le conteneur.

3.6.8.5 Exemple 1

Cherchez-en un, voici RedisAutoConfiguration, voyez comment redis est configuré

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
@Import({
    
     LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {
    
    

    @Bean
    @ConditionalOnMissingBean(name = "redisTemplate")
    @ConditionalOnSingleCandidate(RedisConnectionFactory.class)
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
    
    
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnSingleCandidate(RedisConnectionFactory.class)
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
    
    
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }
}

analyser:

  • @Configuration : Indique que cette classe est une classe de configuration.
  • @ConditionalOnClass(RedisOperations.class) : cette configuration est activée si la classe RedisOperations existe.
  • @EnableConfigurationProperties(RedisProperties.class) : Certains paramètres de configuration de redis sont initialisés dans la classe RedisProperties. La configuration écrite en yml ou properties est la logique correspondante de cette classe.
  • @Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class }) : Indique la configuration de l'importation de la connexion redis.

3.6.8.6 Exemple 2

Voici DispatcherServletAutoConfiguration pour voir comment DispatcherServlet est configuré

@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass(DispatcherServlet.class)
@AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class)
public class DispatcherServletAutoConfiguration {
    
    

	/**
	 * The bean name for a DispatcherServlet that will be mapped to the root URL "/".
	 */
	public static final String DEFAULT_DISPATCHER_SERVLET_BEAN_NAME = "dispatcherServlet";

	/**
	 * The bean name for a ServletRegistrationBean for the DispatcherServlet "/".
	 */
	public static final String DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME = "dispatcherServletRegistration";

	@Configuration(proxyBeanMethods = false)
	@Conditional(DefaultDispatcherServletCondition.class)
	@ConditionalOnClass(ServletRegistration.class)
	@EnableConfigurationProperties(WebMvcProperties.class)
	protected static class DispatcherServletConfiguration {
    
    

	}

	@Configuration(proxyBeanMethods = false)
	@Conditional(DispatcherServletRegistrationCondition.class)
	@ConditionalOnClass(ServletRegistration.class)
	@EnableConfigurationProperties(WebMvcProperties.class)
	@Import(DispatcherServletConfiguration.class)
	protected static class DispatcherServletRegistrationConfiguration {
    
    

	}

	@Order(Ordered.LOWEST_PRECEDENCE - 10)
	private static class DefaultDispatcherServletCondition extends SpringBootCondition {
    
    

	}

	@Order(Ordered.LOWEST_PRECEDENCE - 10)
	private static class DispatcherServletRegistrationCondition extends SpringBootCondition {
    
    

	}

}

analyser:

  • @ConfigurationLa classe de configuration est également un bean, mais pour la classe de configuration, l'ordre d'exécution dans certains scénarios est nécessaire et doit être garanti. Par rapport à Spring, la gestion de la configuration automatique sous Spring Boot est une boite noire, elle va juger dynamiquement si la classe de configuration automatique est chargée ou non, et l'ordre de chargement en fonction de la situation actuelle dans le conteneur, on peut donc dire : La configuration automatique de Spring Boot a une forte exigence sur la commande. Poussé par la demande, Spring Boot nous fournit @AutoConfigureBefore, @AutoConfigureAfter, @AutoConfigureOrder (ces trois annotations sont collectivement appelées "trois annotations") pour nous aider à répondre à cette demande.
  • @AutoConfigureOrderAjouté dans la version 1.3.0, il indique l'ordre absolu (plus le nombre est petit, plus la priorité est élevée).
  • @AutoConfigureBefore, @AutoConfigureAfterpour contrôler l'ordre de configuration , indiquant qu'il est chargé après ou avant une certaine configuration ; DispatcherServletAutoConfigurationla prémisse du chargement est : ServletWebServerFactoryAutoConfigurationl'initialisation est terminée.
  • Quatre classes internes sont définies dans DispatcherServletAutoConfiguration. Ce n'est que lorsque la configuration de DispatcherServletAutoConfiguration prend effet que les conditions de configuration de la classe interne peuvent être jugées.

Résumer:

  • Springboot charge d'abord toutes les classes de configuration automatique xxxxxAutoConfiguration.
  • Chaque classe de configuration automatique prend effet selon les conditions. Par défaut, la valeur spécifiée par le fichier de configuration sera liée, obtenue à partir de la classe xxxxProperties, et xxxProperties est liée au fichier de configuration.
  • La classe de configuration effective assemblera de nombreux composants dans le conteneur, tant qu'il y a ces composants dans le conteneur, elle est équivalente à ces fonctions.
  • Paramétrage personnalisé :
    • Les utilisateurs remplacent directement les composants sous-jacents par @Bean.
    • Lorsque l'utilisateur voit la valeur du fichier de configuration obtenu par ce composant, il la modifie.

Je suppose que tu aimes

Origine blog.csdn.net/ligonglanyuan/article/details/126125992
conseillé
Classement