穴埋めシリーズ | 春の入門学習

最初はダークホースのプログラマーのビデオに従っていたのですが、わかりにくかったので、Wang He 先生のビデオに切り替えました。合計 3+5 日かかりました。ワン先生の講義は良かったのですが、まだソースコードを教えていなかったため、他のビデオで補う必要がありました。

第1章 春の概要

1.1. 春とは

Spring は Java フレームワークであり、Java 言語を使用して開発された、軽量のオープンソース フレームワークです。j2se プロジェクトと j2ee プロジェクトの両方で使用できます。

スプリングコアテクノロジー:ioc、aop

Spring はコンテナとも呼ばれ、コンテナとして Java オブジェクトを保持します。Spring に Java オブジェクトを作成させ、プロパティに値を割り当てることができます。

Spring の役割: デカップリングを実現し、Java オブジェクト間のカップリングを解決し、モジュール間のカップリングを解決します。

Tomcat はコンテナでもあり、サーブレット、リスナー、フィルターなどのオブジェクトを管理します。

HelloServletクラスを作成し、web.xmlを記述します。

spring: SomeServiceImpl を作成し、spring 構成ファイルを書き込みます
[外部リンク画像の転送に失敗しました。ソース サイトにはリーチ防止メカニズムが備わっている可能性があります。画像を保存して直接アップロードすることをお勧めします (img-MzdOLHsA-1675337795383) (images/image-20201023090043961.png)]

1.2 スプリングアドレス

https://spring.io

1.3 スプリングの利点

Spring はフレームワークであり、半完成のソフトウェアです。20 個のモジュールで構成されています。これはコンテナ管理オブジェクトです。コンテナには物が保持されます。Spring コンテナにはテキストや数値は保持されません。物体のふりをする。Spring はオブジェクトを格納するためのコンテナです。
(1)軽量Spring フレームワーク
で使用される jar は比較的小さく、通常は 1M または数百 kb 未満です。Spring のコア機能に必要な jar の総数は約 300 万です。
Spring フレームワークは、使用するリソースが少なく、操作効率が高いです。他のjarに依存しない

(2) インターフェイス プログラミングの場合、
Spring を切り離すことで Ioc 制御の反転が提供され、コンテナがオブジェクトとオブジェクトの依存関係を管理します。プログラム コードでオブジェクトを作成する元の方法は、コンテナーによって行われるようになりました。オブジェクト間の依存関係を切り離します。

(3) AOP プログラミングのサポート
Spring が提供する AOP 機能により、アスペクト指向プログラミングが容易になり、従来の OOP では実装が難しかった多くの機能を AOP で簡単に扱えるようになり、Spring では開発者が複雑なトランザクション管理コードから解放されます。宣言的手法を通じてトランザクションを柔軟に管理し、開発効率と品質を向上させます。

(4) 様々な優れたフレームワークを便利に統合
Spring は様々な優れたオープンソースフレームワークを排除するものではなく、むしろ Spring は様々なフレームワークの使いにくさを軽減することができる Spring は様々な優れたフレームワーク (Struts、Hibernate、MyBatis など) を直接サポートしている、など。フレームワークの使用を簡素化します。スプリングは電源タップのようなもので、その他のフレームは簡単に組み立てることができるプラグです。どのフレームを使用する必要がある場合でも、このプラグを電源タップに差し込みます。不要で簡単に削除できます。

第 2 章 IoC 制御の反転

2.1 IoCの概念

IoC、制御の反転: 制御の反転は理論であり、指針となるイデオロギーです。開発者にオブジェクトの使用方法とオブジェクトの管理方法を指導します。オブジェクトの作成、プロパティの割り当て、オブジェクトの宣言サイクルはすべて、コードの外側のコンテナーによって管理されます。

  1. IoCは制御と反転に分かれる
  • コントロール: オブジェクトの作成、属性の割り当て、オブジェクトのライフサイクル管理

  • 反転: オブジェクトを管理する開発者の権限を、コード外のコンテナ実装に移管します。オブジェクトの管理はコンテナーによって行われます。
    順方向ローテーション: 開発者は、新しいコンストラクターを使用してコード内にオブジェクトを作成します。開発者は、オブジェクトの作成、属性の割り当て、オブジェクトの開始から破棄までのプロセス全体を習得します。開発者はオブジェクトを完全に制御できます。

コンテナを通じて、コンテナ内のオブジェクトを使用できます (コンテナはオブジェクトを作成し、オブジェクトのプロパティを割り当て、オブジェクトを組み立てます)。

Spring は、オブジェクトを管理し、オブジェクトを作成し、プロパティに値を割り当てることができるコンテナーです。

  1. IoCの技術的実装

DI(Dependency Injection):Dependency Injection、略称はDIであり、IoCの技術実装です。プログラムは使用するオブジェクトの名前を指定するだけでよく、オブジェクトの作成方法、コンテナからオブジェクトを検索する方法、オブジェクトを取得する方法はすべてコンテナ自体の中に実装されます。

依存関係名詞: たとえば、ClassA が ClassB の属性またはメソッドを使用する場合、それは ClassA が ClassB に依存していると呼ばれます。

public class ClassB{
    
    
    public void createOrder(){
    
    }
}

public class ClassA{
    
    
    //属性
    private ClassB  b = new ClassB();
    
    public void buy(){
    
    
        b.createOrder();
    }
}

执行ClassAbuy()
ClassA a  = new ClassA();
a.buy();
  1. Spring フレームワークで使用される DI は IoC を実装します。

Spring フレームワークを使用すると、使用するオブジェクト名を指定するだけで済みます。名前に対応するオブジェクトをコンテナから取得します。

スプリングの底部で使用される反射メカニズムは、反射を通じてオブジェクトと属性を作成します。

