Spring コア機能 - IOC および AOP

概要

Spring は、2003 年に登場した、軽量で非侵入型の IOC および AOP のワンストップ Java 開発フレームワークです。エンタープライズ レベルの開発を簡素化するために生まれました。

軽量:Spring の jar パッケージは約 1M で、実行時のフレームワークのリソース占有は少なく、動作効率が高い

非侵入的: ビジネス コードは、ビジネス コードを実装するために Spring でインターフェイスまたはクラスを継承または実装する必要はありませんが、構成ファイルを使用して開発プロセスを簡素化できます。

IOC: 制御の反転、Spring は Java でオブジェクトを管理するのに役立ちます

AOP: オブジェクト指向プログラミング。ビジネス開発プロセスにおけるコードの冗長性を減らし、開発効率を向上させます。

ワンストップ フレームワーク: Spring 自体も Web 機能とデータ アクセス機能を提供し、他のフレームワークも管理できます。

春のアーキテクチャ図

IOC

        制御の反転、IOC と呼ばれる制御の反転、IOC は、プログラム内でオブジェクトを作成する力をフレームワークに移す設計思想です。

        IOCコンテナは、依存性注入機能を備えたコンテナで、オブジェクトの作成、オブジェクトの初期化、オブジェクトの組み立て、外部アクセスメソッドの作成からオブジェクトの破棄までを管理することができます。IOC コンテナは Map コレクションに似ています。オブジェクトが作成されると、このコレクションに追加されます。キー値にはオブジェクトの名前またはクラス名が格納され、値にはオブジェクトのアドレスが格納されます。オブジェクトを使用する必要がある場合、オブジェクトを手動で作成する必要はなく、コンテナーから直接取得できます。

豆のコンセプト

Spring によって管理されるオブジェクトは、まとめて Bean オブジェクトと呼ばれます。

XML 構成による Bean オブジェクトの管理

Spring 構成ファイルの bean タグを使用してオブジェクトを構成します。

    <bean id="admin" class="com.yzl.spring.model.Admin" scope=""></bean>

bean タグの属性:

id : オブジェクト名

name : オブジェクトのエイリアスで、複数で構成できます

class : リフレクション メカニズムを介してオブジェクトを作成する完全なクラス名

scope : シングルトンとプロトタイプの 2 つの値で構成されるオブジェクトのモード

        singleton (デフォルト値): Spring にはシングルトン モードの Bean インスタンスが 1 つだけあります。

        プロトタイプ: オブジェクトが使用されるたびにオブジェクトが作成されます

request : 各 http リクエストは Bean を作成し、WebApplicationContext 環境でのみ使用されます

session : 同じ http セッションは Bean を共有し、異なるセッションは異なる Bean を使用し、使用環境は上記と同じです

xml での依存性注入 (DI) の方法:

Spring でオブジェクトを作成するプロセス中に、オブジェクトの依存関係プロパティ (単純な値、コレクション、オブジェクト) が構成を通じてオブジェクトに設定されます。

たとえば、adminService オブジェクトを構成する場合、adminDao オブジェクトの依存関係をオブジェクトに注入します。

    <bean id="adminService" class="com.yzl.spring.service.AdminService">
        <property name="adminDao" ref="adminDao"></property><!--依赖注入-->
    </bean>

アノテーションによる Bean オブジェクトの管理

準備

最初に、アノテーションに必要な jar をインポートする必要があります。これは通常、Spring の jar 依存関係をインポートするときに自動的にインポートされます。

次に、Spring 構成ファイルで注釈を構成する必要があります

<context:component-scan base-package="com.yzl.spring"></context:component-scan>

この構成には、構成の制約を追加する必要があるという前提条件もあります。

xmlns:context="http://www.springframework.org/schema/context" 
xsi:schemaLocation= 
       "http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context /spring-context.xsd"

スプリング構成におけるいくつかの一般的な制約

<?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:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://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/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    
</beans>

Bean の管理に関する注意事項

@Component(value="user")、このアノテーションは通常、エンティティ クラスがこのクラスのオブジェクトをコンテナーに挿入するために使用されます。これは、xml 構成と同等です。

< bean id="user" class=""></bean>

@Service(value="user")、サービス層のクラス オブジェクトをコンテナーに挿入するために使用されます。

@Repository(value="user") は、Dao レイヤーのクラス オブジェクトをコンテナーに挿入するために使用されます。

@Scope(value="prototype")、クラス オブジェクトのモードを示すために使用されます。これは、Bean タグのスコープ属性と同等です。

最初の 3 つの注釈は同じ機能を持ちますが、異なるレイヤーのオブジェクトに適用されます

注釈タグの自動注入

