学習ノート: 上級シリコンバレー Spring 6

春6

  1. 学習メモ: Spring 6 Basics_ljtxy.love のブログ - CSDN ブログ
  2. 学習メモ: Spring 6 Advanced Chapter_ljtxy.love のブログ-CSDN ブログ

記事ディレクトリ

7. 単体テスト: JUnit

メモの要約:

  1. 概要: JUnit はJava プログラミング言語の単体テスト フレームワークです。

  2. 基本的な使用例:

    ステップ 1: 依存関係の導入: Junit サポートの依存関係、Junit5 テスト

    ステップ 2: 設定ファイル: 基本的なクラス スキャンを設定する

    ステップ 3: デモ: **@SpringJUnitConfig(locations = “classpath:beans.xml”)** アノテーションを使用して、構成ファイルを自動的にロードし、クラスを作成します

7.1 概要

JUnit は Java プログラミング言語の単体テスト フレームワークで、Erich Gamma と Kent Beck によって作成され、徐々に Java 言語の標準単体テスト フレームワークの 1 つになりました。JUnit は、開発者がテスト ケースを作成して実行できるように、いくつかのアノテーションとアサーション メソッドを提供します。また、Maven や Gradle などのビルド ツールと統合して、継続的な統合と自動テストを促進することもできます。

7.2 基本的な使用例

ステップ 1: 依存関係を導入する

<!--spring对junit的支持相关依赖-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>6.0.2</version>
</dependency>

<!--junit5测试-->
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-api</artifactId>
    <version>5.9.0</version>
</dependency>

ステップ 2: 設定ファイル

<?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"
       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">
    <context:component-scan base-package="com.atguigu.spring6.bean"/>
</beans>

例証します:

Bean の自動アセンブリのための構成クラスのスキャン

ステップ 3: クラスを作成する

@Component
public class User {
    
    

    public User() {
    
    
        System.out.println("run user");
    }
}

ステップ 4: デモンストレーションを行う

@SpringJUnitConfig(locations = "classpath:beans.xml")
public class SpringJUnit5Test {
    
    

    @Autowired
    private User user;

    @Test
    public void testUser(){
    
    
        System.out.println(user);
    }
}

例証します:

  • @SpringJUnitConfig アノテーションは、Spring の構成ファイルを指定するために使用されます。テスト メソッドが実行される前に、Spring はまず構成ファイルに基づいて必要な Bean を作成し、それをテスト クラスに注入します。このようにして、テスト用のテスト クラスで Spring の Bean を直接使用できます。

  • クラスは次の場所にあります。

    ApplicationContext context = new ClassPathXmlApplicationContext("xxx.xml");
    Xxxx xxx = context.getBean(Xxxx.class);
    
  • このコードは、ApplicationContextインターフェイスのクラスパス XML コンテキストを通じてClassPathXmlApplicationContextロードされます。

8.事務

メモの要約:

  1. 概要:
    1. 定義: トランザクションには 1 つ以上のデータ操作が含まれており、すべて成功するかすべて失敗します。
    2. 特性:
      • 原子性: すべてが成功するか、すべてが失敗するかのどちらか
      • 一貫性: トランザクションの実行が失敗した後、データベース内のデータは変更されません。
      • Isolation : 複数のトランザクションが互いに分離されます。
      • 耐久性: トランザクションが完了した後、データベース内のデータは通常どおり永続的に保存される必要があります。
    3. プログラムによるトランザクション:コードを使用してトランザクションを処理する
    4. 宣言的トランザクション:アノテーションを使用してトランザクションを処理します。注釈 **@Transactional**
  2. アノテーションベースの宣言的トランザクション:このセクションを詳しく読んでください。
  3. XML ベースの宣言型トランザクション (理解): XMLを介したアスペクトの定義と適用

8.1 概要

8.1.1 定義

トランザクションとは、1 つ以上の一連の操作で構成される論理的な作業単位を指します。これらの操作はすべて成功するか、すべて失敗してロールバックされます。データベースでは、トランザクションには追加、削除、変更などの 1 つ以上のデータ操作が含まれます。同時に、これらの操作はすべて成功するか、すべて失敗する必要があります。成功または失敗するのは一部の操作だけです。

8.1.2 特徴

  1. 原子性: トランザクションは、すべてが成功するかすべてが失敗する、分割できない作業単位です。部分的な成功や部分的な失敗は許可されません。
  2. 一貫性: トランザクションの実行前後でデータベースの状態が一貫している必要があり、トランザクションの実行に失敗した場合は、データベースを実行前の状態に復元する必要があります。
  3. 分離: ダーティ リード、反復不可能な読み取り、ファントム リードなどの問題を回避するために、複数のトランザクションは相互に分離されている必要があり、トランザクションが相互に干渉することはできません。
  4. 耐久性: トランザクションの完了後、データベースへの変更は永続化され、システムに障害やクラッシュが発生した場合でも、データが失われないようにする必要があります。

8.2.3 プログラムによるトランザクション

プログラムによるトランザクションは、コード内にトランザクション管理コードを記述することで実装されます。トランザクションの開始、送信、ロールバックを手動で制御する必要があります。コードの結合が行われるように、トランザクション管理が必要な各メソッドに関連するコードを記述する必要があります。トランザクション管理コードが繰り返されるため

Connection conn = ...;
    
try {
    
    
    
    // 开启事务:关闭事务的自动提交
    conn.setAutoCommit(false);
    
    // 核心操作
    
    // 提交事务
    conn.commit();
    
}catch(Exception e){
    
    
    
    // 回滚事务
    conn.rollBack();
    
}finally{
    
    
    
    // 释放数据库连接
    conn.close();
    
}

8.2.4 宣言的トランザクション

宣言型トランザクションは、トランザクション管理コードをビジネス ロジックから分離する AOP によって実装されます。設定ファイルでトランザクション管理を宣言することで、トランザクションの自動管理が実現します。開発者は、トランザクション管理が必要なメソッドを追加するだけで済みます。アノテーションまたは設定だけで十分です。これにより、コードの作成とメンテナンスが大幅に簡素化されます。

public interface UserService {
    
    
    void updateUser(User user);
}

@Service
@Transactional
public class UserServiceImpl implements UserService {
    
    
    @Autowired
    private UserDao userDao;

    @Override
    public void updateUser(User user) {
    
    
        userDao.update(user);
    }
}

例証します:

  • この例では、@Transactionalアノテーションはサービス実装クラスのクラス レベルで使用されます。これはupdateUser、メソッドが呼び出されるときに Spring がトランザクションを作成し、メソッドの実行が終了するとトランザクションがコミットまたはロールバックされる (例外が発生した場合) ことを意味します。
  • このようにして、updateUserメソッドを呼び出すときに、トランザクションを明示的に開いてコミットする必要はなく、Spring フレームワークがトランザクションの送信とロールバックを自動的に処理します。

8.2 アノテーションベースの宣言的トランザクション

注セクション:

  1. 基本的な使用例:

    ステップ 1: tx 名前空間を追加し、トランザクション マネージャーを追加し、トランザクション アノテーションドライバーを有効にする

    ステップ 2:トランザクションアノテーションを追加する: @Transactional

  2. トランザクション属性:

    1. 読み取り専用: @Transactional( readOnly = true) は、この操作が読み取りのみ可能で書き換えできないことをデータベースに伝えます。
    2. タイムアウト: @Transactional( timeout = 3)、この操作がタイムアウトすると、プロンプトが表示されます
    3. ロールバック戦略:
      • rollbackFor 属性: トランザクション メソッドが指定されたタイプの例外をスローすると、トランザクションはロールバックされます。
      • rollbackForClassName 属性: rollbackFor 属性に似ていますが、例外タイプを指定するときに文字列を使用します。
      • noRollbackFor 属性:トランザクション メソッドが指定されたタイプの例外をスローしたときに、トランザクションがロールバックされないことを指定します。
      • noRollbackForClassName 属性: noRollbackFor 属性と似ていますが、例外タイプを指定するときに文字列を使用します。
    4. 分離レベル:
      • READ_UNCOMMITTED: トランザクションが、コミットされていない別のトランザクションからデータを読み取ることができることを示します。このレベルではダーティ リード、非反復読み取り、ファントム リードが発生する可能性があるため、通常は推奨されません。
      • READ_COMMITTED: トランザクションは、コミットされた別のトランザクションのデータのみを読み取ることができることを示します。これにより、ダーティ リードの問題は回避できますが、反復不可能なおよびファントム リードの問題が依然として発生する可能性があります。
      • REPEATABLE_READ: トランザクションが実行中に同じデータ行を複数回読み取ることができることを示します。これにより、ダーティ リードや非反復読み取りの問題は回避できますが、ファントム リードの問題は依然として発生する可能性があります
      • SERIALIZABLE: トランザクションは実行中に関係するすべてのデータをロックし、ダーティ リード、反復不可能な読み取り、ファントム リードの問題を回避しますが、同時実行パフォーマンスが非常に低いことを示します。
    5. 伝播動作: トランザクションの伝播動作とは、複数のトランザクション メソッドが相互に呼び出されるときに、トランザクションがどのように伝播し、相互の動作に影響を与えるかを制御するルールを指します。
    6. 完全な注釈構成トランザクション: @EnableTransactionManagement が注釈トランザクション管理をオンにします

8.2.1 基本的なユースケース - 注釈付きの宣言的トランザクションの実装

ステップ 1: tx 名前空間と構成を構成ファイルに追加する

<?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:tx="http://www.springframework.org/schema/tx"
       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/tx
                           http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!--事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="druidDataSource"/>
    </bean>

    <!--
		开启事务的注解驱动。通过注解@Transactional所标识的方法或标识的类中所有的方法,都会被事务管理器管理事务-->
    <!-- transaction-manager属性的默认值是transactionManager,如果事务管理器bean的id正好就是这个默认值,则可以省略这个属性 -->
    <tx:annotation-driven transaction-manager="transactionManager" />
</beans>

例証します:

  1. tx 名前空間を追加する
  2. トランザクションマネージャーを追加する
  3. アノテーション駆動によるトランザクションの有効化

