ホームページ  >  記事  >  Java  >  Spring トランザクションの詳細な分析 (例付き)

Spring トランザクションの詳細な分析 (例付き)

不言
不言転載
2019-01-31 10:35:393018ブラウズ

この記事では、Spring トランザクションの詳細な分析 (例を示します) を提供します。必要な方は参考にしていただければ幸いです。

誰もが Spring トランザクション管理を頻繁に使用していると思いますが、それは @Transactional アノテーションまたは XML でのトランザクション関連の設定に限定される可能性があります。いずれにせよ、毎日mayで十分です。しかし、プログラマーとしては、面接のためであっても、作成するコードをより適切に制御するためにも、Spring トランザクションの詳細について学ぶ必要があります。

ここで、全員がすぐに答えられるかどうかを確認するために、いくつかの質問を投げかけます。

  • ネストされた呼び出し にトランザクション メソッドが含まれている場合、Spring ではトランザクション管理、これはどのナレッジ ポイントに属しますか?

  • 私たちが使用するフレームワークは、Hibernate/JPA または Mybatis です。最下層には session/ が必要であることは誰もが知っています。接続 オブジェクトは、操作の実行を支援するために使用されます。トランザクションの整合性を確保するには、データベース操作の複数のグループに同じ session/connection オブジェクトを使用する必要があります。また、Spring IOC によって管理されるオブジェクトはすべて によって管理されることがわかっています。デフォルト。Singleton、これを使用するとスレッド セーフティの問題が発生しないのはなぜですか? Spring は内部的に何をしているのでしょうか?

  • 人々が BPP と呼ぶものは何ですか?

  • Spring トランザクション管理にとって重要なインターフェイスは何ですか?

#1. この記事を読むために必要な基礎知識

この記事を読んだクラスメイト

Default

誰もが知っている春 ビジネス関連の知識をある程度理解している。 (追記: 特定の記事を知らない場合は、読んでからここに戻ってきてください)Spring トランザクションが Spring AOP のベスト プラクティスの 1 つであることは誰もが知っています。そこで、Spring トランザクションの基本的な知識について話しましょう。 AOP (単純な構成、使用法) を最初に知る必要があります。 AOP についてより包括的に理解したい場合は、「AOP の重要な知識ポイント (用語の紹介、包括的な使用法)」の記事を参照してください。 AOP について話すときは、AOP の基礎となる原理である動的プロキシ設計パターンについて話さなければなりません。この時点で、あなたはすでに AOP の基本を理解しています。したがって、XML/アノテーションを使用して Spring トランザクション管理を構成できます。

IOC の学習では、Spring の Bean のライフ サイクル (BPP オブジェクトにつながる) と、IOC によって管理されるオブジェクトはデフォルトでシングルトンです: シングルトン デザイン パターン (シングルトン オブジェクトがある場合)

State

" (メンバー変数付き)、非常に多くのスレッドがこのシングルトン オブジェクトにアクセスすると、スレッドのセキュリティが確保されなくなる可能性があります。では、スレッドセーフとは何でしょうか? 、スレッド セーフを解決するには多くの方法がありますが、そのうちの 1 つは次のとおりです。各スレッドに独自の変数を持たせる: ThreadLocal

上で述べた知識ポイントについてよく知らない場合は、青い「Go in」をクリックして単語を学ぶことをお勧めします。

2. 信頼できない直感の 2 つの例

2.1 最初の例

以前、友人が私に例を尋ねました。 ##Exception はサービス層でスローされ、コントローラー層でキャプチャされます。サービスで例外が発生した場合、トランザクションはロールバックされますか?

// Service方法
    
@Transactional
public Employee addEmployee() throws Exception {

    Employee employee = new Employee("3y", 23);
    employeeRepository.save(employee);
    // 假设这里出了Exception
    int i = 1 / 0;

    return employee;
}