@Autowired

        このタグは、Spring フレームワークが提供するアノテーションであり、フィールドおよびセッター メソッドに記述できます。フィールドに記述されている場合は、setter メソッドを記述する必要はありません。デフォルトでは、依存オブジェクトが存在する必要があります (つまり、コンテナに注入されています). null 値が許可されている場合は、required 属性を false に設定できます。

この注釈には、オブジェクトを照合する 2 つの方法があります。

1.タイプ別

このアノテーションは、デフォルトで自動注入にこのメソッドを使用します。注入時に、オブジェクトはオブジェクトのタイプによって照会されます

2.名前で

このメソッドは、オブジェクトによって定義された id 属性値を検索することです. @Qualifier(value = "") タグと一緒に使用する必要があり、値の値はオブジェクトの id 属性です.

@リソース

このタグは、@Autowired の使用法と同様に、jdk によって提供されます。

この注釈には、オブジェクトを照合する 2 つの方法もあります。

1.タイプ別

デフォルトでこのメソッドを使用します

2.名前で

@Resource(名前="")

XML 構成とアノテーションの長所と短所

注釈:

        利点: 便利、直感的、高効率、構成不要

        短所: 変更には、デプロイ前にコードの再コンパイルが必要です

XML 構成:

        利点: XML 構成の変更は再コンパイルを必要としません。

        短所: 開発ワークロードが大きく、構成の開発要件が多い

AOP

        Aspect Oriented Programming (Aspect Oriented Programming) は AOP と呼ばれます. AOP の核となる考え方は、ビジネス ロジック コードを非ビジネス ロジック コードから分離し、ビジネス コードと非ビジネス コードの間の結合を減らすことです。AOP は、元のビジネス コードを変更することなく、非ビジネス コードを抽出し、非ビジネス コード機能を追加できます。これにより、コードの再利用率と開発効率が向上します

注: 非ビジネス コードには、たとえば、ログの印刷、トランザクションの送信、例外処理などが含まれます。

役割: コードの重複を減らし、ビジネス開発に集中し、効率を改善する

AOP と OOP の違い:

OOP は、より明確な論理単位を取得するために、ビジネス内のエンティティの属性と動作を抽象的にカプセル化したものです。

AOPとは、業務処理の過程で業務コードと非業務コードを分離することであり、例えば、業務コードと非業務コードは異なる側面のコードとみなすことができ、それぞれの側面のコードを分離することで、相互の結合を減らすことができます。コード。

Spring での AOP の基本的な実装は、動的プロキシによって実現されます。これは、ビジネス コードが非ビジネス コードを呼び出す必要がある場合、フレームワークによって生成されたプロキシ オブジェクトが非ビジネス コードを呼び出すために提供されると簡単に理解できます。

AOP の基本概念

接続点: クラス内で拡張できるメソッドを接続点と呼び、拡張とは新しい機能を追加できることを意味します

エントリポイント: クラスで実際に拡張されるメソッドは、エントリポイントと呼ばれます

通知:エントリポイントで強化された特定の機能は通知と呼ばれ、通知に応じて時点を呼び出すことにより、事前通知、事後通知、例外通知、最終通知、周辺通知に分けることができます

アスペクト: ポイントカットによって呼び出されるプロセス全体をアドバイスします

ターゲット: エージェントのターゲット オブジェクト (接続ポイント、エントリ ポイントが配置されているクラス)

プロキシ: 通知が対象オブジェクトに適用されるときに作成されるプロキシ オブジェクト

アスペクトJ

AOPはSpring独自のプログラミング思想ではない. 実際, 多くのフレームワークがAOPプログラミング思想を実装している. AspectJはJava言語に基づくAOPプログラミングフレームワーク. 実装方法が便利でアノテーションベースの開発をサポート. Springはフレームワークを導入の実現

Spring で AOP 関数の構築を実現します。

まず、AspectJ の jar 依存関係を増やします

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

1. xml 構成に基づく実装

<!--首先将通知所在的类对象注入Ioc容器中-->
<bean id="aopdemo" class="com.ff.spring.aop.AopDemo"></bean>
<aop:config>
    <!-- 配置切入点 -->
    <aop:pointcut expression="execution(*
    com.ff.spring.service.UserService.adduser(..))" id="adduser"/>
    <aop:pointcut expression="execution(*
    com.ff.spring.service.UserService.*(..))" id="allmethod"/>
    <!-- 配置通知和切入点 -->
    <aop:aspect ref="aopdemo">
        <aop:before method="savelog" pointcut-ref="adduser"/>
        <aop:after method="savelog" pointcut-ref="adduser"/>
        <aop:round method="aroundAdvice" pointcut-ref="adduser"/>
        <aop:after-throwing method="exceptionAdvice" pointcut-ref="allmethod" throwing="e" />
    </aop:aspect>
</aop:config>

<aop:pointcut>タグのexpression属性の値が業務コードメソッドの式