ステップ 2: トランザクションの注釈を追加する

@Transactional
public void buyBook(Integer bookId, Integer userId) {
    
    
    //查询图书的价格
    Integer price = bookDao.getPriceByBookId(bookId);
    //更新图书的库存
    bookDao.updateStock(bookId);
    //更新用户的余额
    bookDao.updateBalance(userId, price);
    //System.out.println(1/0);
}

例証します:

  • サービス層はビジネスロジック層を表し、通常、トランザクション管理の目的を達成するためにビジネス層の機能にアノテーションが追加されます。
  • メソッドにマークされた @Transactional アノテーションは、トランザクション管理ツールによって管理されるメソッドにのみ影響します。@Transactional アノテーションはクラスにマークされており、トランザクション管理ツールで管理されるクラス内のすべてのメソッドに影響します。

ステップ 3: デモ

例証します:

操作トランザクション中にエラーが発生した場合、Spring フレームワークが自動的にデータをロールバックします。

8.2.2 トランザクション属性: 読み取り専用

クエリ操作の場合、読み取り専用に設定すると、この操作には書き込み操作が含まれないことをデータベースに明確に伝えることができます。これにより、データベースをクエリ操作用に最適化できます。

@Transactional(readOnly = true)
public void buyBook(Integer bookId, Integer userId) {
    
    
    //查询图书的价格
    Integer price = bookDao.getPriceByBookId(bookId);
    //更新图书的库存
    bookDao.updateStock(bookId);
    //更新用户的余额
    bookDao.updateBalance(userId, price);
    //System.out.println(1/0);
}

例証します:

  1. 現時点では、トランザクション読み取り専用属性がトランザクションに追加されているため、操作の追加、削除、変更を行うと例外がスローされます。

  2. Caused by: java.sql.SQLException: Connection is read-only. Queries leading to data modification are not allowed
    

8.2.3 トランザクションのプロパティ: タイムアウト

トランザクションの実行中に、特定の問題が発生してプログラムが停止し、データベース リソースが長時間占有される場合があります。リソースが長時間占有されている場合は、実行中のプログラムに問題があることが考えられます (Java プログラム、MySQL データベース、ネットワーク接続など)。このとき、問題がある可能性のあるプログラムをロールバックし、実行した操作を元に戻し、トランザクションを終了し、他の正常なプログラムが実行できるようにリソースを解放する必要があります。

//超时时间单位秒
@Transactional(timeout = 3)
public void buyBook(Integer bookId, Integer userId) {
    
    
    try {
    
    
        TimeUnit.SECONDS.sleep(5);
    } catch (InterruptedException e) {
    
    
        e.printStackTrace();
    }
    //查询图书的价格
    Integer price = bookDao.getPriceByBookId(bookId);
    //更新图书的库存
    bookDao.updateStock(bookId);
    //更新用户的余额
    bookDao.updateBalance(userId, price);
    //System.out.println(1/0);
}

例証します:

  1. このとき、トランザクションにはトランザクション タイムアウト属性が追加されているため、チェックと変更の操作が単位時間を超えると例外がスローされます。

  2. org.springframework.transaction.TransactionTimedOutException: Transaction timed out: deadline was Fri Jun 04 16:25:39 CST 2022
    

8.2.4 トランザクション属性: ロールバック戦略

トランザクション属性のロールバック戦略は、トランザクションで例外が発生したときにトランザクションのコミットまたはロールバックを処理する方法を指します。

属性の分類:

  1. rollbackFor 属性: トランザクション メソッドが指定されたタイプの例外をスローすると、トランザクションはロールバックされます。

    @Transactional(rollbackFor = {
          
          SQLException.class, IOException.class})
    
  2. rollbackForClassName 属性: rollbackFor 属性に似ていますが、例外タイプを指定するときに文字列を使用します。

    @Transactional(rollbackForClassName = {
          
          "java.sql.SQLException", "java.io.IOException"})
    
  3. noRollbackFor 属性: トランザクション メソッドが指定されたタイプの例外をスローしたときに、トランザクションがロールバックされないことを指定します。

    @Transactional(noRollbackFor = {
          
          NullPointerException.class, IllegalArgumentException.class})
    
  4. noRollbackForClassName 属性: noRollbackFor 属性と似ていますが、例外タイプを指定するときに文字列を使用します。

    @Transactional(noRollbackForClassName = {
          
          "java.lang.NullPointerException", "java.lang.IllegalArgumentException"})
    

基本的な使用例:

@Transactional(noRollbackFor = ArithmeticException.class)
//@Transactional(noRollbackForClassName = "java.lang.ArithmeticException")
public void buyBook(Integer bookId, Integer userId) {
    
    
    //查询图书的价格
    Integer price = bookDao.getPriceByBookId(bookId);
    //更新图书的库存
    bookDao.updateStock(bookId);
    //更新用户的余额
    bookDao.updateBalance(userId, price);
    System.out.println(1/0);
}

例証します:

このとき、 @Transactional アノテーションで設定した属性は となっているnoRollbackForためArithmeticException.class、このような例外が発生してもトランザクションはロールバックされません。

8.2.5 トランザクションのプロパティ: 分離レベル

トランザクション分離レベルとは、複数のトランザクションが同時に実行される場合に、トランザクション間のデータの一貫性を確保するためにデータベースで採用される分離メカニズムを指します。

分離レベル ダーティリード 反復不可能な読み取り 幻の読書
コミットされていない読み取り 持っている 持っている 持っている
コミットされた読み取り なし 持っている 持っている
反復読み取り なし なし 持っている
シリアル化可能 なし なし なし

例証します:

  • READ_UNCOMMITTED: トランザクションが別のコミットされていないトランザクションからデータを読み取ることができることを示します。このレベルでは、ダーティ読み取り、反復不能読み取り、およびファントム読み取りが発生する可能性があるため、通常は推奨されません。
  • READ_COMMITTED: トランザクションは、コミットされた別のトランザクションのデータのみを読み取ることができることを示します。これにより、ダーティ リードの問題は回避できますが、非反復読み取りおよびファントム リードの問題が依然として発生する可能性があります。
  • REPEATABLE_READ: トランザクションが実行中に同じデータ行を複数回読み取ることができることを示します。これにより、ダーティ リードや非反復読み取りの問題は回避できますが、ファントム リードの問題は依然として発生する可能性があります。
  • SERIALIZABLE: トランザクションは、実行中に関係するすべてのデータをロックし、ダーティ リード、反復不可能な読み取り、ファントム リードの問題を回避しますが、同時実行パフォーマンスが非常に低いことを示します。

基本的な使い方

@Transactional(isolation = Isolation.DEFAULT)//使用数据库默认的隔离级别
@Transactional(isolation = Isolation.READ_UNCOMMITTED)//读未提交
@Transactional(isolation = Isolation.READ_COMMITTED)//读已提交
@Transactional(isolation = Isolation.REPEATABLE_READ)//可重复读
@Transactional(isolation = Isolation.SERIALIZABLE)//串行化

8.2.6 トランザクション属性: 伝播動作

トランザクションの伝播動作とは、複数のトランザクション メソッドが相互に呼び出されるときに、トランザクションがどのように伝播し、相互の動作に影響を与えるかを制御するルールを指します。Spring フレームワークでは、トランザクションの伝播動作はPropagation列挙型クラスによって定義されます。一般的に使用される伝播動作には次のものがあります。

  1. REQUIRED (デフォルト): トランザクションが現在存在する場合はトランザクションに参加し、現在のトランザクションが存在しない場合は新しいトランザクションを作成します。つまり、存在しない場合は新規作成し、存在する場合は追加します。
  2. サポート: 現在トランザクションがある場合はトランザクションに参加し、トランザクションがない場合は非トランザクションで実行を継続します。言い換えれば、持っている場合は参加し、持っていない場合は参加しないでください。
  3. 必須: 現在トランザクションがある場合はトランザクションに参加し、トランザクションがない場合は例外をスローします。つまり、存在する場合は結合し、存在しない場合は例外をスローします。
  4. REQUIRES_NEW: 新しいトランザクションを作成します。現在トランザクションが存在する場合は、現在のトランザクションを一時停止します。つまり、有無に関わらず新規トランザクションが直接オープンされ、新規トランザクションと前のトランザクションの間に入れ子関係はなく、前のトランザクションは一時停止されます。
  5. NOT_SUPPORTED: 非トランザクション モードで実行します。現在トランザクションが存在する場合、現在のトランザクションは一時停止されます。つまり、トランザクションがサポートされていない場合、トランザクションが存在していても一時停止されます。
  6. NEVER: 非トランザクション モードで実行し、トランザクションが現在存在する場合は例外をスローします。つまり、トランザクションがサポートされていない場合、トランザクションが存在すると例外がスローされます。
  7. NESTED: 現在トランザクションが存在する場合は、ネストされたトランザクション内で実行されます。現在トランザクションが存在しない場合は、PROPAGATION_REQUIRED に従って実行されます。つまり、トランザクションが存在する場合、そのトランザクション内に完全に独立したトランザクションをネストし、ネストされたトランザクションは独立してサブミットおよびロールバックできます。REQUIRED と同じトランザクションはありません
@Transactional(propagation = Propagation.REQUIRED)
public void transactionalMethod() {
    
    
    // ...
}

8.2.7 完全なアノテーション設定トランザクション (重要なポイント)

ステップ 1: 構成クラスを追加する

package com.atguigu.spring6.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;

@Configuration // 表示该类为配置类
@ComponentScan("com.atguigu.spring6") // 开启组件扫描,扫描com.atguigu.spring6包下的组件
@EnableTransactionManagement // 开启注解式事务管理
public class SpringConfig {
    
    

    @Bean // 声明一个Bean对象
    public DataSource getDataSource(){
    
    
        DruidDataSource dataSource = new DruidDataSource(); // 创建Druid连接池
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver"); // 配置驱动类名
        dataSource.setUrl("jdbc:mysql://localhost:3306/spring?characterEncoding=utf8&useSSL=false"); // 配置数据库URL
        dataSource.setUsername("root"); // 配置数据库用户名
        dataSource.setPassword("root"); // 配置数据库密码
        return dataSource; // 返回配置好的数据源对象
    }

