SpringBoot-3.自動組み立てと開発のヒントの原則

コンテンツ

1.スプリングブーツの特徴

1.1。依存関係の管理

1.2、自動構成

1.2.1.Tomcatを自動的に構成する

1.2.2。SpringMVCを自動的に構成する

1.2.3.次のような一般的なWeb機能を自動的に構成します。文字エンコードの問題

1.2.4、デフォルトのパッケージ構造

1.2.5、さまざまな構成にはデフォルト値があります

1.2.6。すべての自動構成アイテムをオンデマンドでロードします

2.コンテナ機能

2.1、コンポーネントの追加

2.1.1、@Configuration

2.1.2、@インポート

2.1.3、@Conditional

2.2、ネイティブ構成ファイルの導入

2.2.1、@ImportResource

2.3、構成バインディング

2.3.1、@ Component + @ConfigurationProperties

 2.3.2、@ EnableConfigurationProperties + @ConfigurationProperties

3.自動構成の原理の紹介

3.1。ブートロード自動構成クラス

 3.1.1、@SpringBootConfiguration

3.1.2、ComponentScan

3.1.3、@EnableAutoConfiguration

3.2.必要に応じて自動構成アイテムを有効にする

3.3、デフォルト構成を変更します

3.4。まとめ

3.5.ベストプラクティス

4.開発スキル

4.1、ロンボク

4.2、@ Slf4j

 4.3、dev-tools

4.4、Spring Initailizr(プロジェクト初期化ウィザード)


1.スプリングブーツの特徴

1.1。依存関係の管理

  • 親プロジェクトは依存関係の管理を行います
    <!-- 依赖管理 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.5</version>
    </parent>

spring-boot-starter-parentをクリックし、その親プロジェクトを表示してから、5行目のspring-boot-dependenciesをクリックすると、一般的に使用されるほとんどすべての依存関係バージョンが設定されていることがわかります。

  • バージョン番号、自動バージョンアービトレーションに注意を払う必要はありません。デフォルトのバージョン番号を変更できます

上記のように、SpringBootは、一般的に使用されるほとんどすべての依存関係バージョンを設定するため、デフォルトでバージョンを記述せずに依存関係をインポートできます。

他のバージョンの依存関係を使用する場合は、次のようにpom.xmlで必要なバージョンを設定できます。mysqlによって駆動されるバージョンは5.1.47です。

    <properties>
        <mysql.version>5.1.47</mysql.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
    </dependencies>
  • 開発インポートスターターシーンスターター

1.たくさんのspring-boot-starter-*が表示されます:*特定のシナリオを表します
2.スターターが導入されている限り、このシナリオのすべての通常の依存関係が自動的に導入されます。3.SpringBootで
サポートされるすべてのシナリオ  https://docs.spring.io/spring-boot/docs/current/reference/html/using.html#using.build-systems.starters 4. * -spring
-boot-starter:によって提供される簡略化された開発シナリオを参照してください。私たちランチャーのサードパーティ。
5.すべてのシーンランチャーの最下位レベルの依存関係は次のとおりです

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
      <version>2.6.5</version>
      <scope>compile</scope>
    </dependency>

1.2、自動構成

1.2.1.Tomcatを自動的に構成する

        tomcatを導入し、Tomcatを構成します

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-tomcat</artifactId>
      <version>2.6.5</version>
      <scope>compile</scope>
    </dependency>

1.2.2。SpringMVCを自動的に構成する

        SpringMVCコンポーネントのフルセットを導入し、SpringMVC共通コンポーネント(機能)を自動的に構成します

1.2.3.次のような一般的なWeb機能を自動的に構成します。文字エンコードの問題

        SpringBootは、Web開発のすべての一般的なシナリオを構成するのに役立ちます。表示したい場合は、メインプログラムで取得できます。