2.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">
    <!--声明对象
        id:自定义对象名称,唯一值。(可以没有,spring可以提供默认名称)
        class:类的全限定名称,spring通过反射机制创建对象,不能是接口

        spring根据id,class创建对象, 把对象放入到spring的一个map对象。
        map.put(id,对象)
    -->
    <bean id="someService" class="com.bjpowernode.service.impl.SomeServiceImpl" />
</beans>
spring标准的配置文件:
1)根标签是 beans
2) beans 后面的是约束文件说明
3)beans里面是bean声明
4)什么是bean: bean就是java对象, spring容器管理的java对象,叫做bean

2.3 スプリングコンテナで作成されるオブジェクトの特徴

  1. コンテナオブジェクト ApplicationContext: インターフェース
    ApplicationContext オブジェクトを通じて、使用する他の Java オブジェクトを取得し、getBean(" <bean>id")を実行します

  2. Spring のデフォルトでは、クラスのパラメータなしのコンストラクターを呼び出してオブジェクトを作成します。

  3. Spring コンテナ オブジェクトを作成するとき、設定ファイルを読み取り、ファイル内で宣言された Java オブジェクトを作成します。Spring は
    設定ファイルを読み取り、すべての Java オブジェクトを一度に作成し、マップに配置します。
    オブジェクトはクラスで作成できる
    長所: オブジェクトがすでに作成されているため、オブジェクトの読み込みが速い
    短所: メモリを消費する

2.4 DI: 属性に値を割り当てます。

Spring はクラスのパラメータなしのコンストラクターを呼び出してオブジェクトを作成します。オブジェクトの作成後にプロパティに値を割り当てます。

属性に値を割り当てるには、1) XML 構成ファイル内のタグと属性を使用する、2) アノテーションを使用することができます。

DI 分類: 1 セット注入 (設定値注入とも呼ばれます)、2 コンストラクト注入。

2.4.1 XMLベースのDI

XML 構成ファイル内のタグと属性を使用して、オブジェクトの作成と属性の割り当てを完了します。

1) セットインジェクション。設定値インジェクションとも呼ばれます。

概念: Spring はクラス内で set メソッドを呼び出し、set メソッド内で属性の割り当てを完了できます。推奨される使用方法。

简单类型的设值注入,使用value
<bean id="mySchool" class="com.bjpowernode.ba02.School">
    <property name="name" value="北京大学"/>
    <property name="address" value="北京的海淀区"/>
</bean>
<!--引用类型set注入-->
<bean id="myStudent" class="com.bjpowernode.ba02.Student">
    <property name="name" value="李四"/>
    <property name="age" value="22" />
    <!--引用类型的赋值-->
    <property name="school" ref="mySchool" /><!--setSchool(mySchool)-->
</bean>

2) コンストラクト注入

コンストラクターインジェクション: Spring は、オブジェクトの作成中にクラス内のパラメーター化されたコンストラクターを呼び出し、プロパティに値を割り当てます。

<!--构造注入,使用name属性-->
<bean id="myStudent" class="com.bjpowernode.ba03.Student">
    <constructor-arg name="myage" value="22" />
    <constructor-arg name="myname" value="李四"/>
    <constructor-arg name="mySchool" ref="mySchool"/>
</bean>

<!--构造注入,使用index,参数的位置,构造方法参数从左往右位置是0,1,2-->
<bean id="myStudent2" class="com.bjpowernode.ba03.Student">
    <constructor-arg index="1" value="28"/>
    <constructor-arg index="0" value="张三"/>
    <constructor-arg index="2" ref="mySchool" />
</bean>

<!--构造注入,省略index属性-->
<bean id="myStudent3" class="com.bjpowernode.ba03.Student">
    <constructor-arg  value="张峰"/>
    <constructor-arg  value="28"/>
    <constructor-arg  ref="mySchool" />
</bean>

3) 参照型の自動挿入

概念: Spring は、特定のルールに従って参照型の割り当てを完了できます。参照型にのみ有効です。名前別、タイプ別のルール。

①:byName(名前による注入):Javaクラスの参照型属性の名前はSpringコンテナのBeanのID名と同じで、データ型も同じで、これらのBeanを割り当てることができます。参照タイプ。

<!-- byName 自动注入 -->
<bean id="myStudent" class="com.bjpowernode.ba04.Student" autowire="byName">
    <property name="name" value="李四"/>
    <property name="age" value="22" />
    <!--引用类型的赋值-->
    <!--<property name="school" ref="mySchool" />-->
</bean>

②: byType (型による注入): Java クラスの参照型のデータ型と Spring コンテナの Bean のクラス値が同じ起源を持ち、そのような Bean を参照型に割り当てます。

注意: 在xml配置文件中, 符合条件的对象,只能有一个。 多余一个是报错的。
<!-- byType 自动注入 -->
<bean id="myStudent" class="com.bjpowernode.ba05.Student" autowire="byType">
    <property name="name" value="张三"/>
    <property name="age" value="26" />
    <!--引用类型的赋值-->
    <!--<property name="school" ref="mySchool" />-->
</bean>

4) ジョブ IoC

要件: ユーザー登録操作をシミュレートします。

daoインターフェース(UserDao)のメソッドinsertUser(SysUser user)をインターフェース内に定義する必要があります。インターフェースMySqlUserDaoの実装クラスを定義します。insertUser
()メソッドはデータ操作を行う必要はありません。「daoは実行に使用されます」と出力されます。挿入操作」。

サービス インターフェイス (UserService) を定義し、インターフェイス UserServiceImpl の実装クラスを定義する必要があります。サービスの実装クラスには UserDao 型の属性があります。サービスクラスにはメソッドaddUser(SysUser user)があります。

操作はサービス クラスの addUser() { userDao.insertUser() } で登録を完了します。

ユーザー データを表すエンティティ クラス SysUser を定義します。

達成するための要件:

プログラム内の UserServiceImpl クラスと MySqlUserDao クラスは Spring コンテナーによって作成および管理されますが、同時に UserServiceImpl クラスの userDao 属性に値を割り当てる必要があります。SpringコンテナからUserServiceImpl型オブジェクトを取得し、addUser()メソッドを呼び出し、「挿入操作の実行にはdaoを使用します」と出力

5) プロジェクト内で複数の Spring 構成ファイルを使用する

複数の設定ファイルを分割する方法: 1) 機能モジュールに応じて、モジュールごとに 1 つの設定ファイル。2) クラスの機能に応じて、データベース操作に関連するクラスは 1 つのファイルにあり、サービス クラスは設定ファイルにあり、redis やトランザクションなどを設定するための設定ファイルがあります。

Spring は複数の設定ファイルを管理します。一般的に使用されるのは、関係を含む設定ファイルです。プロジェクトには一般ファイルがあり、インポート タグを持つ他の複数の構成ファイルが含まれています。

文法:

总的文件(xml)
<import resource="其他的文件的路径1"/>
<import resource="其他的文件的路径2"/>

关键字"classpath:":表示类路径, 也就是类文件(class文件)所在的目录。 spring到类路径中加载文件
                   什么时候使用classpath: 在一个文件中要使用其他的文件, 需要使用classpath
2.4.2 アノテーションベースのDI

注釈ベースの DI: Spring によって提供される注釈を使用して、Java オブジェクトの作成と属性の割り当てを完了します。

注釈を使用するための主要な手順は次のとおりです。

1. @Component などの注釈をソース コードに追加します。

2. Spring 構成ファイルに、コンポーネント スキャナー タグを追加します。

<context:component-scan base-package="注解所在的包名;"/>

1. オブジェクトの注釈を作成する

@Component 通常の Java オブジェクト

@Respository dao オブジェクト、永続化レイヤー オブジェクトは、オブジェクトがデータベースにアクセスできることを示します。

@Service サービス オブジェクト、ビジネス レイヤー オブジェクト、ビジネス ロジックを処理し、トランザクション機能を備えています。

@Controller リクエストを受信し、リクエストの処理結果を表示するコントローラオブジェクトです。ビューレイヤーオブジェクト

2. 単純型属性の割り当て

@価値

3. 参照型の割り当て

@Autowired: Spring によって提供されるアノテーション。byName、byType をサポート

@Autowired: デフォルトは byType です

@Autowired @Qualifier: byName を使用します

@Resource: jdk からのアノテーション。参照タイプに割り当てられます。デフォルトは byName です。

@Resource: 最初に byName を使用し、次に byType を使用します

@Resource(name="bean's name"): byName インジェクションのみを使用する

2.5 IoCの概要

IoC: オブジェクトの管理、コンテナへのオブジェクトの配置、作成、値の割り当て、および依存関係の管理を行います。

IoC: 分離は管理オブジェクトを通じて実現されます。IoC は、ビジネス ロジック オブジェクト間の結合関係、つまりサービスと Dao 間の分離を解決します。

Spring がコンテナとして管理するのに適したオブジェクトは何ですか?
1) サービスオブジェクト、dao オブジェクト。
2) ツールオブジェクト。

春に渡すのに適さない物体ですか?
1) エンティティクラス。
2) サーブレット、リスナー、フィルター、および Web 内のその他のオブジェクト。これらは Tomcat によって作成および管理されます。

第 3 章 AOP アスペクト指向プログラミング

3.1 機能追加による問題点

ソースコードでは、ビジネスメソッドに機能が追加されています。

1) ソースコードは大幅に変更される可能性があります。

2) 重複したコードが多数あります。

3) コードの保守が難しい。

3.2 AOPの概念

3.1 AOPとは

AOP (Aspect Orient Programming): アスペクト指向プログラミング

アスペクト:アスペクトを表し、ビジネスメソッドに付加された機能をアスペクトと呼びます。アスペクトは通常、非ビジネス機能であり、アスペクト機能は通常、再利用可能です。例えば、ログ機能、トランザクション機能、権限チェック、パラメータチェック、統計情報など。

方向: 対面、対面

プログラミング:プログラミング。

アスペクト指向プログラミングを理解するにはどうすればよいですか? アスペクトをコアとしてアプリケーションを設計および開発します。

1) プロジェクトを設計するときは、各側面の機能を調べます。

2) アスペクトの実行時間と実行場所を調整します。

3.2 AOP機能

1) アスペクト関数の再利用

2) 開発者がビジネス ロジックに集中できるようにします。開発効率の向上

3) ビジネス機能とその他の非ビジネス機能の分離を実現します。

4) 元のコードを変更せずに、既存のビジネス メソッドに機能を追加します。

3.3 AOP の用語

1)アスペクト:アスペクト、ビジネスメソッドに追加される機能。

2) JoinPoint: 接続ポイント、アスペクトを接続するためのビジネス メソッド。このビジネスメソッドが実行されると、アスペクト機能も同時に実行されます。

3) ポイントカット: エントリ ポイントは 1 つ以上の接続ポイントの集合です。これは、これらのメソッドを実行すると、アスペクトの機能を向上させることができることを意味します。

アスペクトが実行される場所を示します。

4) target: ターゲット オブジェクト。そのオブジェクトにアスペクト関数を追加します。このオブジェクトがターゲット オブジェクトです。

5) アドバイス: アスペクトの実行時間を示す通知 (拡張)。アスペクトはターゲット メソッドの前に実行する必要がありますか、それともターゲット メソッドの後に実行する必要がありますか?

AOP には、アスペクト、ポイントカット、アドバイスの 3 つの重要な要素があり、この概念を理解すると、アドバイスの時点で、ポイントカットの位置でアスペクトが実行されます。

AOP は動的なアイデアです。プログラム実行時にプロキシ(ServcieProxy)が作成され、プロキシ実行方式を使用する場合にはアスペクト機能が追加されます。このプロキシ オブジェクトはメモリに保存されます。

3.4 AOPを使用したい場合