    @Bean(name = "jdbcTemplate") // 声明一个Bean对象并命名为"jdbcTemplate"
    public JdbcTemplate getJdbcTemplate(DataSource dataSource){
    
    
        JdbcTemplate jdbcTemplate = new JdbcTemplate(); // 创建JdbcTemplate对象
        jdbcTemplate.setDataSource(dataSource); // 设置JdbcTemplate的数据源
        return jdbcTemplate; // 返回配置好的JdbcTemplate对象
    }

    @Bean // 声明一个Bean对象
    public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource){
    
    
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager(); // 创建DataSourceTransactionManager对象
        dataSourceTransactionManager.setDataSource(dataSource); // 设置数据源
        return dataSourceTransactionManager; // 返回配置好的DataSourceTransactionManager对象
    }
}

例証します:

完全なアノテーションを使用してトランザクションを構成する場合は、トランザクション マネージャーを宣言し、アノテーション @EnableTransactionManagement を使用してトランザクション マネージャーを有効にする必要があります。

ステップ 2: デモンストレーション

@Test
public void testTxAllAnnotation(){
    
    
    ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
    BookController accountService = applicationContext.getBean("bookController", BookController.class);
    accountService.buyBook(1, 1);
}

8.2.8 基礎となる原則

Java では、@Transactionalアノテーションを使用したメソッドレベルのトランザクション管理の実装は、Spring フレームワークの特性と AOP (アスペクト指向プログラミング) の原則に基づいています。

基礎となる原則は次のとおりです。

  1. Spring は、 AOP 機能を通じて、アノテーションを持つ@Transactionalメソッドの実行をインターセプトします。
  2. メソッドが呼び出されると、Spring は実行時にそのメソッドのプロキシ オブジェクトを作成します。
  3. プロキシ オブジェクトは、メソッドの実行の前後にトランザクション関連のロジックを挿入します。
  4. メソッドの開始時に、トランザクション マネージャーは新しいデータベース トランザクションを開始します。
  5. メソッドが正常に実行された場合 (例外がスローされなかった場合)、トランザクション マネージャーはトランザクションをコミットし、データベースへの変更を永続化します。
  6. メソッドの実行中に例外が発生した場合、トランザクション マネージャーはトランザクションをロールバックし、データベースへの変更を元に戻し、トランザクションが開始される前の状態に復元します。
  7. メソッドの実行が完了すると、トランザクション マネージャーはトランザクションを閉じます。

AOP を通じて、Spring はメソッドの実行前後のトランザクションを制御できます。メソッドが実行される前にトランザクションを開始し、メソッドの実行後にトランザクションをコミットまたはロールバックすることで、データの一貫性と整合性が保証されます。

画像-20230624175741508

@Transactionalアノテーションの有効性は、トランザクション マネージャーの構成と使用環境のサポートにも依存することに注意してください。Spring フレームワークには、JDBC ベースのトランザクション マネージャーや JTA ベースのトランザクション マネージャーなど、さまざまなトランザクション マネージャーの実装が用意されており、特定のニーズに応じて適切なトランザクション マネージャーを選択できます。同時に、Spring は設定ファイルでトランザクション マネージャーを有効にし、@Transactionalアノテーションによって変更されたメソッドが Spring コンテナによって取得されたプロキシ オブジェクトを通じて呼び出されるようにする必要があります。この方法によってのみ、トランザクション アノテーションが有効になり、トランザクション管理機能が正しく適用されます。

8.3 XML ベースの宣言型トランザクション (理解)

<aop:config>
    <!-- 配置事务通知和切入点表达式 -->
    <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.atguigu.spring.tx.xml.service.impl.*.*(..))"></aop:advisor>
</aop:config>
<!-- tx:advice标签:配置事务通知 -->
<!-- id属性:给事务通知标签设置唯一标识,便于引用 -->
<!-- transaction-manager属性:关联事务管理器 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <!-- tx:method标签:配置具体的事务方法 -->
        <!-- name属性:指定方法名,可以使用星号代表多个字符 -->
        <tx:method name="get*" read-only="true"/>
        <tx:method name="query*" read-only="true"/>
        <tx:method name="find*" read-only="true"/>
    
        <!-- read-only属性:设置只读属性 -->
        <!-- rollback-for属性:设置回滚的异常 -->
        <!-- no-rollback-for属性:设置不回滚的异常 -->
        <!-- isolation属性:设置事务的隔离级别 -->
        <!-- timeout属性:设置事务的超时属性 -->
        <!-- propagation属性:设置事务的传播行为 -->
        <tx:method name="save*" read-only="false" rollback-for="java.lang.Exception" propagation="REQUIRES_NEW"/>
        <tx:method name="update*" read-only="false" rollback-for="java.lang.Exception" propagation="REQUIRES_NEW"/>
        <tx:method name="delete*" read-only="false" rollback-for="java.lang.Exception" propagation="REQUIRES_NEW"/>
    </tx:attributes>
</tx:advice>

注: XML に基づいて実装された宣言トランザクションには、aspectJ 依存関係を導入する必要があります。

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>6.0.2</version>
</dependency>

9. リソ​​ース操作: リソース

メモの要約:

  1. 概要: Spring フレームワークでは、インターフェイスとその実装クラスは、リソース(ファイル、クラスパス リソース、URL など) を処理するorg.springframework.core.io.Resourceために使用される抽象化レイヤーです。
  2. Resources インターフェース: Resource インターフェースは Spring のリソース アクセス戦略の抽象化です。それ自体はリソース アクセスの実装を提供しません。特定のリソース アクセスは、このインターフェースの実装クラスによって完了されますResource インターフェースは、低レベルのリソースへのアクセスを抽象化するために使用されます。
  3. リソース実装クラス:
    • UrlResource: このクラスは、ネットワーク リソースへのアクセスに使用できるURL タイプのリソースを表すために使用されます
    • ClassPathResource : ClassPath Resource は、クラスパス下のリソースを表すために使用され、リソースの相対パスまたは絶対パスを指定することでインスタンス化できます。
    • FileSystemResource : FileSystem Resource クラスは、ファイル システムリソースにアクセスするために使用されます。
    • ServletContextResource:わずかに
    • InputStreamResource:わずかに
    • ByteArrayResource:わずかに
  4. ResourceLoader インターフェイス: リソースをロードするための統合アクセス方法を定義します
  5. ResourceLoader実装クラス:
    • DefaultResourceLoader: デフォルトのリソース ローダー。クラスパス、ファイル システム、および URL リソースをロードするために使用できます
    • FileSystemResourceLoader:ファイル システムにリソースをロードするために使用されます。
    • ClassPathResourceLoader:クラスパスの下のリソースをロードするために使用されます。
    • ServletContextResourceLoader: Web アプリケーションのコンテキストでリソースをロードするために使用されます。
  6. ResourceLoaderAware インターフェース:このインターフェースを実装する Bean にResourceLoader インスタンスを注入するために使用されます。
  7. Resource リソースを動的に取得します。依存関係の注入を直接使用して、Spring リソースへのアクセスを最大限に簡素化します。
  8. リソースのアクセス パスを決定します。
    • 実装クラスはアクセスパスを指定します
      • ClassPathXML ApplicationContext: リソース アクセスに ClassPathResource を使用することに対応します。
      • FileSystemXml ApplicationContext: リソース アクセスに FileSystemResource を使用することに対応します。
      • XmlWeb ApplicationContext: リソース アクセスに ServletContextResource を使用することに対応します。
    • プレフィックスはアクセス パスを指定します。
      1. クラスパス接頭辞
      2. クラスパスワイルドカード
      3. ワイルドカードのその他の用途

9.1 概要

Spring フレームワークでは、org.springframework.core.io.Resourceインターフェイスとその実装クラスは、リソース (ファイル、クラスパス リソース、URL など) を処理するために使用される抽象化レイヤーです。ファイル システム内、クラスパス下、または URL を通じてアクセスされるかどうかに関係なく、さまざまな種類のリソースにアクセスして操作するための統一された方法を提供します。

9.2リソースインターフェース

9.2.1 概要

Spring の Resource インターフェイスはorg.springframework.core.ioにあります。低レベルのリソースへのアクセスを抽象化するための、より強力なインターフェイスを目的としています。

インターフェイスはSpring のインターフェイスResource継承し、より多くのメソッドを提供します。インターフェースにはメソッドが 1 つInputStreamSourceだけありますInputStreamSource

9.2.2 一般的な方法

  • boolean exists(): リソースが存在するかどうかを確認します。
  • boolean isReadable(): リソースが読み取り可能かどうかを確認してください。
  • boolean isOpen(): リソースが開いているかどうかを確認してください。
  • URL getURL(): リソースの URL を取得します。
  • URI getURI(): リソースの URI を取得します。
  • File getFile(): リソースに対応するファイルを取得します。
  • long contentLength(): リソースの長さを取得します。
  • long lastModified(): リソースの最終変更時刻を取得します。
  • Resource createRelative(String relativePath): 現在のリソースを基準とした相対リソースを作成します。
  • String getFilename(): リソースのファイル名を取得します。
  • String getDescription(): リソースの説明情報を取得します。
  • InputStream getInputStream(): リソースの入力ストリームを取得します。

9.3リソース実装クラス

9.3.1 概要

Resource インターフェイスは Spring のリソース アクセス戦略を抽象化したもので、それ自体はリソース アクセスの実装を提供せず、特定のリソース アクセスはインターフェイスの実装クラスによって完了されます。各実装クラスはリソース アクセス戦略を表します。リソースには通常、次の実装クラスが含まれます。UrlResource、ClassPathResource、FileSystemResource、ServletContextResource、InputStreamResource、ByteArrayResource

画像-20230516133813254

9.3.2UrlResourceクラス

このクラスは、URLオブジェクトまたはタイプStringの URL パスを通じてインスタンス化され、ネットワーク リソースにアクセスするために使用できる URL タイプのリソースを表すために使用されます。