@SpringBootApplication  // 标识为一个SpringBoot应用,被标识的类称为主程序类
public class MainApplication {
    public static void main(String[] args) {
        // 返回IOC容器
        ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);

        // 查看容器里面的组件
        String[] names = run.getBeanDefinitionNames();
        for (String name : names) {
            System.out.println(name);
        }
    }
}

1.2.4 、デフォルトのパッケージ構造

  ○メインプログラムが配置されているパッケージ内のコンポーネントと、その下にあるすべてのサブパッケージは、以下に示すように、デフォルトでスキャンされます。


  ○以前のパッケージスキャン構成は必要ありません○
  スキャンパスを変更するには、@ ComponentScanでスキャンパスを指定するか、@SpringBootApplicationアノテーションでscanBasePackages宣言を使用する必要があります。次に例を示します。

@SpringBootApplication(scanBasePackages = "com.zyj")

注:@ComponentScanアノテーションは@SpringBootApplicationアノテーションで宣言されており、メインプログラムが配置されているパッケージをスキャンするため、@SpringBootApplicationと@ComponentScanを一緒に使用することはできません。

1.2.5、さまざまな構成にはデフォルト値があります

  デフォルトの構成は、最終的に次のようなクラスにマップされます。MultipartProperties

  構成ファイルの値は、最終的に各クラスにバインドされ、コンテナー内にオブジェクトが作成されます。

1.2.6。すべての自動構成アイテムをオンデマンドでロードします

  ○必要に応じて導入できるスターターがたくさんあります
  ○このシナリオの自動構成を有効にする前に導入するシナリオ
  ○SpringBootのすべての自動構成機能はspring-boot-autoconfigureパッケージに含まれています

2.コンテナ機能

2.1、コンポーネントの追加

2.1.1、@Configuration

フルモードとライトモード

Full(proxyBeanMethods = true):プロキシオブジェクトがメソッドを呼び出します。SpringBootはコンポーネントがコンテナに登録されているかどうかを確認します。つまり、コンポーネントを単一インスタンスに保ちます
Lite(proxyBeanMethods = false):単一インスタンスを保持しません 

構成クラスのコンポーネント間に依存関係はありません。Liteモードを使用して、コンテナーの起動プロセスを高速化し、判断を減らし
ます。構成クラスのコンポーネント間に依存関係がある場合は、メソッドが呼び出されて、前の単一インスタンスのコンポーネントが取得されます。フルを使用モード

コンポーネント間には依存関係があります。たとえば、あるコンポーネントにはプロパティとして別のコンポーネントが必要です。次の例では、ユーザーコンポーネントはペットコンポーネントに依存しています。

①まず2つのクラスを用意し、src / main / java / com / zyj / boot/beanの下にPetクラスとUserクラスを作成します。

Petクラスの属性は次のとおりで、パラメーターなしの構造、パラメーター化された構造、setメソッドとgetメソッド、およびtoStringメソッドを生成します。

    private String name;

Userクラスのプロパティは次のとおりで、パラメータなしの構造、パラメータ化された構造、setメソッドとgetメソッド、およびtoStringメソッドを生成します。

    private String name;
    private Integer age;
    private Pet pet;

②構成クラスを生成する

src / main / java / com / zyj / boot/configの下にMyConfig構成クラスを作成します

/**
 * 1、配置类里面使用@Bean标注在方法上给容器注册组件,默认是单实例的
 * 2、@Configuration 标识的类也是容器的一个组件
 * 3、proxyBeanMethods:代理bean方法
 *      Full(proxyBeanMethods = true):代理对象调用方法,SpringBoot会检查这个组件在容器中是否已被注册,即保持组件单实例
 *      Lite(proxyBeanMethods = false):不会保持单实例
 *      用于解决组件依赖:组件依赖必须使用Full模式默认。其他默认是Lite模式(减少判断,加快运行)
 */