特定のメソッドに同じ機能を追加する必要があります。ソースコードは変更できません。ビジネス以外の機能をビジネス メソッドに追加するには、AOP を使用することもできます。

3.5 AOP 技術アイデアの実装

フレームワークを使用して AOP を実装します。AOP を実装するためのフレームワークは数多くあります。2 つの有名なもの:
1) Spring: Spring フレームワークは、AOP アイデアのいくつかの機能を実装します。AOP を実装する Spring フレームワークの操作は比較的面倒で面倒です。
2) Aspectj: AOP に特化した独立したフレームワーク。エクリプス所属

3.6 AspectJ フレームワークを使用した AOP の実装

AspectJ フレームワークは、アノテーションと XML 構成ファイルという 2 つの方法で AOP を実装できます。

3.6.1 通知

Aspectjは、アスペクトの実行時間をアドバイス(Advice)で表します。この通知はアノテーションを使用して表現できます。

アスペクトの 5 つの実行時間を表す 5 つのアノテーションについて説明します。これらのアノテーションは通知アノテーションと呼ばれます。

@Before: 事前通知

@AfterRetunring: 通知を投稿する

@Around: サラウンド通知

@AfterThrowing:例外通知

@After:最終通知

3.6.2. ポイントカットの位置

Pointcut は、Aspectj のポイントカット式を使用して、アスペクトの実行位置を表すために使用されます。

ポイントカット式構文:実行(アクセス許可メソッド戻り値メソッド宣言(パラメータ)例外タイプ)

3.6.3 @事前通知の前

事前通知@Before

 /*
       前置通知方法的定义
       1)方法是public
       2)方法是void
       3)方法名称自定义
       4)方法可以有参数,如果有是JoinPoint
          也可以没有
*/
/**
 * 切面类中的通知方法,可以有参数
 * JoinPoint必须是它。
 *
 * JoinPoint: 表示正在执行的业务方法。 相当于反射中 Method
 *   使用要求:必须是参数列表的第一个
 *   作用:获取方法执行时的信息,例如方法名称, 方法的参数集合
 */
@Before(value = "execution(* *..SomeServiceImpl.do*(..) )")
public void myBefore2(JoinPoint jp){
    
    
    //获取方法的定义
    System.out.println("前置通知中,获取目标方法的定义:"+jp.getSignature());
    System.out.println("前置通知中,获取方法名称="+jp.getSignature().getName());
    //获取方法执行时参数
    Object args []= jp.getArgs();// 数组中存放的是 方法的所有参数
    for(Object obj:args){
    
    
        System.out.println("前置通知,获取方法的参数:"+obj);
    }

    String methodName = jp.getSignature().getName();
    if("doSome".equals(methodName)){
    
    
        //切面的代码。
        System.out.println("doSome输出日志=====在目标方法之前先执行==:"+ new Date());
    } else if("doOther".equals(methodName)){
    
    
        System.out.println("doOther前置通知,作为方法名称,参数的记录。");
    }
}
3.6.4 @AfterReturning 投稿通知

@AfterReturning: ターゲットメソッドの後に実行されます。

 /*
       后置通知方法的定义
       1)方法是public
       2)方法是void
       3)方法名称自定义
       4)方法有参数,推荐使用Object类型。
*/
 /* 特点:
     *  1.在目标方法之后,执行的。
     *  2.能获取到目标方法的执行结果。
     *  3.不会影响目标方法的执行
     *
     * 方法的参数:
     *   Object res: 表示目标方法的返回值,使用res接收doOther的调用结果。
     *   Object res= doOther();
     *
     *  后置通知的执行顺序
     *  Object res = SomeServiceImpl.doOther(..); Student
     *
     *  myAfterReturning(res);
     *
     *  思考:
     *    1 doOther方法返回是String ,Integer ,Long等基本类型,
     *      在后置通知中,修改返回值, 是不会影响目标方法的最后调用结果的。
     *    2 doOther返回的结果是对象类型,例如Student。
     *      在后置通知方法中,修改这个Student对象的属性值,会不会影响最后调用结果?
     */
    @AfterReturning(value = "execution(* *..SomeServiceImpl.doOther(..))",
                    returning = "res")
    public void myAfterReturning(JoinPoint jp, Object res){
    
    
        //修改目标方法的返回值
        if(res != null){
    
    
            res = "HELLO Aspectj";
        }
        System.out.println("后置通知,在目标方法之后,执行的。能拿到执行结果:"+res);
        //Object res有什么用
        if("abcd".equals(res)){
    
    
            System.out.println("根据返回值的不同,做不同的增强功能");
        } else if("add".equals(res)){
    
    
           System.out.println("doOther做了添加数据库, 我做了备份数据");
        }
    }
3.6.5 @Around サラウンド通知

@Around(value="ポイントカット式")

サラウンド通知を使用する: アスペクト クラスの通知メソッドを呼び出すだけです。
[外部リンク画像の転送に失敗しました。ソース サイトにはリーチ防止メカニズムが備わっている可能性があります。画像を保存して直接アップロードすることをお勧めします (img-5H5hbYFm-1675337795390) (images/image-20201024113735575.png)]

/*
       环绕置通知方法的定义
       1)方法是public
       2)方法是必须有返回值, 推荐使用Object类型
       3)方法名称自定义
       4)方法必须有ProceedingJoinPoint参数,
*/
/**
 * @Around:环绕通知
 *    属性:value 切入点表达式
 *    位置:在方法定义的上面
 *
 * 返回值:Object ,表示调用目标方法希望得到执行结果(不一定是目标方法自己的返回值)
 * 参数:  ProceedingJoinPoint, 相当于反射中 Method。
 *        作用:执行目标方法的,等于Method.invoke()
 *
 *        public interface ProceedingJoinPoint extends JoinPoint {}
 *
 * 特点:
 *  1.在目标方法的前和后都能增强功能
 *  2.控制目标方法是否执行
 *  3.修改目标方法的执行结果。
 */