基本的な使用例:

public class UrlResourceDemo {
    
    

    public static void loadAndReadUrlResource(String path){
    
    
        // 创建一个 Resource 对象
        UrlResource url = null;
        try {
    
    
            url = new UrlResource(path);
            // 获取资源名
            System.out.println(url.getFilename());
            System.out.println(url.getURI());
            // 获取资源描述
            System.out.println(url.getDescription());
            //获取资源内容
            System.out.println(url.getInputStream().read());
        } catch (Exception e) {
    
    
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
    
    
        //1 访问网络资源
        //loadAndReadUrlResource("http://www.atguigu.com");

        //2 访问文件系统资源
        loadAndReadUrlResource("file:atguigu.txt");
    }
}

例証します:

  • ファイル システム リソースにアクセスするときは、現在のプロジェクトのルート パスに基づいてファイルを読み取る必要があります。

    画像-20230516140223559

補充:

  • http:------このプレフィックスは、HTTP プロトコルに基づいてネットワーク リソースにアクセスするために使用されます
  • ftp:------このプレフィックスは、FTP プロトコルに基づいてネットワーク リソースにアクセスするために使用されます
  • file: ------このプレフィックスは、ファイル システムからリソースを読み取るために使用されます

9.3.3 ClassPathResourceクラス

ClassPathResource は、クラス パスの下のリソースを表すために使用され、リソースの相対パスまたは絶対パスを指定することでインスタンス化できます。他の Resource 実装クラスと比較した場合、その主な利点は、特に Web アプリケーションの場合、クラス読み込みパス内のリソースへのアクセスが容易になることです。, ClassPathResource は、絶対パス アクセスを使用せずに、クラスの下にあるリソース ファイルを自動的に検索できます。

基本的な使用例:

public class ClassPathResourceDemo {
    
    

    public static void loadAndReadUrlResource(String path) throws Exception{
    
    
        // 创建一个 Resource 对象
        ClassPathResource resource = new ClassPathResource(path);
        // 获取文件名
        System.out.println("resource.getFileName = " + resource.getFilename());
        // 获取文件描述
        System.out.println("resource.getDescription = "+ resource.getDescription());
        //获取文件内容
        InputStream in = resource.getInputStream();
        byte[] b = new byte[1024];
        while(in.read(b)!=-1) {
    
    
            System.out.println(new String(b));
        }
    }

    public static void main(String[] args) throws Exception {
    
    
        loadAndReadUrlResource("atguigu.txt");
    }
}

例証します:

  • ファイル リソース システムにアクセスするときは、現在のプロジェクトのクラス パスに基づいてファイルを読み取る必要があります。

    画像-20230516140413107

9.3.4FileSystemResourceクラス

ファイル システム リソースへのアクセスには Spring が提供する FileSystemResource クラスが使用されますが、Java が提供する File クラスもファイル システム リソースへのアクセスに使用できるため、FileSystemResource を使用してファイル システム リソースにアクセスする利点はあまりありません。

public class FileSystemResourceDemo {
    
    

    public static void loadAndReadUrlResource(String path) throws Exception{
    
    
        //相对路径
        FileSystemResource resource = new FileSystemResource("atguigu.txt");
        //绝对路径
        //FileSystemResource resource = new FileSystemResource("C:\\atguigu.txt");
        // 获取文件名
        System.out.println("resource.getFileName = " + resource.getFilename());
        // 获取文件描述
        System.out.println("resource.getDescription = "+ resource.getDescription());
        //获取文件内容
        InputStream in = resource.getInputStream();
        byte[] b = new byte[1024];
        while(in.read(b)!=-1) {
    
    
            System.out.println(new String(b));
        }
    }

    public static void main(String[] args) throws Exception {
    
    
        loadAndReadUrlResource("atguigu.txt");
    }
}

9.3.5 ServletContextResourceクラス

これは、ServletContext関連する Web アプリケーションのルート ディレクトリ内の相対パスを解釈するリソースの Resource 実装です。ストリーム アクセスと URL アクセスは常にサポートされますが、Web アプリケーション アーカイブが拡張され、リソースが実際にファイル システム上にある場合にのみ java.io.File アクセスが許可されます。ファイル システム上で拡張される場合でも、JAR または他の場所 (データベースなど) から直接アクセスされる場合でも、実際にはサーブレット コンテナに依存します。

9.3.6InputStreamResourceクラス

InputStreamResource 指定された入力ストリームのリソース実装です その使用シナリオは、特定のリソース実装がない場合に使用されます (@Component の該当するシナリオと非常によく似ています)。他の Resource 実装とは異なり、これは開かれたリソースの記述子です。したがって、そのisOpen()メソッドは true を返します。リソース記述子をどこかに保持する必要がある場合、またはストリームを複数回読み取る必要がある場合は、これを使用しないでください。

9.6.7ByteArrayResourceクラス

バイト配列のリソース実装クラス。指定された配列から配列を作成しますByteArrayInputStreamこれは、使い捨てのものに頼らずに、任意のバイト配列からコンテンツをロードする場合に便利ですInputStreamResource

9.4ResourceLoaderインターフェース

9.4.1 概要

このインターフェイスResourceLoaderは Spring フレームワークのコア インターフェイスであり、リソースをロードするための統一されたアクセス方法を定義します。ファイル、クラスパス リソース、URL リソースなど、さまざまなタイプのリソースをロードするための統一されたメソッドを提供します。

9.4.2 一般的な方法

  • Resource getResource(String location):指定されたリソースの場所に基づいてResourceオブジェクトを取得します。リソースの場所には、ファイル パス、クラスパス、URL などがあります。特定のリソース読み込み戦略は、ResourceLoader特定の実装クラスによって決定されます。
  • ClassLoader getClassLoader(): クラスのロードに使用されるオブジェクトを取得しますClassLoaderこれは、クラスパスにリソースをロードする場合に便利です。

9.4.3 実装クラス

Spring フレームワークは、ResourceLoader次のようなインターフェイスを実装する複数のクラスを提供します。

  • DefaultResourceLoader: デフォルトのリソース ローダー。クラスパス、ファイル システム、および URL リソースをロードするために使用できます。
  • FileSystemResourceLoader: ファイル システムにリソースをロードするために使用されます。
  • ClassPathResourceLoader: クラスパスの下のリソースをロードするために使用されます。
  • ServletContextResourceLoader: Web アプリケーションのコンテキストでリソースをロードするために使用されます。

9.4.4 基本的な使用例

public static void main(String[] args) {
    
    
    // 创建Spring应用上下文,从类路径中加载配置文件
    ApplicationContext ctx = new ClassPathXmlApplicationContext();
    //        通过ApplicationContext访问资源
    //        ApplicationContext实例获取Resource实例时,
    //        默认采用与ApplicationContext相同的资源访问策略
    Resource res = ctx.getResource("atguigu.txt");
    System.out.println(res.getFilename());
}

例証します:

Spring は、ApplicationContext と同じ戦略を使用してリソースにアクセスします。つまり、ApplicationContext が ClassPathXmlApplicationContext の場合、res は ClassPathResource インスタンスになります。

public static void main(String[] args) {
    
    
    // 创建Spring应用上下文,指定文件系统路径加载配置文件
    ApplicationContext ctx = new FileSystemXmlApplicationContext();
    Resource res = ctx.getResource("atguigu.txt");
    System.out.println(res.getFilename());
}

例証します:

Spring は、ApplicationContext と同じ戦略を使用してリソースにアクセスします。つまり、ApplicationContext が FileSystemXmlApplicationContext の場合、res は FileSystemResource インスタンスです。

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.Resource;

public class ResourceLoaderExample {
    
    

    public static void main(String[] args) {
    
    
        // 创建一个ApplicationContext容器对象,该对象会读取classpath(类路径)下的名为applicationContext.xml的配置文件
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

        // 使用 classpath: 前缀指定使用 ClassPathResource 实现类
        Resource resource1 = context.getResource("classpath:config.properties");
        System.out.println("Resource 1: " + resource1.getClass().getSimpleName());

        // 使用 file: 前缀指定使用 FileSystemResource 实现类
        Resource resource2 = context.getResource("file:/path/to/file.txt");
        System.out.println("Resource 2: " + resource2.getClass().getSimpleName());

        // 使用 http: 前缀指定使用 UrlResource 实现类
        Resource resource3 = context.getResource("http://www.example.com");
        System.out.println("Resource 3: " + resource3.getClass().getSimpleName());
    }
}

例証します:

ApplicationContext の getResource() メソッドを使用して 3 つの異なるタイプのリソースを取得し、異なる接頭辞を使用して異なる Resource 実装クラスを指定します

9.5ResourceLoaderAwareインターフェース

9.5.1 概要

9.5.1.1 意味

ResourceLoaderAware は、このインターフェイスを実装する Bean に ResourceLoader インスタンスを注入するために使用される Spring Bean インターフェイスです。これは setResourceLoader(ResourceLoader resourceLoader) メソッドを定義しており、Spring コンテナは起動時に ResourceLoader インスタンスをパラメータとしてこのメ​​ソッドに渡します。

9.5.1.2 機能

ResourceLoaderAwareインターフェースを実装したクラスは、SpringコンテナのResourceLoaderインスタンスを取得することで、Springコンテナが提供するリソースロード機能を利用することができます。

9.5.2 基本的な使用例

ステップ 1: Bean の作成

package com.atguigu.spring6.resouceloader;

import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.ResourceLoader;

public class TestBean implements ResourceLoaderAware {
    
    

    private ResourceLoader resourceLoader;

    //实现ResourceLoaderAware接口必须实现的方法
	//如果把该Bean部署在Spring容器中,该方法将会有Spring容器负责调用。
	//SPring容器调用该方法时,Spring会将自身作为参数传给该方法。
    public void setResourceLoader(ResourceLoader resourceLoader) {
    
    
        this.resourceLoader = resourceLoader;
    }

    //返回ResourceLoader对象的应用
    public ResourceLoader getResourceLoader(){
    
    
        return this.resourceLoader;
    }

}

例証します:

  • ResourceLoaderAware インターフェイスを実装するには、setResourceLoaderメソッドを実装する必要があります。

ステップ 2: Bean の構成

<?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="testBean" class="com.atguigu.spring6.resouceloader.TestBean"></bean>
</beans>

ステップ 3: デモ

public static void main(String[] args) {
    
    
    //Spring容器会将一个ResourceLoader对象作为该方法的参数传入
    ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");
    TestBean testBean = ctx.getBean("testBean",TestBean.class);
    //获取ResourceLoader对象
    ResourceLoader resourceLoader = testBean.getResourceLoader();
    System.out.println("Spring容器将自身注入到ResourceLoaderAware Bean 中 ? :" + (resourceLoader == ctx));
    //加载其他资源
    Resource resource = resourceLoader.getResource("atguigu.txt");
    System.out.println(resource.getFilename());
    System.out.println(resource.getDescription());
}

例証します:

ApplicationContextインターフェースの実装クラスがインターフェースClassPathXmlApplicationContextを実装するため、インスタンスオブジェクトも「ResourceLoader」の機能を持ちます。したがって、このインターフェースを実装したオブジェクトは、Spring コンテナーが提供するリソース読み込み機能を使用できます。ResourceLoaderClassPathXmlApplicationContextResourceLoaderAware

9.6 Resource リソースを動的に取得する

9.6.1 概要

9.6.1.1 意味

Spring フレームワークは、戦略パターンを最大限に活用してリソースへのアクセスを簡素化するだけでなく、戦略パターンと IoC を完全に組み合わせて、Spring リソースへのアクセスを最大限に簡素化します。アプリケーション内の Bean インスタンスがリソースにアクセスする必要がある場合、Spring には依存関係注入を直接使用するというより良い解決策があります。

9.6.1.2 機能

コードでリソース インスタンスを取得するには、プログラムがリソース インスタンスを取得するときに、FileSystemResource を通じてインスタンスを作成するか、ClassPathResource を通じてインスタンスを作成するか、getResource() メソッドを通じてインスタンスを取得するかにかかわらず、常にリソースの場所を提供する必要があります。 ApplicationContext のリソースの場所を指定します。これは、リソースの物理的な位置がコードに組み込まれており、リソースの位置が変更された場合はプログラムを書き直す必要があることを意味します。したがって、一般的には、依存関係注入の方法を採用し、Springに Bean インスタンスのリソースを注入させることが推奨されます。

9.6.2 基本的な使用例

ステップ 1: 依存関係注入クラスを作成し、プロパティとメソッドを定義する

public class ResourceBean {
    
    
    
    private Resource res;
    
    public void setRes(Resource res) {
    
    
        this.res = res;
    }
    public Resource getRes() {
    
    
        return res;
    }
    
    public void parse(){
    
    
        System.out.println(res.getFilename());
        System.out.println(res.getDescription());
    }
}

ステップ 2: Spring 構成ファイルを作成し、依存関係の注入を構成する

<?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="resourceBean" class="com.atguigu.spring6.resouceloader.ResourceBean" >
      <!-- 可以使用file:、http:、ftp:等前缀强制Spring采用对应的资源访问策略 -->
      <!-- 如果不采用任何前缀,则Spring将采用与该ApplicationContext相同的资源访问策略来访问资源 -->
        <property name="res" value="classpath:atguigu.txt"/>
    </bean>
</beans>

ステップ 3: デモ

public static void main(String[] args) {
    
    
    ApplicationContext ctx =
        new ClassPathXmlApplicationContext("bean.xml");
    ResourceBean resourceBean = ctx.getBean("resourceBean",ResourceBean.class);
    resourceBean.parse();
}

9.7 リソースアクセスパスの決定

9.7.1 概要

ApplicationContext インスタンスを作成する方法に関係なく、ApplicationContext の構成ファイルを指定する必要があります。Spring では 1 つ以上の XML 構成ファイルを使用できます。プログラムが ApplicationContext インスタンスを作成するとき、通常は Resource の形式で構成ファイルにアクセスするため、ApplicationContext は ClassPathResource、FileSystemResource、ServletContextResource などのリソース アクセス メソッドを完全にサポートします。

9.7.2 アクセスパスを指定するクラスの実装

(1) ClassPathXMLApplicationContext: リソースへのアクセスに ClassPathResource を使用することに対応します。

(2) FileSystemXmlApplicationContext: リソースへのアクセスに FileSystemResource を使用することに対応します。

(3) XmlWebApplicationContext: リソース アクセスに ServletContextResource を使用することに対応します。

詳細な手順については、リソースの実装クラスを参照してください。

9.7.3 アクセスパスを指定するプレフィックス

9.7.3.1クラスパス接頭辞

public class Demo1 {
    
    

    public static void main(String[] args) {
    
    
        /*
         * 通过搜索文件系统路径下的xml文件创建ApplicationContext,
         * 但通过指定classpath:前缀强制搜索类加载路径
         * classpath:bean.xml
         * */
        ApplicationContext ctx =
                new ClassPathXmlApplicationContext("classpath:bean.xml");
        System.out.println(ctx);
        Resource resource = ctx.getResource("atguigu.txt");
        System.out.println(resource.getFilename());
        System.out.println(resource.getDescription());
    }
}

例証します:

ApplicationContext を使用する場合、パスを指定するときは、プレフィックスとして **classpath:** を使用します

9.7.3.2クラスパスワイルドカード

ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath*:bean.xml");

例証します:

ApplicationContext を使用する場合、パスを指定するときに、プレフィックスとして classpath* を使用します。これは、Spring がクラス読み込みパスでこのルールを満たすすべての構成ファイルを検索することを意味します。例: bean.xml、beans.xml

9.7.3.3 ワイルドカードのその他の使用法

ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:bean*.xml");

例証します:

複数の構成ファイルを一度にロードする方法: 構成ファイルを指定するときにワイルドカードを使用します

ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath*:bean*.xml");

例証します:

Spring では、クラスパス*: プレフィックスとワイルドカードの組み合わせが可能です

10. 国際化: i18n

メモの要約:

  1. 概要:さまざまな言語文化、地域のニーズに適応するソフトウェア、アプリケーション、または Web サイトの設計

  2. Java の国際化:

    • ResourceBundleクラス: さまざまな言語環境でリソース ファイルをロードおよび管理するために使用される国際化ツールクラスです

    • 設定ファイルの命名規則:basename_language_country.properties例:messages_en_CB.properties

    • 基本的な使用例:

      1. リソース構成ファイルの作成

      2. ResourceBundle クラスを通じて取得

        public static void main(String[] args) {
                   
                   
            ResourceBundle resourceBundle = ResourceBundle.getBundle("messages", new Locale("en", "GB"));
            String string = resourceBundle.getString("test");
            System.out.println(string);
        }
        
  3. Spring6 の国際化

    ステップ 1: プロパティリソース構成ファイルを作成する

    ステップ 2: Spring 構成ファイルを作成し、MessageSource を構成する

    ステップ 3: Spring6 構成ファイルにキーを挿入して、リソース構成ファイル内のキーを取得する

    public static void main(String[] args) {
           
           
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        //传递动态参数,使用数组形式对应{0} {1}顺序
        Object[] objs = new Object[]{
           
           "atguigu",new Date().toString()};
        //www.atguigu.com为资源文件的key值,
        //objs为资源文件value值所需要的参数,Local.CHINA为国际化为语言
        String str=context.getMessage("www.atguigu.com", objs, Locale.CHINA);
        System.out.println(str);
    }
    

10.1 概要

国際化とは、多くの場合 i18n (i + 18 文字 + n) と略され、さまざまな言語、文化、地域のニーズに適応するソフトウェア、アプリケーション、または Web サイトを設計することを指します。一般に、ソフトウェアの国際化は構成ファイルによって実現されますが、2 つの言語をサポートしたい場合は、2 つのバージョンの構成ファイルが必要です。

10.2 Javaの国際化

10.2.1createConstant方法

画像-20230525173916281

例証します:

java.util.Localeは現在のユーザーが属するロケールなどの情報を指定するために使用され、java.util.ResourceBundleはバインディングに対応するリソースファイルを検索するために使用されます。Locale には言語情報と国情報が含まれます。デフォルトのロケール オブジェクトを作成するときに Locale によって使用される静的メソッドは次のとおりです。

10.2.2 ResourceBundle クラス

ResourceBundle は、国際化のために Java によって提供されるツール クラスで、さまざまな言語環境でリソース ファイルをロードおよび管理するために使用されます。

10.2.3 設定ファイルの命名規則

basename_language_country.properties

例証します:

Java が認識するには、上記の命名規則に従う必要があります。このうち、ベース名は必須ですが、言語と国はオプションです。ここには優先順位の概念があり、messages.properties とmessages_zh_CN.propertes の両方が同時に提供され、提供されたロケールが en_CN に準拠している場合、messages_en_CN.propertes 構成ファイルが最初に検索されます。見つからない場合は、メッセージが検索されます。 .properties 設定が検索されます。ドキュメント。最後に、プロンプトが表示されたら、すべての構成ファイルをクラスパス (通常はリソース ディレクトリ) に配置する必要があります。

10.3 基本的な使用例

ステップ 1: リソースリソースファイルに構成ファイルを作成する

画像-20230525175111010

例証します:

作成されたプロパティ ファイルは Java の国際命名規則に準拠しているため、リソース バンドルの「メッセージ」はシステムによって自動的に生成されます。

ステップ 2: さまざまな言語で構成ファイルを作成する

test=123
// 
test=456

ステップ 3: デモ

public class ResourceBundleExample {
    
    