@Configuration(proxyBeanMethods = true)  // 告诉SpringBoot这是一个配置类 == 配置文件
public class MyConfig {
    /**
     * 在 proxyBeanMethods = true 的情况下:
     * 外部无论对配置类中的这个组件方法调用多少次,获取的都是之前注册到容器的单实例对象
     * @return
     */
    @Bean()  //给容器添加组件,默认以方法名作为组件的id(可以在括号中自定义),返回类型就是组件类型,返回的值就是组件在容器中的实例
    public User user01(){
        User zhangsan = new User("zhangsan", 18);
        // user组件依赖了pet组件,需要使用Full模式
        zhangsan.setPet(tomcatPet());
        return new User("zhangsan", 18);
    }

    @Bean("tom")
    public Pet tomcatPet(){
        return new Pet("tomcat");
    }
}

③メインプログラムクラス:

@SpringBootApplication(scanBasePackages = "com.zyj")  // 标识为一个SpringBoot应用,被标识的类称为主程序类
public class MainApplication {
    public static void main(String[] args) {
        // 返回IOC容器
        ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);

        // 查看容器里面的组件
        String[] names = run.getBeanDefinitionNames();
        for (String name : names) {
            System.out.println(name);
        }

        // 从容器中获取组件
        Pet tom01 = run.getBean("tom", Pet.class);
        Pet tom02 = run.getBean("tom", Pet.class);
        // 若proxyBeanMethods为true,返回true,否则返回false
        System.out.println("组件:" + (tom01 == tom02));

        MyConfig bean = run.getBean(MyConfig.class);
        System.out.println(bean);

        // 如果@Configuration(proxyBeanMethods = true),则是代理对象调用方法
        // SpringBoot会检查这个组件在容器中是否已被注册,即保持组件单实例
        User user1 = bean.user01();
        User user2 = bean.user01();
        // 若proxyBeanMethods为true,返回true,否则返回false
        System.out.println("user比较:" + (user1 == user2));

        User user01 = run.getBean("user01", User.class);
        Pet tom = run.getBean("tom", Pet.class);
        // 若proxyBeanMethods为true,返回false,否则返回true
        System.out.println("用户的宠物与容器的宠物比较:" + (user01.getPet() == tom));
    }
}

2.1.2、@インポート

@Import({User.class、Matcher.class}):括弧内のコンポーネントは、パラメーターなしの構成によってコンテナー用に自動的に作成されます(複数のコンポーネントはコンマで区切られます)。デフォルトのコンポーネント名は完全なクラス名です。

構成クラス: 

@Import({User.class, Matcher.class})
@Configuration(proxyBeanMethods = true)  // 告诉SpringBoot这是一个配置类 == 配置文件
public class MyConfig {
}

メインプログラムで確認します。

        // 验证@Import注解获取组件
        String[] beanNamesForType = run.getBeanNamesForType(User.class);
        System.out.println("===================================");
        System.out.println("验证@Import注解获取组件");
        for (String s : beanNamesForType) {
            System.out.println(s);
        }
        //com.zyj.boot.bean.User    @Import注解生成的
        //user01    MyConfig中生成的
        Matcher bean1 = run.getBean(Matcher.class);
        System.out.println(bean1);  //java.util.regex.Matcher[pattern=null region=0,0 lastmatch=]

2.1.3、@Conditional

条件付きアセンブリ:条件付きで指定された条件が満たされると、コンポーネントの注入が実行されます

 たとえば、@ ConditionalOnBean(name = "tom")アノテーションがメソッドにある場合、このメソッドによって生成されたコンポーネントは、コンテナーにtomコンポーネントがある場合にのみ注入されます。クラス上にある場合、クラスのメソッドによって生成されたコンポーネントは、コンテナーにtomコンポーネントがある場合にのみ注入されます。

構成クラス: 