@Around("execution(* *..SomeServiceImpl.doFirst(..))")
public Object myAround(ProceedingJoinPoint pjp) throws Throwable {
    
    
    //获取方法执行时的参数值
    String name = "";
    Object args [] = pjp.getArgs();
    if( args != null && args.length > 0){
    
    
        Object arg = args[0];
        if(arg !=null){
    
    
            name=(String)arg;
        }
    }

    Object methodReturn = null;

    System.out.println("执行了环绕通知,在目标方法之前,输出日志时间=="+ new Date());
    //执行目标方法  ProceedingJoinPoint,表示doFirst

    if("lisi".equals(name)){
    
    
        methodReturn = pjp.proceed();//method.invoke(),表示执行doFirst()方法本身
    }
    
    if( methodReturn != null){
    
    
        methodReturn ="环绕通知中,修改目标方法原来的执行结果";
    }

    System.out.println("环绕通知,在目标方法之后,增加了事务提交功能");

    //return "HelloAround,不是目标方法的执行结果";
    //返回目标方法执行结果。没有修改的。
    return methodReturn;
}
3.6.6 @AfterThrowing 例外通知

構文 @AfterThrowing(value="ポイントカット式", throwing="カスタム変数")

/*
       异常通知方法的定义
       1)方法是public
       2)方法是没有返回值。是void
       3)方法名称自定义
       4)方法有参数是Exception
*/
/**
 * @AfterThrowing:异常通知
 *     属性: value 切入点表达式
 *           throwing 自定义变量,表示目标方法抛出的异常。
 *                    变量名必须和通知方法的形参名一样
 *     位置:在方法的上面
 * 特点:
 *  1. 在目标方法抛出异常后执行的, 没有异常不执行
 *  2. 能获取到目标方法的异常信息。
 *  3. 不是异常处理程序。可以得到发生异常的通知, 可以发送邮件,短信通知开发人员。
 *      看做是目标方法的监控程序。
 *
 *  异常通知的执行
 *  try{
 *      SomeServiceImpl.doSecond(..)
 *  }catch(Exceptoin e){
 *      myAfterThrowing(e);
 *  }
 */
@AfterThrowing(value = "execution(* *..SomeServiceImpl.doSecond(..))",throwing = "ex")
public void myAfterThrowing(Exception ex){
    
    
    System.out.println("异常通知,在目标方法抛出异常时执行的,异常原因是:"+ex.getMessage());
    /*
       异常发生可以做:
       1.记录异常的时间,位置,等信息。
       2.发送邮件,短信,通知开发人员
     */
}
3.6.7 @最終通知後

構文: @After(value="ポイントカット式")

/*
       最终通知方法的定义
       1)方法是public
       2)方法是没有返回值。是void
       3)方法名称自定义
       4)方法没有参数
*/
/**
 * @After:最终通知
 *    属性: value 切入点表达式
 *    位置: 在方法的上面
 * 特点:
 *  1. 在目标方法之后执行的。
 *  2. 总是会被执行。
 *  3. 可以用来做程序最后的收尾工作。例如清除临时数据,变量。 清理内存
 *
 *  最终通知
 *  try{
 *      SomeServiceImpl.doThird(..)
 *  }finally{
 *      myAfter()
 *  }
 */
@After(value = "execution(* *..SomeServiceImpl.doThird(..))")
public void myAfter(){
    
    
    System.out.println("最终通知,总是会被执行的");
}
3.6.8 @Pointcut はポイントカット注釈を定義および管理します

@Pointcut(value="ポイントカット式")

@After(value = "mypt()")
public void myAfter(){
    
    
    System.out.println("最终通知,总是会被执行的");
}

/**
 * @Pointcut: 定义和管理切入点,不是通知注解。
 *     属性: value 切入点表达式
 *     位置: 在一个自定义方法的上面, 这个方法看做是切入点表达式的别名。
 *           其他的通知注解中,可以使用方法名称,就表示使用这个切入点表达式了
 */
@Pointcut("execution(* *..SomeServiceImpl.doThird(..))")
private void mypt(){
    
    
    //无需代码
}

3.7 AOPの概要

AOP は、ビジネス機能と非ビジネス機能の分離を実現することを目的とした動的な技術的アイデアです。ビジネス機能は独立したモジュールであり、他の機能も独立したモジュールです。トランザクション機能、ログなど。これらのトランザクションとログ機能を再利用しましょう。

対象メソッドに何らかの機能が必要な場合、AOP技術を利用することで、ソースコードを変更することなくプログラム実行時にプロキシオブジェクトを生成し、機能を追加しながらプロキシ経由でビジネスメソッドを実行できます。

第 4 章 Spring は MyBatis を統合します

4.1 統合のアイデア

Spring は多くのフレームワークを統合できることが Spring の利点です。機能を統合すると、開発者は他のフレームワークを簡単に使用できるようになります。

この統合には Spring IOC コア テクノロジーが使用されます。

4.2 mybatis などのフレームワークを使用するには、mybatis を使用する方法を教えてください。

mybatis を使用するには、mybatis フレームワーク内に特定のオブジェクトを作成する必要があり、これらのオブジェクトを使用して、mybatis が提供する機能を使用できます。

分析: Mybatis は SQL ステートメントを実行します。どのオブジェクトを使用する必要がありますか

  1. Dao インターフェースのプロキシ オブジェクトが必要です。たとえば、StudentDao インターフェースにはそのプロキシ オブジェクトが必要です。

    SqlSession.getMapper(StudentDao.class) を使用して dao プロキシ オブジェクトを取得します

  2. openSession() を使用して SqlSession オブジェクトを取得する前に、SqlSessionFactory を用意し、SqlSessionFactory オブジェクトを作成する必要があります。

  3. データ ソース DataSource オブジェクト。mybatis 独自の PooledDataSource の代わりに、より強力で機能的な接続プール オブジェクトを使用します。
    [外部リンク画像の転送に失敗しました。ソース サイトにはリーチ防止メカニズムが備わっている可能性があります。画像を保存して直接アップロードすることをお勧めします (img-tAepHfPO-1675337795391) (images/image-20201024145315985.png)]