    public static void main(String[] args) {
    
    
        // 获取名为 "messages" 的资源包,使用英国地区设置(Locale)
        ResourceBundle resourceBundle = ResourceBundle.getBundle("messages", new Locale("en", "GB"));
        
        // 从资源包中获取名为 "test" 的字符串
        String string = resourceBundle.getString("test");
        
        System.out.println(string);
    }
}

例証します:

ResourceBundle クラスは、国際化中にさまざまな言語環境でリソース ファイルを管理するために使用され、Locale は現在のユーザーが属する言語環境を指定するために使用されます。

10.4Spring6 の国際化

ステップ 1: リソース ファイルを作成する

国際化されたファイル命名形式: 基本的な name_ language_country.properties

{0}、{1} などの内容は動的パラメータです。

画像-20221207140024056

(1) atguigu_en_US.propertiesを作成する

www.atguigu.com=welcome {0},时间:{1}

(2) atguigu_zh_CN.propertiesを作成する

www.atguigu.com=欢迎 {0},时间:{1}

ステップ 2: Spring 構成ファイルを作成し、MessageSource を構成する

<?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="messageSource"
          class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basenames">
            <list>
                <value>atguigu</value>
            </list>
        </property>
        <property name="defaultEncoding">
            <value>utf-8</value>
        </property>
    </bean>
</beans>

例証します:

Spring 6 では、ResourceBundleMessageSource の ID に messageSource という名前を付けることで、不必要な設定と明示的な参照を減らし、Spring 6 で自動インジェクションを実現できるようになります。

ステップ 3: テストクラスを作成する

package com.atguigu.spring6.javai18n;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.Date;
import java.util.Locale;

public class Demo2 {
    
    

    public static void main(String[] args) {
    
    
        
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        
        //传递动态参数,使用数组形式对应{0} {1}顺序
        Object[] objs = new Object[]{
    
    "atguigu",new Date().toString()};

        //www.atguigu.com为资源文件的key值,
        //objs为资源文件value值所需要的参数,Local.CHINA为国际化为语言
        String str=context.getMessage("www.atguigu.com", objs, Locale.CHINA);
        System.out.println(str);
    }
}

11. データ検証: 検証

メモの要約:

  1. 概要: データ検証 (検証) は、アプリケーションにユーザーが入力したデータを検証して、データが予想されるルールと制約に準拠していることを確認するプロセスです。

  2. 検証は Validator インターフェイスを通じて実装されます。

    ステップ 1: インポートhibernate-validatorjakarta.el依存関係

    ステップ 2: エンティティ クラスを作成する

    ステップ 3: Validator インターフェイスを実装する

    ステップ 4:DataBinderバリデーターを実装する

  3. Bean Validation アノテーションを使用して検証を実装します (推奨):

    ステップ 1: 構成ファイルクラスを作成する

    ステップ 2: エンティティ クラスを作成し、アノテーションを使用して検証ルールを定義する

    ステップ 3: バリデーターサービスを作成する (@Autowired を使用)

    ステップ 4: 検証

  4. 検証は次のメソッドを通じて実装されます。

    ステップ 1: 構成ファイルクラスを作成する

    ステップ 2: エンティティ クラスを作成し、アノテーションを使用して検証ルールを定義する

    ステップ 3: バリデーター・サービスを作成する (@Valid を使用)

  5. カスタム検証に合格します (補足):

    ステップ 1: 検証アノテーションをカスタマイズする

    ステップ 2: 実装された検証クラスを作成する

  6. その他のアノテーションについては、スプリングブート リクエスト パラメータの検証を参照してください。アノテーション @Validated の使用、手動検証、カスタム verify_validate アノテーション verify_sayyy のブログ - CSDN ブログ

11.1 概要

データ検証 (検証) は、アプリケーションのユーザー入力データを検証して、データが予期されたルールと制約に準拠していることを確認するプロセスです。Java で一般的に使用されるデータ検証フレームワークは Validation API です。これは Java EE の一部であり、Spring フレームワークでも統合およびサポートされています。

11.2 Validator インターフェースによる基本的なユースケースの検証

例証します:

インターフェイスを介してデータ検証を実装することValidatorは、データ検証に Validation API を使用するもう 1 つの方法です。Validatorこのインターフェイスは、より柔軟な検証メカニズムを提供し、検証ロジックとエラー メッセージをカスタマイズできます。

ステップ 1: 関連する依存関係を導入する

<dependencies>
    <dependency>
        <groupId>org.hibernate.validator</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>7.0.5.Final</version>
    </dependency>

    <dependency>
        <groupId>org.glassfish</groupId>
        <artifactId>jakarta.el</artifactId>
        <version>4.0.1</version>
    </dependency>
</dependencies>

ステップ 2: エンティティ クラスを作成する

package com.atguigu.spring6.validation.method1;

public class Person {
    
    
    private String name;
    private int age;

    public String getName() {
    
    
        return name;
    }
    public void setName(String name) {
    
    
        this.name = name;
    }
    public int getAge() {
    
    
        return age;
    }
    public void setAge(int age) {
    
    
        this.age = age;
    }
}

ステップ 3: Validator インターフェイスを実装する

public class PersonValidator implements Validator {
    
    

    // supports方法用来表示此校验用在哪个类型上
    @Override
    public boolean supports(Class<?> clazz) {
    
    
        return Person.class.equals(clazz);
    }

    // validate是设置校验逻辑的地点
    @Override
    public void validate(Object object, Errors errors) {
    
    
        ValidationUtils.rejectIfEmpty(errors, "name", "name.empty");
        Person p = (Person) object;
        if (p.getAge() < 0) {
    
    
            errors.rejectValue("age", "error value < 0");
        } else if (p.getAge() > 110) {
    
    
            errors.rejectValue("age", "error value too old");
        }
    }
}

例証します:

  • Validator インターフェイスを実装し、サポートおよび検証メソッドをオーバーライドし、ロジックを実装します。
  • ValidationUtils は、検証を迅速に実装するために Spring によってカプセル化された検証ツール クラスです。

ステップ 4: デモンストレーションを行う

public static void main(String[] args) {
    
    
    // 创建person对象
    Person person = new Person();
    person.setName("lucy");
    person.setAge(-1);

    // 创建Person对应的DataBinder
    DataBinder binder = new DataBinder(person);

    // 绑定校验
    binder.setValidator(new PersonValidator());

    // 开始校验
    binder.validate();

    // 输出结果
    BindingResult results = binder.getBindingResult();
    System.out.println(results.getAllErrors());
}

例証します:

バリデーターを使用するとDataBinder、オブジェクトのデータ検証を簡単に実行し、検証結果を取得できます。

11.3 Bean Validation アノテーションによる基本的なユースケースの検証

例証します:

Bean Validation は Java のアノテーションベースのデータ検証仕様であり、エンティティクラスの属性に対応するアノテーションを追加することでデータ検証ルールを定義できます。

よく使用される注釈:

  1. @NotNull処置: フィールド値がnullでないことを確認してください。
  2. @NotEmpty: 文字列、コレクション、または配列の値が空でないことを確認します。
  3. @NotBlank: 文字列の値が空でないこと、または空白文字のみが含まれていないことを確認します。
  4. @Min(value): フィールド値が指定された最小値以上であることを確認します。
  5. @Max(value): フィールド値が指定された最大値以下であることを確認します。
  6. @Size(max, min): フィールド値のサイズが指定された範囲内であることを確認します。
  7. @Email: フィールド値が電子メールの形式要件を満たしていることを確認します。
  8. @Pattern(regex): フィールド値が指定された正規表現と一致するかどうかを確認します。

ステップ 1: 構成ファイルクラスを作成する

@Configuration
@ComponentScan("org.example")
public class ValidationConfig {
    
    

    @Bean
    public LocalValidatorFactoryBean validator() {
    
    
        return new LocalValidatorFactoryBean();
    }
}

例証します:

  • LocalValidatorFactoryBeanValidatorFactorySpringフレームワークが提供するインターフェースを実装したクラスで、Validatorインスタンスの作成と管理に使用されます。
  • ComponentScan スキャン ルールを設定すると、パッケージ スキャンが有効になり、Spring フレームワークの Bean インジェクションが容易になります。

ステップ 2: エンティティ クラスを作成し、アノテーションを使用して検証ルールを定義する

@Data
public class User {
    
    

    @NotNull
    private String name;

    @Min(0)
    @Max(120)
    private int age;
}

知らせ:

@Max および @Min アノテーションでは、データ検証の前に依存関係をインポートする必要があります。依存関係については、Validator インターフェイスを通じて確認してください。

ステップ 3: バリデーターを作成する

1. jakarta.validation.Validator を使用して検証します

@Service
public class ValidatorServiceOne {
    
    

  // 导入 jakarta.validation.Validator
    @Autowired
    Validator validator;

    public Boolean vailAge(Person person) {
    
    
        // 使用Validator的vaildate方法进行数据验证
        Set<ConstraintViolation<Person>> validate = validator.validate(person);
        return validate.isEmpty();
    }
}

例証します:

検証プロセスでは、Validatorユーザー オブジェクトの各属性が順番にチェックされ、指定された制約を満たしているかどうかが検証されます。属性の値が制約を満たさない場合、ConstraintViolation属性名、違反した制約のタイプ、エラー メッセージなど、制約違反の詳細を含むオブジェクトが生成されます。最後に、これらのConstraintViolationオブジェクトはコレクションに集められてSet返されます。

2. org.springframework.validation.Validator を使用して検証する

@Service
public class ValidatorServiceTwo {
    
    

     // 导入  org.springframework.validation.Validator;
    @Autowired
    private Validator validator; 

    public boolean validaPersonByValidator(User user) {
    
    
        // 创建 BindException 对象,用于收集校验错误信息
        BindException bindException = new BindException(user, user.getName());
        
        // 使用 Validator 对象对用户对象进行校验,将校验结果收集到 bindException 中
        validator.validate(user, bindException);
        
        // 判断 bindException 中是否存在校验错误信息
        return bindException.hasErrors();
    }
}

例証します:

はパッケージ内のクラスでBindExceptionありインターフェイスから継承し、検証エラー情報を収集するために使用されます。オブジェクトを作成すると、検証結果をオブジェクトに収集して、その後のエラー情報の処理を容易にすることができます。org.springframework.validationorg.springframework.validation.ErrorsBindException

知らせ:

Validator を使用する場合は、Validator インターフェイスを使用する場合と同様に、依存関係をインポートする必要があります。

ステップ 4: デモンストレーションを行う

1. jakarta.validation.Validator を使用して検証します