@ConditionalOnBean(name = "tom")
@Import({User.class, Matcher.class})
@Configuration(proxyBeanMethods = true)  // 告诉SpringBoot这是一个配置类 == 配置文件
public class MyConfig {
    /**
     * 在 proxyBeanMethods = true 的情况下:
     * 外部无论对配置类中的这个组件方法调用多少次,获取的都是之前注册到容器的单实例对象
     * @return
     */
    //@ConditionalOnBean(name = "tom") // 容器中有tom组件时才注入user01组件
    @Bean()  //给容器添加组件,默认以方法名作为组件的id(可以在括号中自定义),返回类型就是组件类型,返回的值就是组件在容器中的实例
    public User user01(){
        User zhangsan = new User("zhangsan", 18);
        // user组件依赖了pet组件,需要使用Full模式
        zhangsan.setPet(tomcatPet());
        return new User("zhangsan", 18);
    }

    @Bean("tom22")
    public Pet tomcatPet(){
        return new Pet("tomcat");
    }
}

メインプログラムクラス:

        // 去掉com.zyj.boot.config.MyConfig.tomcatPet的@Bean("tom")注解后,查看是否有tom组件
        boolean tom = run.containsBean("tom");
        System.out.println("查看是否有tom组件:" + tom); //false
        // 给com.zyj.boot.config.MyConfig.user01添加注解@ConditionalOnBean(name = "tom")后
        boolean user01 = run.containsBean("user01");
        System.out.println("查看是否有user01组件:" + user01); //false
        // 给com.zyj.boot.config.MyConfig添加注解@ConditionalOnBean(name = "tom")后
        boolean tom22 = run.containsBean("tom22");
        System.out.println("查看是否有tom22组件:" + tom22); //false

2.2、ネイティブ構成ファイルの導入

2.2.1、@ImportResource

@ImportResourceアノテーションは構成ファイルをインポートできます

Beans.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="haha" class="com.zyj.boot.bean.User">
        <property name="name" value="zhangsan"></property>
        <property name="age" value="18"></property>
    </bean>

    <bean id="hehe" class="com.zyj.boot.bean.Pet">
        <property name="name" value="tomcat"></property>
    </bean>

</beans>

構成クラスMyConfig:

@ImportResource("classpath:beans.xml")  //导入配置文件
public class MyConfig {
}

メインプログラムクラス:

        boolean haha = run.containsBean("haha");
        boolean hehe = run.containsBean("hehe");
        //在配置类加入@ImportResource("classpath:bean.xml")之前为false
        System.out.println("查看是否有haha组件" + haha);
        System.out.println("查看是否有hehe组件" + hehe);

2.3、構成バインディング

Javaを使用してプロパティファイルのコンテンツを読み取り、すぐに使用できるようにJavaBeanにカプセル化するのは非常に面倒です。

public class getProperties {
     public static void main(String[] args) throws FileNotFoundException, IOException {
         Properties pps = new Properties();
         pps.load(new FileInputStream("a.properties"));
         Enumeration enum1 = pps.propertyNames();//得到配置文件的名字
         while(enum1.hasMoreElements()) {
             String strKey = (String) enum1.nextElement();
             String strValue = pps.getProperty(strKey);
             System.out.println(strKey + "=" + strValue);
             //封装到JavaBean。
         }
     }
 }

2.3.1、@ Component + @ConfigurationProperties

src / main / resources / application.properties

mycar.brand=BYD
mycar.price=100000

src / main / java / com / zyj / boot/beanの下に車を作成します

// 只有在容器中的组件才有SpringBoot提供的强大功能
@Component
@ConfigurationProperties(prefix = "mycar")
public class Car {

    private String brand;
    private Integer price;

    public Car() {
    }

    public Car(String brand, Integer price) {
        this.brand = brand;
        this.price = price;
    }

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public Integer getPrice() {
        return price;
    }