第5章 春のトランザクション

5.1 トランザクションの概念

どのようなビジネス?トランザクションとは、複数の SQL をいくつか集めたもので、全体として実行されます。

mysql执行事务
beginTransaction 开启事务
insert into student() values.....
select * from student where id=1001
update school set name=xxx where id=1005
endTransaction   事务结束

トランザクションを使用する必要があるのはどのような場合ですか?

操作を成功させるには、複数 (2 つ以上の SQL) SQL ステートメントを同時に完了する必要があります。

5.2 プログラム内のトランザクションの位置の説明

トランザクション: ビジネス クラスのメソッド (パブリック メソッドの上) に追加され、ビジネス メソッドの実行時にトランザクションのサポートが必要であることを示します。

public class AccountService{
    
    
   private AccountDao dao; 
   private MoneyDao dao2;
   // 在service(业务类)的public方法上面,需要说明事务。
   public void trans(String a, String b, Integer money){
    
    
       dao.updateA();
       dao.updateB();
       dao2.insertA();
   }
}

public class AccountDao{
    
    
    public void updateA(){
    
    }
    public void updateB(){
    
    }
}

public class MoneyDao{
    
     
    public void insertA(){
    
    }
    public void deleteB(){
    
    }  
}

5.3 トランザクションマネージャー

5.3.1 データベース アクセス技術が異なれば、トランザクションの処理方法も異なります
  1. jdbc を使用してデータベースにアクセスし、トランザクション処理を行います。
public void updateAccount(){
    
    
    Connection conn = ...
    conn.setAutoCommit(false);
    stat.insert()
    stat.update();
    conn.commit();
    con.setAutoCommit(true)
}
  1. mybatis はデータベースを実行し、トランザクションを処理します。
public void updateAccount(){
    
    
    SqlSession session = SqlSession.openSession(false);
    try{
    
    
        session.insert("insert into student...");
    	session.update("update school ...");
    	session.commit(); 
    }catch(Exception e){
    
    
        session.rollback();
    } 
}
5.3.2 springではトランザクションを一元管理し、異なるデータベースアクセス技術のトランザクション処理を統一します。

Spring のトランザクション マネージャーを使用して、さまざまなデータベース アクセス テクノロジのトランザクション処理を管理します。開発者は Spring のトランザクション処理ソリューションの 1 つを習得するだけで、さまざまなデータベース アクセス テクノロジを使用したトランザクション管理を実装できます。

管理トランザクションは Spring を指向しており、Spring はトランザクションの管理、トランザクションのコミット、トランザクションのロールバックを行います。

5.3.3 Springトランザクションマネージャー

Spring フレームワークは、トランザクション マネージャー オブジェクトを使用してすべてのトランザクションを管理します。

トランザクション マネージャー インターフェイス: PlatformTransactionManager

機能: 主に commit()、rollback() などのトランザクション操作を定義します。

トランザクション マネージャーには多数の実装クラスがあります。データベース アクセス テクノロジには 1 つの実装クラスがあります。実装クラスは、具体的にはトランザクションの送信とレビューを完了します。

意味: jdbc または mybatis には、データベースにアクセスするときに独自のトランザクション マネージャー実装クラスがあります: DataSourceTranactionManager

Hibernate フレームワーク、そのトランザクション マネージャー実装クラス: HibernateTransactionManager。

トランザクションマネージャーの仕組み:
[外部リンク画像の転送に失敗しました。ソース サイトにはリーチ防止メカニズムが備わっている可能性があります。画像を保存して直接アップロードすることをお勧めします (img-0Q0ND5Ig-1675337795392) (images/image-20201026102015375.png)]

5.3.4 トランザクションのコミットとロールバックのタイミング

トランザクションをいつコミットしてロールバックする必要がありますか?

ビジネス メソッドが正常に実行されると、例外は発生せず、トランザクションはコミットされます。ビジネス メソッドが実行時例外をスローした場合、トランザクションはロールバックされます。

例外の分類:

エラー: 重大なエラー。トランザクションをロールバックします。

例外: 例外クラス、発生する可能性のある例外

  1. 実行時例外: RuntimeException とそのサブクラスは実行時例外、つまりプログラムの実行中にスローされる例外です。一般的な実行時例外: NullPoinerException、NumberFormatException、ArithmeticException、IndexOutOfBoundsException。

  2. チェック例外: Java コードを作成するときに必ず発生する例外。たとえば、IOException、SQLException、FileNotFoundException

注意事項:
メソッドで実行時例外がスローされた場合、トランザクションはロールバックされますが、それ以外の場合 (メソッドの通常の実行、チェックされた例外)、トランザクションはコミットされます。

5.3.5 トランザクションで使用される AOP ラップアラウンド通知

サラウンド通知: コードを変更せずに、ターゲット メソッドの前後の機能を拡張できます。

spring给业务方法在执行时,增加上事务的切面功能

@Around("execution(*  所有的业务类中的方法)")
public Object myAround(ProceedingJoinPoint pjp) {
    
    
    try{
    
    
       PlatformTransactionManager.beginTransaction();//使用spring的事务管理器,开启事务
       pjp.proceed(); //执行目标方法 //doSome()
       PlatformTransactionManager.commit();//业务方法正常执行,提交事务
    }catch(Exception e){
    
    
        PlatformTransactionManager.rollback();//业务方法正常执行,回滚事务
    }
}

5.4 トランザクション定義インターフェース TransactionDefinition

トランザクション定義インターフェイス。3種類の定数が定義されており、トランザクション制御に関する属性が定義されています。