  @Test
    public void testMyService1() {
    
    
        ApplicationContext context = new AnnotationConfigApplicationContext(ValidationConfig.class);
        MyService1 myService = context.getBean(MyService1.class);
        User user = new User();
        user.setAge(-1);
        boolean validator = myService.validator(user);
        System.out.println(validator);
    }

2. org.springframework.validation.Validator を使用して検証する

    @Test
    public void testMyService2() {
    
    
        ApplicationContext context = new AnnotationConfigApplicationContext(ValidationConfig.class);
        MyService2 myService = context.getBean(MyService2.class);
        User user = new User();
        user.setName("lucy");
        user.setAge(130);
        user.setAge(-1);
        boolean validator = myService.validaPersonByValidator(user);
        System.out.println(validator);
    }

11.4 基本的な使用例 - メソッドによる検証

例証します:

メソッドベースの検証とは、特定のメソッドに検証アノテーションを使用して、メソッドの実行中にメソッドの入力パラメータ、戻り値、またはステータスを検証することを指します。Spring は、メソッドベースの検証を実装するための@Validatedアノテーションと検証アノテーション ( @NotNull@NotBlank、など) を提供します。@Min@Max

ステップ 1: 構成ファイルクラスを作成する

@Configuration
@ComponentScan("org.example")
public class ValidationConfig {
    
    

    @Bean
    public MethodValidationPostProcessor validationPostProcessor() {
    
    
        return new MethodValidationPostProcessor();
    }
}

例証します:

MethodValidationPostProcessorは、メソッド呼び出し時のパラメータ検証のために Spring によって提供されるポストプロセッサです @Validatedアノテーションでマークされたメソッドを自動的にインターセプトし、メソッドのパラメータを検証できます。

ステップ 2: エンティティ クラスを作成し、アノテーションを使用して検証ルールを定義する

@Data
public class User {
    
    

    @NotNull
    private String name;

    @Min(0)
    @Max(120)
    private int age;