    public void setPrice(Integer price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Car{" +
                "brand='" + brand + '\'' +
                ", price=" + price +
                '}';
    }
}

在src/main / java / com / zyj / boot / controller / HelloController.java 

@RestController  // @RestController可以代替@Controller和@ResponseBody
public class HelloController {

    @Autowired
    Car car;

    @RequestMapping("/car")
    public Car car(){
        return car;
    }

    @RequestMapping("/hello")
    public String handler01(){
        return "hello,Spring Boot 2!" + "你好";
    }

}

実行後、対応するアドレスにアクセスすると、次のようなページが表示されます

 2.3.2、@ EnableConfigurationProperties + @ConfigurationProperties

このメソッドは、構成クラスで記述する必要があります

src / main / resources / application.properties

mycar.brand=BYD
mycar.price=100000

src / main / java / com / zyj / boot / config / MyConfig.java

@EnableConfigurationProperties(Car.class)  //开启Car配置绑定功能,并把Car这个组件自动注册到容器中
public class MyConfig {
}
@ConfigurationProperties(prefix = "mycar")
public class Car {

    private String brand;
    private Integer price;

    public Car() {
    }

    public Car(String brand, Integer price) {
        this.brand = brand;
        this.price = price;
    }

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public Integer getPrice() {
        return price;
    }

    public void setPrice(Integer price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Car{" +
                "brand='" + brand + '\'' +
                ", price=" + price +
                '}';
    }
}

生成されたアドレスを表示するには、対応するアドレスにアクセスしてください

3.自動構成の原理の紹介

3.1。ブートロード自動構成クラス

SpringBootApplicationのソースコードを見ると、@ SpringBootConfiguration、@ EnableAutoConfiguration、@ComponentScanが含まれていることがわかります。

 3.1.1、@SpringBootConfiguration

@SpringBootConfigurationにはアノテーション@Configurationが含まれています。これは、現在、構成クラスであることを意味します。

3.1.2、ComponentScan

スキャンするパッケージを指定し、

3.1.3、@EnableAutoConfiguration

 @EnableAutoConfigurationには、次の2つのアノテーションが含まれています

@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
}

①@AutoConfigurationPackage

P13 

@AutoConfigurationPackageは、デフォルトのパッケージポリシーを指定する自動構成パッケージです

@Import({Registrar.class})  //给容器导入一个组件
public @interface AutoConfigurationPackage {
}

Registrarをクリックすると、Registrarを使用して一連のコンポーネントをコンテナにインポートしていることがわかります。

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

alt + F8、メインプログラムが配置されているパッケージの下のすべてのコンポーネントがコンテナにインポートされていることがわかります 

②@Import({AutoConfigurationImportSelector.class})

1. getAutoConfigurationEntry(annotationMetadata)を使用して、一部のコンポーネントをコンテナーにバッチインポートし
ます。2。List <String> configuration = getCandidateConfigurations(annotationMetadata、attributes)を呼び出して、コンテナーにインポートする必要のあるすべての構成クラスを取得します
。 load Map <String、List <String >> loadSpringFactories(@Nullable ClassLoader classLoader);すべてのコンポーネントを取得します
4. META-INF/spring.factoriesの場所からファイルをロードします。
    デフォルトでは、現在のシステムのすべてのMETA-INF/spring.factoriesの場所にあるファイルspring-boot-autoconfigure-2.3.4.RELEASE.jarがスキャンされ
    ます。パッケージにはMETA-INF/spring.factoriesもあり、 spring-bootはファイルに書き込まれます。コンテナにロードされるすべての構成クラスは、起動時にロードされます。

構成には133のコンポーネントがあります 

3.2.必要に応じて自動構成アイテムを有効にする

133シーンのすべての自動構成は、開始時にデフォルトでロードされますが。xxxxAutoConfigurationです
が、条件付きアセンブリルール(@Conditional)に従って、最終的にはオンデマンドで構成されます。

3.3、デフォルト構成を変更します

コンテナにファイルアップロードパーサーを追加しました