トランザクションのプロパティ: 1) 分離レベル 2) 伝播動作 3) トランザクションのタイムアウト

ビジネスメソッドにトランザクション属性を記述します。ACIDとは異なります。

5.4.1 分離レベル

分離レベル: トランザクション間の影響の程度を制御します。

5 つの値、4 つの分離レベルのみ

1) デフォルト: DB のデフォルトのトランザクション分離レベルを使用します。MySql のデフォルトは REPEATABLE_READ、Oracle のデフォルトは READ_COMMITTED です。

2) READ_UNCOMMITTED: コミットされていない読み取り。同時実行の問題は解決されませんでした。
3) READ_COMMITTED: 送信された読み取り。ダーティ リードを解決するには、ノンリピータブル リードとファントム リードがあります。
4) REPEATABLE_READ: 繰り返し可能な読み取り。ダーティ リード、反復不可能なリード、ファントム リードを解決します
。 5) SERIALIZABLE: シリアル化。同時実行性の問題はありません。

5.4.2 タイムアウト期間

タイムアウト (秒単位)。整数値。デフォルトは -1 です

タイムアウト: ビジネス メソッドの最長実行時間を示します。時間に達する前に実行が完了しない場合、Spring はトランザクションをロールバックします。

5.4.3 通信動作

伝播動作には 7 つの値があります。

伝播動作: ビジネス メソッドが呼び出されると、メソッド間でトランザクションが転送されて使用されます。

伝播動作を使用して、メソッドにトランザクションがあるかどうかを識別します。

PROPAGATION_REQUIRED
PROPAGATION_REQUIRES_NEW
PROPAGATION_SUPPORTS

上記3つをマスターする必要があります。

PROPAGATION_MANDATORY
PROPAGATION_NESTED
PROPAGATION_NEVER
PROPAGATION_NOT_SUPPORTED

1) REQUIRED: Spring のデフォルトの伝播動作。メソッドが呼び出されたとき、トランザクションが存在する場合は現在のトランザクションが使用されます。トランザクションが存在しない場合は、新しいトランザクションが作成され、メソッドは新しいトランザクションで実行されます。

2) サポート: サポート。メソッドはトランザクションを使用して通常に実行でき、トランザクションなしで通常に実行することもできます。

3) REQUIRES_NEW: このメソッドには新しいトランザクションが必要です。メソッドの呼び出し時にトランザクションが存在する場合、元のトランザクションは一時停止されます。新しいトランザクションが実行されるまで。メソッドの呼び出し時にトランザクションが存在しない場合は、新しいトランザクションが作成され、コードは新しいトランザクションで実行されます。

5.5 Spring フレームワークは独自のアノテーション @Transactional を使用してトランザクションを制御します

@Transactional アノテーション。アノテーション付きプロパティを使用してトランザクション (分離レベル、伝播動作、タイムアウト) を制御します。

プロパティ:

1. 伝播: Propagation クラスの列挙値を使用するトランザクション伝播動作。たとえば、Propagation.REQUIRED

2.isolation: 分離レベルを示します。分離レベルを示すには、Isolation クラスの列挙値を使用します。DefaultIsolation.DEFAULT

3.readOnly: データベース操作が読み取り専用かどうかを示すブール型の値。デフォルトは false です

4. timeout: トランザクションのタイムアウト、デフォルトは -1、整数値、単位は秒です。たとえば、タイムアウト=20

5.rollbackFor: ロールバックの例外クラスのリストを表し、その値は配列であり、各値は例外タイプのクラスです。

6.rollbackForClassName: ロールバックの例外クラスのリストを表し、その値は例外クラスの名前であり、String型の値です。

7.noRollbackFor: ロールバックを必要としない例外クラスのリスト。クラスタイプです。

8.noRollbackForClassName: ロールバックする必要のない例外クラスのリスト、String型の値

位置づけ:①ビジネスメソッドの上、パブリックメソッドの上

②クラスのトップにいる。

アノテーションを使用する手順:
1) Spring 構成ファイルで、トランザクションのコンテンツを宣言します。

トランザクション マネージャーを宣言し、どのトランザクション マネージャー オブジェクトを使用するかを指定します

トランザクションを管理するためのアノテーションの使用を宣言し、アノテーション駆動型を有効にする

2) クラスのソース コードに @Transactional を追加します。

トランザクション制御モード: 1. コードでトランザクションをプログラム的に制御します。2. 宣言的なトランザクション。コーディングは必要ありません

例:

spring配置文件
<!--声明事务的控制-->
<!--声明事务管理器-->
<bean id="transactionManager"  class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <!--指定数据源DataSource-->
    <property name="dataSource" ref="myDataSource" />
</bean>

<!--开启事务注解驱动: 告诉框架使用注解管理事务
    transaction-manager:指定事务管理器的id
-->
<tx:annotation-driven transaction-manager="transactionManager" />
java代码
//@Transactional 放在public方法的上面。表示方法有事务功能
    /*
    第一种设置方式
    @Transactional(
            propagation = Propagation.REQUIRED,
            isolation = Isolation.DEFAULT,
            readOnly = false, timeout = 20,
            rollbackFor = {NullPointerException.class,NotEnougthException.class})
     */
     
    /*
    第二种设置方式
     @Transactional(
            propagation = Propagation.REQUIRED,
            isolation = Isolation.DEFAULT,
            readOnly = false, timeout = 20
     )
     解释 rollbackFor 的使用;
     1)框架首先检查方法抛出的异常是不是在 rollbackFor 的数组中, 如果在,一定回滚。
     2)如果方法抛出的异步不在 rollbackFor 数组, 框架会继续检查 抛出的异常 是不是 RuntimeException.
        如果是RuntimeException, 一定回滚。


     例如 抛出 SQLException , IOException
     rollbackFor={SQLException.class, IOException.class}
     */


    //第三种方式: 使用默认值 REQUIRED , 发生运行时异常回滚。
    @Transactional
    @Override
    public void buy(Integer goodsId, Integer num) {
    
     }