    @Pattern(regexp = "^1(3|4|5|7|8)\\d{9}$",message = "手机号码格式错误")
    @NotBlank(message = "手机号码不能为空")
    private String phone;
}

ステップ 3: バリデーターを作成する

@Service
@Validated
public class MyService {
    
    
    //	使用 @Valid 注解标记了 User 参数,表示对该参数进行校验、使用 @NotNull 注解标记了 User 参数,表示该参数不能为空。
    public String testParams(@NotNull @Valid User user) {
    
    
        return user.toString();
    }
}

例証します:

検証が失敗した場合は ConstraintViolationException がスローされ、検証が成功した場合は他のビジネス ロジックが実行されます。

ステップ 4: デモンストレーションを行う

@Test
public void testMyService1() {
    
    
    ApplicationContext context = new AnnotationConfigApplicationContext(ValidationConfig.class);
    MyService myService = context.getBean(MyService.class);
    User user = new User();
    user.setAge(-1);
    myService.testParams(user);
}

11.5 基本的なユースケース - カスタム検証をパスする

ステップ 1: 検証アノテーションをカスタマイズする

@Target({
    
    ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
// @Target 和 @Retention 来定义注解的使用范围和生命周期
@Documented
// @Constraint 标记该注解为校验注解,并指定对应的校验器类
@Constraint(validatedBy = {
    
    CannotBlankValidator.class})
public @interface CannotBlank {
    
    
    //默认错误消息
    String message() default "不能包含空格";

    //分组
    Class<?>[] groups() default {
    
    };

    //负载
    Class<? extends Payload>[] payload() default {
    
    };

    //指定多个时使用
    @Target({
    
    ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @interface List {
    
    
        CannotBlank[] value();
    }
}

例証します:

このアノテーションの内容実装については、既存のアノテーションに付属する部分を参照できます。

補充:

  • @Targetアノテーションは、メソッド、フィールド、アノテーション タイプ、コンストラクター、パラメーターなどのアノテーションの使用範囲を指定するために使用されます。
  • @Retention注釈は、注釈のライフサイクルを指定するために使用されます。つまり、注釈情報は実行時にも保持されます。
  • @Documented注釈は、生成されたドキュメントに注釈を含める必要があることを示すために使用されます。
  • @ConstraintAnnotation は、アノテーションを検証アノテーションとしてマークし、対応するバリデーター クラスを指定しますCannotBlankValidator
  • message()このメソッドは、検証が失敗した場合に使用されるデフォルトのエラー メッセージを定義します。
  • groups()このメソッドはグループ検証に使用され、バリデーターが有効になるグループを指定できます。
  • payload()メソッドは、カスタムバリデーターで使用できるペイロードタイプを指定します。
  • @Listアノテーションは複数指定する場合に使用され@CannotBlank、複数のアノテーションを組み合わせることができます。

知らせ:

アノテーション自体は特定の検証ロジックを実装しませんが、CannotBlankValidatorバリデーター クラスを通じて特定の検証ロジックを実装します。

ステップ 2: 検証クラスを作成する

public class CannotBlankValidator implements ConstraintValidator<CannotBlank, String> {
    
    

    	// initialize() 方法用于初始化校验器,在校验之前进行一些初始化操作。可以获取注解中的属性值,并进行相应的处理
        @Override
        public void initialize(CannotBlank constraintAnnotation) {
    
    
        }

    	// isValid() 方法是校验的核心逻辑,用于判断被校验的值是否符合自定义的校验规则
        @Override
        public boolean isValid(String value, ConstraintValidatorContext context) {
    
    
                //null时不进行校验
                if (value != null && value.contains(" ")) {
    
    
                        //获取默认提示信息
                        String defaultConstraintMessageTemplate = context.getDefaultConstraintMessageTemplate();
                        System.out.println("default message :" + defaultConstraintMessageTemplate);
                        //禁用默认提示信息
                        context.disableDefaultConstraintViolation();
                        //设置提示语
                        context.buildConstraintViolationWithTemplate("can not contains blank").addConstraintViolation();
                        return false;
                }
                return true;
        }
}

例証します:

  • カスタム バリデータ クラスを作成します。ConstraintValidator インターフェイスを実装し、検証するアノテーション タイプと検証する値のタイプを指定します。検証ロジックでは、カスタマイズされた検証ルールを実装し、必要に応じて検証結果を返します。
  • isValid()このメソッド には2 つのパラメーターがあります。
    • value: 検証する値、つまり、検証する必要があるフィールドまたはメソッドのパラメータの値。
    • context: バリデーターのコンテキスト オブジェクト。検証プロセス中に一部の動作と設定を制御するために使用されます。
  • メソッドを実装するときはisValid()、カスタマイズされた検証ルールに従って、valueパラメーターを使用して検証された値を取得し、ビジネス ロジックに従って検証できます。検証が成功した場合、戻りtrue値は検証が成功したことを示し、検証が失敗した場合、戻り値はfalse検証が失敗したことを示します。

ステップ 3: デモ

public static void main(String[] args) {
    
    
    ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ValidationConfig.class);
    ValidatorService bean = (ValidatorService) applicationContext.getBean("validatorService");
    Person person = new Person();
    person.setAge(12);
    person.setMessage("fd s  f");
    String s = bean.vailAge(person);
    System.out.println(s);
}

例証します:

このステップでは、カスタム アノテーションによる検証のためのカスタム ルールのみを実装します。検証の実装方法の詳細については、实现検証メソッドを参照する必要があります。

12. 事前コンパイル: AOT

メモの要約:

  1. 概要:
    • 意味: Ahead of Time Compilation (AOT) は、を実行する前にプログラム コードをマシン コードにコンパイルするテクノロジです。従来のジャストインタイム コンパイル (JIT) とは対照的に、ジャストインタイム コンパイルはプログラム コードを 1 行ずつマシン コードに解釈し、実行時に実行します。
    • Graalvm: Spring 6 でサポートされる AOT テクノロジー。この GraalVM が基礎的なサポートであり、Spring は GraalVM ネイティブ イメージに対する最上級のサポートも提供します。GraalVM は、Java およびその他の JVM 言語で記述されたアプリケーションの実行を高速化するように設計された高性能 JDK であり、JavaScript、Python、およびその他の多くの一般的な言語のランタイムも提供します。
    • ネイティブ イメージ: JVM での AOT のこのソリューションに加えて、業界では Java AOT を実装する別の方法があります。これは、JVM を直接放棄し、C/C++ などのコンパイラーを通じてコードをマシン コードに直接コンパイルしてから、走る。これは間違いなく、Java 言語設計、つまり GraalVM Native Image を直接覆すアイデアです。
  2. ネイティブイメージの構築プロセス
    • GraalVMのインストール
    • C++ コンパイル環境をインストールする
    • コードを記述してネイティブ イメージを構築する

12.1 概要

12.1.1 意味

Ahead of Time Compilation (AOT) は、を実行する前にプログラムコードをマシン コードにコンパイルするテクノロジです。従来のジャストインタイム コンパイル (JIT) とは対照的に、ジャストインタイム コンパイルはプログラム コードを 1 行ずつマシン コードに解釈し、実行時に実行します。

AOTの利点

  1. 起動時間の短縮: コードはマシンコードにコンパイルされているため、実行時にコンパイルして解釈する必要がなく、直接実行できるため、起動時間が短縮されます
  2. 実行パフォーマンスの向上: AOT コンパイルは、コードの最適化、インライン化、不要なチェックの削除などを含む包括的な静的最適化を実行できます。これらの最適化はコンパイル時に実行され、より高い実行パフォーマンスを提供できます
  3. セキュリティの向上: AOT コンパイルは、ソース コードをマシン コードにコンパイルし、ソース コードのロジックを隠しセキュリティを強化します。

AOTのデメリット

  1. コンパイル出力の拡大: AOT コンパイルでは、ソース コードまたは中間コードをマシン コードに完全にコンパイルするため、コンパイル出力は通常、ソース コードまたはバイトコードよりも大きくなり、より多くのストレージ スペースを占有します。
  2. コンパイル時間の遅延: プログラムを実行する前に AOT コンパイルを行う必要があるため、特に大規模なコード ベースまたは複雑なプロジェクトの場合、開発およびビルド時間のコストが増加します。
  3. 実行時の最適化の欠如: AOT コンパイルはプログラムの実行前に実行されるため、実際の実行時のコンテキスト情報に従って最適化することができず、変化する実行環境に動的に適応することができません。

12.1.2 JIT と AOT の違い

JIT、ジャストインタイム、動的(ジャストインタイム)コンパイル、実行中のコンパイル。

プログラムの実行中に、ホット コードがアルゴリズムに従って計算され、JIT がリアルタイムでコンパイルされます。この方法は、スループットが高く、実行時のパフォーマンス ボーナスがあり、より高速に実行でき、コードを動的に生成できます。ただし、起動速度は遅く、JIT 階層化メカニズムをトリガーするには、ある程度の時間と呼び出し頻度がかかります。JIT の欠点は、コンパイルにランタイム リソースが必要なため、プロセスの遅延が発生する可能性があることです。

AOT (Ahead Of Time) は、実行前コンパイル、事前コンパイルを指します。

AOT コンパイルは、メモリ使用量が少なく起動速度が速いため、ソース コードをマシン コードに直接変換できます。ランタイムなしで実行でき、ランタイムを最終プログラムに直接静的にリンクできますが、ランタイム パフォーマンスのボーナスはなく、さらなる最適化を図るため、AOT の欠点は、プログラムを実行する前にコンパイルするとプログラムのインストール時間が長くなる点です。

一般に、JIT ジャストインタイム コンパイルとは、プログラムの実行中にハードウェア上で直接実行できるマシン コードにバイトコードを変換し、それをホスティング環境に展開するプロセスを指します。AOT コンパイルとは、プログラムを実行する前にバイトコードをマシンコードに変換するプロセスを指します。

画像-20230526155600385

例証します:

.java -> .class -> (jaotc コンパイルツールを使用) -> .so (プログラム関数ライブラリ、つまり、他のプログラムで使用できるコンパイルされたコードとデータ)

12.1.3Graalvm

GraalVM は、Spring 6 でサポートされる AOT テクノロジーの基礎的なサポートです。Spring は、GraalVM ネイティブ イメージに対する最上級のサポートも提供します。GraalVM は、Java およびその他の JVM 言語で記述されたアプリケーションの実行を高速化するように設計された高性能 JDK であり、JavaScript、Python、およびその他の多くの一般的な言語のランタイムも提供します。GraalVM は、Java アプリケーションを実行する 2 つの方法を提供します。HotSpot JVM 上の Graal ジャストインタイム (JIT) コンパイラーを使用する方法と、事前にコンパイルされたネイティブ実行可能ファイル (AOT) として使用する方法です。GraalVM の多言語機能により、外国語呼び出しのコストを削減しながら、単一のアプリケーションで複数のプログラミング言語を混在させることができます。GraalVM は、Java で書かれた高度なジャストインタイム (JIT) 最適化コンパイラーを HotSpot Java 仮想マシンに追加します。

GraalVM には次の機能があります。

(1)必要なコンピューティング リソースが少なく、より高速で無駄のないコードを生成する高度な最適化コンパイラー

(2) AOT ネイティブ イメージ コンパイルは、Java アプリケーションを事前にネイティブ バイナリにコンパイルし、すぐに開始し、予熱なしで最大のパフォーマンスを実現します。

(3) ポリグロット プログラミングは、追加のオーバーヘッドなしで、単一のアプリケーションで人気のある言語の最高の機能とライブラリを活用します。

(4) Java および複数の言語でリソース消費をデバッグ、監視、分析、最適化するための高度なツール

一般的にクラウドネイティブの要件は高くないため、短期的には 2.7.X バージョンと JDK8 を使い続けることもできますが、Spring は正式に Spring 6 の正式版をリリースしました。

12.1.4ネイティブ画像

現在、業界では、JVM で AOT を実行するこのソリューションに加えて、Java AOT を実装する別の方法があります。これは、JVM を直接放棄し、C のようなコンパイラを通じてコードをマシンコードに直接コンパイルすることです。 /C++ を選択して実行します。これは間違いなく、Java 言語設計、つまり GraalVM Native Image を直接覆すアイデアです。C 言語を通じて超小型のランタイム コンポーネントを実装します - Substrate VM は基本的に JVM のさまざまな機能を実装しますが、十分に軽量で簡単に埋め込むことができるため、Java 言語とエンジニアリングが JVM の制限を取り除くことができます。 . 本当に C/C++ と同じ AOT コンパイルを実現できます。長期にわたる最適化と蓄積を経て、このソリューションは非常に良い結果を達成し、基本的にオラクルが公式に推奨する最初の Java AOT ソリューションになりました。
ネイティブ イメージは、Java コードをスタンドアロンのネイティブ実行可能ファイルまたはネイティブ共有ライブラリにコンパイルする革新的なテクノロジです。ネイティブ実行可能ファイルのビルド中に処理される Java バイトコードには、すべてのアプリケーション クラス、依存関係、サードパーティの依存ライブラリ、および必要な JDK クラスが含まれます。結果として得られる自己完結型のネイティブ実行可能ファイルは、JVM を必要としない、個々のオペレーティング システムおよびマシン アーキテクチャに固有のものです。

12.2ネイティブイメージの構築プロセス

12.2.1GraalVMのインストール

ステップ 1: GraalVM をダウンロードする

公式 Web サイトにアクセスしてダウンロードします: https://www.graalvm.org/downloads/

画像-20221207153944132

画像-20221207152841304

ステップ 2: 環境変数を構成する

GRAALVM_HOME を追加

画像-20221207110539954

JAVA_HOME を graalvm の場所に変更します。

画像-20221207153724340

graalvm のビンの場所へのパスを変更します。

画像-20221207153755732

コマンドを使用してインストールが成功したかどうかを確認します

画像-20221207153642253

ステップ 3: ネイティブ イメージ プラグインをインストールする

コマンド gu installnative-image を使用してダウンロードしてインストールします

画像-20221207155009832

12.2.2 C++ コンパイル環境のインストール

ステップ 1: Visual Studio インストール ソフトウェアをダウンロードする

https://visualstudio.microsoft.com/zh-hans/downloads/

画像-20221219112426052

ステップ 2: Visual Studio をインストールする

画像-20221207155726572

画像-20221207155756512

ステップ 3: Visual Studio 環境変数を追加する

INCLUDE、LIB、およびパスを構成する

画像-20221207110947997

画像-20221207111012582

画像-20221207111105569

ステップ 4: ツールを開いてツール内で操作する

画像-20221207111206279

12.2.3 コードを記述してネイティブ イメージを構築する

ステップ 1: Java コードを作成する

public class Hello {
    
    

    public static void main(String[] args) {
    
    
        System.out.println("hello world");
    }
}

ステップ 2: ファイルをディレクトリにコピーし、コンパイルを実行します。

画像-20221207111420056

ステップ 3: ネイティブ イメージを構築する

画像-20221207111509837

画像-20221207111609878

ステップ 4: ビルドされたファイルを表示する

画像-20221207111644950

ステップ 5: ビルドされたファイルを実行する

画像-20221207111731150

Hello によって最終的にパッケージ化されたバイナリ ファイルのサイズは 11M であることがわかります。これは、SVM と JDK のさまざまなライブラリを含めた後のサイズです。C/C++ のバイナリ ファイルよりも大きいですが、完全なバイナリ ファイルよりも小さいです。 JVM はすでに非常に小さいと言えます。

JVM を使用して実行する場合と比較して、ネイティブ イメージははるかに高速であり、CPU 使用率が低くなります。また、ネイティブ イメージが起動速度とメモリ使用量を大幅に向上させることを条件として、さまざまな公式実験データからもわかります。

画像-20221207111947283

画像-20221207112009852

知識ガソリンスタンド

1.ResourceLoaderとResource実装クラスの違い

ResourceLoaderResourceインターフェースの実装クラスとの主な違いは以下のとおりです

  1. ResourceLoader実装クラスは主にリソースをロードするClassPathResourceLoaderために使用され、クラスパス下のリソースのロード、UrlResourceLoaderURL リソースのロード、FileSystemResourceLoaderファイル システム内のリソースのロードなど、リソースをロードするためのメソッドを提供します。
  2. Resource実装クラスは主にリソースにアクセスして操作するClassPathResourceために使用され、クラスパス下のリソースへのアクセス、UrlResourceURLリソースへのアクセス、FileSystemResourceファイルシステム上のリソースへのアクセスなど、リソースに対する具体的な操作方法を提供します。
  3. ResourceLoader実装クラスは通常、リソース読み込み機能を提供するためにSpring フレームワークによって内部的に使用され、アプリケーションでは直接使用されません。
  4. Resource実装クラスはアプリケーションで使用でき、それを通じてリソースの情報とコンテンツを取得、読み取り、操作できます。

一般に、の実装クラスは主にリソースのロードResourceLoaderを担当しの実装クラスは主にリソースへのアクセスと操作を担当します。これらはフレームワーク内でさまざまな役割を果たしますが、すべてアプリケーション内のリソースの処理と管理に使用されます。Resource

画像-20230526220018997

例証します:

Resource インターフェースは Spring のリソースにアクセスするための抽象化であり、Resource インターフェース自体は規定を提供するだけであり、以下のような多数の実装クラスが存在します。これらはすべて、実際のシステムの基礎となるリソースから抽象化されたリソース記述子です。一般に、Spring ではリソースは URL 形式およびワイルドカード文字を使用した Ant 形式のリソース アドレスとして記述されます。

画像-20230526220042075

例証します:

インターフェイス はResourceLoader、その名前が示すように、Resource インスタンスのオブジェクトを迅速に返す (つまり、ロードする) ように設計されています。

詳細な参考ドキュメント: Spring Framework ソース コード分析 (IoC): リソース、リソースローダー、コンテナーの関係 - Tencent Cloud 開発者コミュニティ - Tencent Cloud (tencent.com)

おすすめ

転載: blog.csdn.net/D_boj/article/details/132286524