		@ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME) //容器中没有这个名字 multipartResolver 的组件
		public MultipartResolver multipartResolver(MultipartResolver resolver) {
            //给@Bean标注的方法传入了对象参数,这个参数的值就会从容器中找。
            //SpringMVC multipartResolver。防止有些用户配置的文件上传解析器不符合规范
			// Detect if the user has created a MultipartResolver but named it incorrectly
			return resolver;
		}

SpringBootは、デフォルトですべてのコンポーネントを下部に構成します。ただし、ユーザー自身がユーザーの優先順位を構成する場合

    @Bean
	@ConditionalOnMissingBean
	public CharacterEncodingFilter characterEncodingFilter() {
    }

3.4。まとめ

  • SpringBootは、最初にすべての自動構成クラスxxxxxAutoConfigurationをロードします

  • 各自動構成クラスは条件に従って有効になり、デフォルト値は構成ファイルで指定された値にバインドされます。xxxxProperties内にそれを取ります。xxxプロパティと構成ファイルがバインドされています

  • 効果的な構成クラスは、多くのコンポーネントをコンテナーにアセンブルします

  • コンテナ内にこれらのコンポーネントがある限り、これらの関数と同等です。

  • カスタマイズされた構成

    • ユーザーは、基盤となるコンポーネントを独自の@Beanに直接置き換えます

    • ユーザーは、このコンポーネントによって取得された構成ファイルの値を変更できます。

    xxxxxAutoConfiguration--->コンポーネント--->xxxxPropertiesで値を取得---->application.properties

3.5.ベストプラクティス

  • シーンの依存関係を導入する

  • 自動的に構成されるものを確認する(オプション)

    • 自分で分析すると、紹介シーンに対応した自動設定が一般的に有効になります

    • 構成ファイルで、debug=trueは自動構成レポートを有効にします。ネガティブ(効果的ではない)\ポジティブ(効果的)

  • 変更する必要がありますか

    • 構成項目を変更するには、ドキュメントを参照してください

    • コンポーネントのカスタム追加または交換

      • @Bean、@Component。。。。。

    • カスタマイザーXXXXXCustomizer ;

    • .....。

4.開発スキル

4.1、ロンボク

①依存関係を導入する

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

②メモを追加

@ConfigurationProperties(prefix = "mycar")
@Data //setter和getter方法
@ToString //toString方法
@AllArgsConstructor //全参构造
@NoArgsConstructor //无参构造
@EqualsAndHashCode //equals和hashCode方法
public class Car {

    private String brand;
    private Integer price;

}

4.2、@ Slf4j

①コントローラーメソッドでアノテーションとログを追加する

@RestController  // @RestController可以代替@Controller和@ResponseBody
@Slf4j
public class HelloController {
    @Autowired
    Car car;

    @RequestMapping("/car")
    public Car car(){
        return car;
    }

    @RequestMapping("/hello")
    public String handler01(){
        log.info("请求进来了...");
        return "hello,Spring Boot 2!" + "你好";
    }
}

②対応するアドレスにアクセスすると、コンソール出力は次のようになります。

 4.3、dev-tools

本質は再起動することです。自動的にロードしたい場合は、JRebel(有料)を使用できます。

①依存関係を導入する

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>

②依存関係をインポートしてページを変更した後、ctrl + F9(プロジェクトをビルドするためのショートカットキー)を押して再コンパイルし、Webページを更新できます。

4.4、Spring Initailizr(プロジェクト初期化ウィザード)

①新しいプロジェクトを作成するときは、Spring Initailizrを選択し、必要に応じてボックスに入力して、[次へ]をクリックします。

 ②必要なものを選ぶ

 ③作成完了後、ディレクトリは以下のようになり、依存関係が自動的に導入され、メインプログラムクラスが作成されました。 

 

おすすめ

転載: blog.csdn.net/Mr_zhangyj/article/details/123852839