// Controller调用
@RequestMapping("/add")
public Employee addEmployee() {
    Employee employee = null;
    try {
        employee = employeeService.addEmployee();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return employee;

}

私の

最初の反応

: ロールバックされません。

当時私が考えたのは、サービス層が例外をスローし、それがコントローラーによってキャッチされたためです。ロールバックするかどうかは、コントローラーのキャッチ コード ブロックのロジックによって決定する必要があります。キャッチ コード ブロックがロールバックしない場合は、ロールバックしないでください。

  • しかし、友人はテスト後にロールバックできると言いました。 (パパパパが顔を平手打ちする)

ドキュメントを見ると、ドキュメントには次の指示があることがわかりました:

Spring トランザクションの詳細な分析 (例付き)

デフォルトでは、チェックされた例外は次のことを行います。トランザクション インターセプターがトランザクションをロールバック対象としてマークすることはなく、RuntimeException とそのサブクラスのインスタンスが実行します。

結論: コンパイル時例外の場合、自動的にロールバックされません。実行時例外の場合は、自動的にロールバックされます

!

2.2 2 番目の例

2 番目の例は Zhihu@willows の記事から引用したもので、対応する URL は記事の最後に記載されています

ご存知のとおり、
@Transactional

アノテーションで囲まれたメソッドは Spring トランザクションで管理できます。その後、

current クラスでトランザクションのないメソッドを使用して、トランザクションのあるメソッドを呼び出すとします
、今度電話したらどうなるでしょうか?何か用事はあるのでしょうか?

コードで説明します:

// 没有事务的方法去调用有事务的方法
public Employee addEmployee2Controller() throws Exception {

    return this.addEmployee();
}

@Transactional
public Employee addEmployee() throws Exception {

    employeeRepository.deleteAll();
    Employee employee = new Employee("3y", 23);

    // 模拟异常
    int i = 1 / 0;

    return employee;
}
私の最初の直感は次のとおりです。これは Spring トランザクションの伝播メカニズムに関連しています。

実際、これは Spring トランザクション伝播メカニズムとは何の関係もありません。

以下に説明します。

Spring トランザクション管理は AOP を使用します。 、AOP 動的プロキシの最下層が使用されます。したがって、クラスまたはメソッドにアノテーション @Transactional

をマークすると、
    プロキシ オブジェクト
  • が生成されます。

    次に、写真を使って説明します:

    Spring トランザクションの詳細な分析 (例付き)

    显然地,我们拿到的是代理(Proxy)对象,调用addEmployee2Controller()方法,而addEmployee2Controller()方法的逻辑是target.addEmployee(),调用回原始对象(target)的addEmployee()。所以这次的调用压根就没有事务存在,更谈不上说Spring事务传播机制了。

    Spring トランザクションの詳細な分析 (例付き):

    Spring トランザクションの詳細な分析 (例付き)

    测试结果:压根就Spring トランザクションの詳細な分析 (例付き)

    Spring トランザクションの詳細な分析 (例付き)

    2.2.1再延伸一下

    从上面的测试我们可以发现:如果是在本类中没有事务的方法来调用标注注解@Transactional方法,最后的结论是没有事务的。那如果我将这个标注注解的方法移到别的Service对象上,有没有事务?

    @Service
    public class TestService {
    
        @Autowired
        private EmployeeRepository employeeRepository;
        
        @Transactional
        public Employee addEmployee() throws Exception {
    
            employeeRepository.deleteAll();
    
            Employee employee = new Employee("3y", 23);
    
            // 模拟异常
            int i = 1 / 0;
    
            return employee;
        }
    
    }
    
    
    @Service
    public class EmployeeService {
    
        @Autowired
        private TestService testService;
        // 没有事务的方法去调用别的类有事务的方法
        public Employee addEmployee2Controller() throws Exception {
            return testService.addEmployee();
        }
    }

    测试结果:

    Spring トランザクションの詳細な分析 (例付き)

    因为我们用的是代理对象(Proxy)去调用addEmployee()方法,那就当然有事务了。

    看完这两个例子,有没有觉得3y的直觉是真的水

    三、Spring事务传播机制

    如果嵌套调用含有事务的方法,在Spring事务管理中,这属于哪个知识点?

    在当前含有事务方法内部调用其他的方法(无论该方法是否含有事务),这就属于Spring事务传播机制的知识点范畴了。

    Spring事务基于Spring AOP,Spring AOP底层用的动态代理,动态代理有两种方式:

    • 基于接口代理(JDK代理)

      • 基于接口代理,凡是类的方法非public修饰,或者用了static关键字修饰,那这些方法都不能被Spring AOP增强

    • 基于CGLib代理(子类代理)

      • 基于子类代理,凡是类的方法使用了private、static、final修饰,那这些方法都不能被Spring AOP增强

    至于为啥以上的情况不能增强,用你们的脑瓜子想一下就知道了。

    值得说明的是:那些不能被Spring AOP增强的方法并不是不能在事务环境下工作了。只要它们被外层的事务方法调用了,由于Spring事务管理的传播级别,内部方法也可以工作在外部方法所启动的事务上下文中

    至于Spring事务传播机制的几个级别,我在这里就不贴出来了。这里只是再次解释“啥情况才是属于Spring事务传播机制的范畴”。

    四、多线程问题

    我们使用的框架可能是Hibernate/JPA或者是Mybatis,都知道的底层是需要一个session/connection对象来帮我们执行操作的。要保证事务的完整性,我们需要多组数据库操作要使用同一个session/connection对象,而我们又知道Spring IOC所管理的对象默认都是单例的,这为啥我们在使用的时候不会引发线程安全问题呢?内部Spring到底干了什么?

    回想一下当年我们学Mybaits的时候,是怎么编写Session工具类?

    Spring トランザクションの詳細な分析 (例付き)

    没错,用的就是ThreadLocal,同样地,Spring也是用的ThreadLocal。

    以下内容来源《精通 Spring4.x》

    我们知道在一般情况下,只有无状态的Bean才可以在多线程环境下共享,在Spring中,绝大部分Bean都可以声明为singleton作用域。就是因为Spring对一些Bean(如RequestContextHolder、TransactionSynchronizationManager、LocaleContextHolder等)中非线程安全状态的“状态性对象”采用ThreadLocal封装,让它们也成为线程安全的“状态性对象”,因此,有状态的Bean就能够以singleton的方式在多线程中工作。

    我们可以试着点一下进去TransactionSynchronizationManager中看一下:

    Spring トランザクションの詳細な分析 (例付き)

    5. BPP とは何ですか?

    BBP の完全名は BeanPostProcessor で、一般に オブジェクト ポストプロセッサとして知られています

    • つまり、オブジェクトを処理できます。 BeanPostProcessor「Processing」を介して。

    春の Bean 管理 (または Bean ライフサイクル) も、頻繁にテストされる知識ポイントです。これは、秋の採用で 再整理します。手順は、より重要であるため、ここに投稿します。

      ResouceLoader は構成情報をロードします。
    1. BeanDefintionReader は構成を解析します。
    2. #BeanDefintion は BeanDefintionRegistry によって管理されます
    3. BeanFactoryPostProcessor は構成情報を処理します (つまり、通常は構成情報を処理します)。 PropertyPlaceholderConfigurer 実装する)
    4. Instantiate Bean
    5. Bean
    6. が設定/実装されている場合、
    7. InstantiationAwareBean、対応するメソッドが呼び出されます

      BeanWarpper を使用してオブジェクト間の属性設定 (依存関係) を完了します
    8. ##Bean

      が設定/実装されている場合
    9. Aware インターフェイス、次に、対応するメソッドを呼び出します
    10. ##Bean が BeanPostProcessor の before メソッドで構成されている場合は、

    11. ##Bean が構成されている場合は呼び出します
    12. init-method

      または、InstantiationBean を実装し、対応するメソッドを呼び出します。

    13. Bean が BeanPostProcessor の after メソッドで構成されている場合は、

      を呼び出します。
    14. オブジェクトを HashMap に配置します
    15. 最後に、destroy メソッドまたは DisposableBean メソッドが設定されている場合は、破棄操作が実行されます
    16. BPP に関する写真もあります:

    Spring トランザクションの詳細な分析 (例付き)

    5.1 なぜ特に BPP について話すのですか?

    Spring AOP プログラミングの最下層は動的プロキシ テクノロジを使用しており、呼び出し時には

    プロキシ オブジェクトSpring トランザクションの詳細な分析 (例付き)を使用する必要があります。では、Spring はどのようにしてそれを行うのでしょうか?

    BPP を記述するだけで済みます。postProcessBeforeInitialization メソッドまたは postProcessAfterInitialization メソッドでオブジェクトを判断して、アスペクト ロジックに組み込む必要があるかどうかを確認します。必要な場合は、プロキシを生成します。オブジェクトを取得し、このプロキシ オブジェクトを返すと、最終的にコンテナに注入されるのは当然プロキシ オブジェクトです。

    Spring は BeanPostProcessor を提供します。これにより、必要なオブジェクトを「

    処理
    」できます。

    6. Spring トランザクションのいくつかの重要なインターフェイスを理解する

    Spring トランザクションは 2 つのタイプに分類できます:

    プログラムによるトランザクション (コードを介してトランザクションを実装するには) )

      宣言型トランザクション (設定を通じてトランザクションを実装する)
    • 宣言型トランザクションは多くの要素をカプセル化するため、Spring ではプログラム的なトランザクションを実装するのが比較的簡単です。 (通常は単純に使用しますが、内部はすべて非常に複雑です)、宣言型トランザクションを実装するのははるかに困難です。
    • プログラムによるトランザクションには、次の重要なインターフェイスがあります:

    TransactionDefinition: Spring 互換の

    トランザクション属性を定義します

    (トランザクション分離レベル、トランザクションなど)伝播、トランザクション タイムアウト、読み取り専用ステータス)

    • TransactionStatus: トランザクション の特定の 実行ステータスを表します (トランザクションの実行ステータス情報を取得します。これを使用することもできます)インターフェイス

      間接
    • トランザクションとその他の操作のロールバック)
    • PlatformTransactionManager: トランザクション マネージャー インターフェイス (一連の動作を定義し、特定の実装は別の永続フレームワークに渡されます)完全 ---analogyJDBC)

    • 宣言型トランザクションでは、TransactionStatus インターフェイスと PlatformTransactionManager インターフェイスに加えて、いくつかのインターフェイスがあります。重要なインターフェイス:

    Spring トランザクションの詳細な分析 (例付き)TransactionProxyFactoryBean: プロキシ オブジェクトの生成

      TransactionInterceptor: オブジェクト インターセプトの実装
    • TransactionAttrubute : トランザクション構成データ

以上がSpring トランザクションの詳細な分析 (例付き)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はcnblogs.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。