定形:実行(戻り値クラス名フルネーム.メソッド名(..))

戻り値 * 任意の型の戻り値に置き換わります

クラス名は * を使用して、com.example.test.* などのすべてのクラスを表します。

メソッド名は * を使用してすべてのメソッドを表すことができます

メソッドの後の括弧はパラメータリストを表し、「..」は任意の長さのパラメータ長を表し、空欄の場合はパラメータなしのメソッドを表す

通知タイプ

事前通知: 業務コードの前にコール通知

<aop:before method="savelog" pointcut-ref="adduser"/>

method は通知を意味し、pointcut-ref はエントリ ポイントを意味します。

事後通知: 業務コードの後に​​呼び出し、業務コードに例外がある場合、再度呼び出されることはありません

<aop:after-returning method="savelog" pointcut-ref="adduser"/>

例外通知: この通知は、ビジネス コードで例外が発生したときに呼び出されます。

<aop:after-throwing method="exceptionAdvice" pointcut-ref="allmethod" throwing="e" />

Throwing は通知で渡されたパラメーターを示し、Throwable クラスのパラメーターは、例外通知のパラメーター リストで定義する必要があります。

最終通知: 業務コードに例外があるかどうかに関係なく呼び出されます

<aop:after method="savelog" pointcut-ref="adduser"/>

サラウンド通知: 上記の 4 つの通知呼び出しは、個別に同時に実装できます。

<aop:round method="aroundAdvice" pointcut-ref="adduser"/>

サラウンド通知では、エントリー ポイントを表す ProceedingJoinPoint クラスのパラメーターを渡す必要があります。

サラウンド通知の実装:

ProceedingJoinPointクラスのproceed()メソッドは実行エントリポイントを表します.このメソッドによって呼び出される相対位置に対応するコードは,さまざまな種類の通知に対応します.たとえば,前に書いたコードは事前通知を表し,中のコードはcatch コード ブロックは例外通知です。

public void aroundAdvice(ProceedingJoinPoint point){
​
        try {
            System.out.println("前置通知");
            point.proceed();
            System.out.println("后置通知");
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            System.out.println("异常通知"+throwable.getMessage());
        }
        System.out.println("最终通知");
​
 }

2. アノテーションに基づく実装

①まず、構成ファイルに aop アノテーション サポート <aop:aspectj-autoproxy /> を追加する必要があります。

② AOP コードクラスのフィールドに @Component アノテーションと @Aspect アノテーションを使用する 前者はこのクラスのオブジェクトを Ioc コンテナに注入するためのもので、後者はクラスがアスペクトクラスであることを表すためのものです

@Component 
@Aspect//このクラスがアスペクト クラスであることを示します
public class MyUtil {}

③通知フィールドに対応する通知注釈を使用する

事前通知: @Before("execution(* com.yzl.spring.dao.AdminDao.save(..))")

投稿通知 @AfterReturning("execution(* com.yzl.spring.dao.AdminDao.save(..))")

例外通知: @AfterThrowing(value = "execution(* com.yzl.spring.dao.AdminDao.save(..))", throwing = "e")

最終通知: @After("execution(* com.yzl.spring.dao.AdminDao.save(..))")

アラウンドアドバイス: @Around("execution(* com.yzl.spring.dao.AdminDao.save(..))")

通知コンテンツのパラメーターは、ビジネス コードの対応するメソッドの式を記述します。例外通知など、複数のパラメーターを必要とする通知は、value 属性値を使用して、throwing 属性値でパラメーターを区別する式を記述する必要があります。

    //前置通知
    @Before("execution(* com.yzl.spring.dao.AdminDao.save(..))")
    public void printLog(){
        System.out.println("打印日志");
    }
​
    //后置通知
    @AfterReturning("execution(* com.yzl.spring.dao.AdminDao.save(..))")
    public void commit(){
        System.out.println("事物提交");
    }
​
    //异常通知
    @AfterThrowing(value = "execution(* com.yzl.spring.dao.AdminDao.save(..))",throwing = "e")
    public void exceptionService(Throwable e){
        System.out.println("异常通知"+e.getMessage());
    }
​
    //最终通知
    @After("execution(* com.yzl.spring.dao.AdminDao.save(..))")
    public void finalAdvic(){
        System.out.println("最终通知");
    }
​
    //环绕通知
    @Around("execution(* com.yzl.spring.dao.AdminDao.save(..))")
    public void aroundAdvice(ProceedingJoinPoint point){
​
        try {
            System.out.println("前置通知");
            point.proceed();
            System.out.println("后置通知");
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            System.out.println("异常通知"+throwable.getMessage());
        }
        System.out.println("最终通知");
​
    }

おすすめ

転載: blog.csdn.net/yzl1293346757/article/details/128223268