@Transactional で使用される機能:

1.Spring Framework自体が提供するトランザクション制御

2. 小規模および中規模のプロジェクトに適しています。

3. 使いやすく、効率が高い。

5.6 Aspectj フレームワークを使用して Spring 構成ファイルでトランザクション制御を宣言する

aspectjのaopを使ってトランザクション制御を宣言することを宣言型トランザクションといいます。

使用手順:

  1. pom.xml は Spring アスペクトの依存関係を追加します

  2. Spring設定ファイルでトランザクションの内容を宣言する

    1) トランザクションマネージャーを宣言する

    2) ビジネスメソッドで必要なトランザクション属性を宣言する

    3) ポイントカット式の宣言

宣言的トランザクション

<!--声明式事务: 不用写代码 -->
    <!--1. 声明事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="myDataSource" />
    </bean>


    <!--2.声明业务方法的事务属性(隔离级别,传播行为,超时)
        id:给业务方法配置事务这段代码起个名称,唯一值
        transaction-manager:事务管理器的id
    -->
    <tx:advice id="serviceAdvice" transaction-manager="transactionManager">
        <!--给具体的业务方法增加事务的说明-->
        <tx:attributes>
            <!--
               给具体的业务方法,说明他需要的事务属性
               name: 业务方法名称。 
                     配置name的值: 1. 业务方法的名称; 2. 带有部分通配符(*)的方法名称; 3 使用*
               propagation:指定传播行为的值
               isolation:隔离级别
               read-only:是否只读,默认是false
               timeout:超时时间
               rollback-for:指定回滚的异常类列表,使用的异常全限定名称
            -->
            <tx:method name="buy" propagation="REQUIRED" isolation="DEFAULT"
                       read-only="false" timeout="20"
                       rollback-for="java.lang.NullPointerException,com.bjpowernode.excetion.NotEnougthException"/>


            <!--在业务方法有命名规则后, 可以对一些方法使用事务-->
            <tx:method name="add*"
                propagation="REQUIRES_NEW" rollback-for="java.lang.Exception" />
            <tx:method name="modify*"  
                propagation="REQUIRED" rollback-for="java.lang.Exception" />
            <tx:method name="remove*"  
                propagation="REQUIRED" rollback-for="java.lang.Exception" />

            <!--以上方法以外的 * :querySale, findSale, searchSale -->
            <tx:method name="*" propagation="SUPPORTS" read-only="true" />
        </tx:attributes>
    </tx:advice>

    <!--声明切入点表达式: 表示那些包中的类,类中的方法参与事务-->
    <aop:config>
       <!--声明切入点表达式
            expression:切入点表达式, 表示那些类和类中的方法要参与事务
            id:切入点表达式的名称,唯一值

            expression怎么写?
      -->
      <aop:pointcut id="servicePointcut" expression="execution(* *..service..*.*(..))" />
      <!--关联切入点表达式和事务通知-->
      <aop:advisor advice-ref="serviceAdvice" pointcut-ref="servicePointcut" />
    </aop:config>

宣言的トランザクションの長所と短所:

  1. 短所: 理解するのが難しく、設定が複雑です。

  2. 利点: コードとトランザクション構成が分離されています。制御トランザクションのソースコードを変更する必要はありません。

    プロジェクトのすべての事項を迅速に理解し、管理できる。大規模なプロジェクトに適しています。

第6章 春とウェブ

6.1 現在のコンテナオブジェクトの使用に関する問題

  1. コンテナオブジェクトが何度も作成される
  2. 複数のサーブレットでコンテナ オブジェクトを個別に作成する

6.2 どのような種類のコンテナ オブジェクトが必要ですか?

  1. コンテナ オブジェクトは 1 つだけです。一度作成するだけです。
  2. コンテナ オブジェクトはプロジェクト全体で共有する必要があります。複数のサーブレットが同じコンテナ オブジェクトを使用できる

この問題を解決するには、リスナー ServletContextListener を使用します (2 つのメソッドは最初と破棄時に実行されます)。

リスナーでは、作成されたコンテナ オブジェクトを Web アプリケーションの ServletContext スコープに配置する必要があります。

6.3 ContextLoaderListener

ContextLoaderListener は Spring Framework によって提供されるリスナー オブジェクトです。このリスナー関数を使用します。

1. コンテナオブジェクトを一度作成します

2. コンテナ オブジェクトを ServletContext スコープに配置します。

使用手順:

1.pom.xml は spring-web 依存関係を追加します

2.web.xmlでリスナーを宣言します

頼る

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-web</artifactId>
  <version>5.2.5.RELEASE</version>
</dependency>

リスナー設定

<context-param>
    <!--
      contextConfigLocation:名称是固定的, 表示自定义spring配置文件的路径
    -->
    <param-name>contextConfigLocation</param-name>
    <!--自定义配置文件的路径-->
    <param-value>classpath:spring-beans.xml</param-value>
</context-param>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

6.4 ContextLoaderListener ソースコード

public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
    
    

    //监听器的初始方法
    public void contextInitialized(ServletContextEvent event) {
    
    
        this.initWebApplicationContext(event.getServletContext());
    }

}


private WebApplicationContext context;

public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
    
    


            try {
    
    
                if (this.context == null) {
    
    
                    //创建srping的容器对象
                    this.context = this.createWebApplicationContext(servletContext);
                }
                
                //把容器对象放入的ServletContext作用域
                //key=WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE
                //value=容器对象
                
                servletContext.setAttribute(
                    WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,                             this.context);
               

            } catch (Error | RuntimeException var8) {
    
    
     
            }
        }
    }


//WebApplicationContext是web项目中使用的容器对象
public interface WebApplicationContext extends ApplicationContext  

おすすめ

転載: blog.csdn.net/Peanut31434331/article/details/128856167
おすすめ