IOCとAOPの理解

面接の質問:1。IOCとAOPについてのあなたの理解について話します

参考資料:SpringIOC
とAOPのコアコンセプトを説明してみてください
。SpringJdbcTemplate
はJavaでのJDBCを詳細に説明しています
[Springの基本]実際にアノテーションを使用したAOP

回答:IOCはスプリングのコンテナであり、手動でオブジェクトを作成しなくてもオブジェクトを作成するのに役立ちます。IOCには強力な機能依存性注入(DI)があり、依存性注入を通じてBeanをより適切に管理して、デカップリングの目的を達成できます。例:使用するJDBCTemplateはxmlで構成し、挿入して使用できますが、データソースが必要です。データソースを自由に切り替えることができるため、JDBCTemplateは特定のデータソースに依存してデカップリングを実現しません。 。

回答:AOPは、コードに埋め込まれなくても実行できるため、トランザクションやログでよく使用されます。

2.IOCのプロセスについて説明します。範囲検索に役立つB + Treeのポインターもあります。動物園の飼育係とユーレカの違いは、1つはhttpで、もう1つはRPCです。

3. Aopでターゲットメソッドのパラメータを変更できますか?

1. IOC(設計モード:工場モード)

1.1。コンセプト:オブジェクトの作成に役立つスプリングコンテナです

2、Aopの概念

Aopはコンセプトであり、springAopとaspectJはAopの実現です。フロントエンドがコントローラーにリクエストを送信し、次にdaoに上から下に送信すると、springAopはレベルから切り込みますが、ログ記録などの一部の機能を実現するために、レベルから完全に切り離されます。 、トランザクション、例外、および権限待機。アスペクトのいくつかの機能を実現します。ログ、トランザクション、権限、例外など。

3.AopとaspectJの関係

Aopの文法はより複雑であるため、aspectJの文法スタイルを使用しますが、最下層はそれ自体で実装されます。

第四に、Aopの使用

4.1、Aopを開く

@Configurationアノテーションを使用してaspectJサポートを有効にし、@ EnableAspectJAutoProxyにアノテーションを付けます。
@Configuration
@EnableAspectJAutoProxy
public class AopConfig {
    
    


}

4.2、アスペクト(アスペクト)クラスを宣言する

Aspectアノテーションクラスを宣言し、そのクラスをBean to SpringManagementとして定義します。

4.2.1。アスペクトには、通知とエントリポイントが含まれます

@Component
@Aspect
public class AspectTest {
    
    

}

4.3。アスペクトカテゴリにエントリポイントと通知を書き込む

4.3.1。エントリポイントは、どのターゲットメソッドに実行が通知されるかです。

4.3.2。通知は、ターゲットメソッドを中心とした実行方法です。

4.3.4。コードは次のとおりです:(エントリポイントの式がすべて同じであることがわかりますが、どうすればそれを削除できますか?)

@Component
@Aspect
public class AspectTest {
    
    


    @Before("execution(* com.xuecheng.aop.service..*.*(..))")
    public void before() {
    
    
        System.out.println("before执行。。。。");
    }

    @After("execution(* com.xuecheng.aop.service..*.*(..))")
    public void after() {
    
    
        System.out.println("after执行。。。。");
    }

}

4.3.5。最適化されたコードは次のとおりです。


@Component
@Aspect
public class AspectTest {
    
    
    
    @Pointcut("execution(* com.xuecheng.aop.service..*.*(..))")
    public void pointCut() {
    
    

    }


    @Before("pointCut()")
    public void before(){
    
    
        System.out.println("before执行。。。。");
    }

    @After("pointCut()")
    public void after(){
    
    
        System.out.println("after执行。。。。");
    }



}

4.4、ターゲットメソッドを記述します

4.4.1、インターフェースコード

public interface FatherServ {
    
    

    public void ss();
}

4.4.2。実装クラス(ターゲットクラス)コード

@Component("s")
public class TestService implements FatherServ {
    
    
    public void ss(){
    
    
        System.out.println("目标方法执行...");
    }
}

4.5。テスト結果は次のとおりです。

before执行。。。。
目标方法执行...
after执行。。。。

5、Aopでのエントリーポイント発現分析

参考:SpringAOPポイントカット式の詳細説明

ここに画像の説明を挿入

式を実行するとき、式を論理演算子&&(and)、||(or)、!(not)と一致させることができます。といった:

execution(* com.jpeony.spring.ConferenceServiceImpl.conference(..)
       && within(com.jpeony.spring.*))

追加の制限は、com.jpeony.springの下のパッケージのみを処理することです。ここの&&は、とに置き換えることができます。
同様に|| 、!は同じ使用法で、柔軟性があり、変更可能であり、に従ってのみ処理できます。実際の状況。

5.1、実行(粒度は特定のメソッドに対して正確である可能性があります)

5.2、内(粒度はクラスに対してのみ正確である可能性があります)

5.2.1。BusinessObjectクラスに正確であり、このクラスのすべてのメソッドを拡張します。

within(com.spring.service.BusinessObject)

5.2.2、サービスパッケージの下のすべてのクラスに対して正確ですが、サブパッケージの下のクラスは含まれません

within(com.spring.service.*)

5.2.3、サービスパッケージの下のクラスおよびパッケージの下のサブパッケージのすべてのクラスに正確

within(com.spring.service..*)

5.3、args(粒度はパラメーターの数とパラメーターのタイプを一致させる方法です)

5.3.1、1つの文字列型パラメータのみに正確に一致する方法

args(java.lang.String)

5.3.2。パラメータが最初に文字列型、最後に整数型になるまで完全に一致し、任意の数とタイプのパラメータを中央に置くことができます。ここで、ワイルドカードは「*」ではなく「...」を使用します

args(java.lang.String,..,java.lang.Integer)

5.4、これとターゲットの違い

5.4.1。サラウンド通知に使用する場合、thisとtargetでターゲットオブジェクトを指定すると、ターゲットオブジェクトがインターフェイスを実装していない場合、実行結果は同じになります。ターゲットオブジェクトがインターフェイスを実装している場合、これは実行できません。通知を囲みますが、ターゲットはできます。

5.5、@ within

5.5.1。粒度が、指定された注釈が配置されているクラスと一致する場合、どのクラスが拡張されます。

5.6、@ annotation

5.6.1。@withinと同様に、@ annotationはメソッドに作用します。

5.7、@ args

5.7.1は、アノテーションでマークされたクラスがパラメーターとして使用される場合、実行メソッドが拡張されることを示します

5.8、@ DeclareParents

5.8.1。指定されたターゲットクラスの新しい属性とメソッドの導入を表します。

5.9、perthis和ターゲット

5.9.1。複数のスレッドの場合、Aspectクラスの複数のインスタンスを作成します

6、サラウンド通知

6.1。スライスは次のとおりです。

ステップ1:アノテーション@Aroundを追加する

ステップ2:通知メソッドにパラメーターProceedingJoinPointを渡し、そのメソッドproceed();を呼び出します。


@Component
@Aspect
public class AspectTest {
    
    

    @Around("pointCut()")
    public void aroundTest(ProceedingJoinPoint proceedingJoinPoint) {
    
    
        try {
    
    
            System.out.println("环绕通知之前执行");
            proceedingJoinPoint.proceed();
            System.out.println("环绕通知之后执行");
        } catch (Throwable throwable) {
    
    
            System.out.println("异常通知执行。。");
        }
    }

    @Pointcut("execution(* com.xuecheng.aop.service..*.*(..))")
    public void pointCut() {
    
    

    }
}

7つ目は、ターゲットメソッドのパラメータを取得して変更できることです。

7.1。通知メソッドにパラメーターJoinPointを渡し、メソッドgetArgs();を呼び出して、ターゲットメソッドのパラメーターを取得して変更します。

    @Around("execution(* com.xuecheng.aop.service..*.*(..))")
    public void aroundTest(JoinPoint JoinPoint) {
    
    
        //获取目标方法的参数,并可以对其进行修改
		// Object[] args = joinPoint.getArgs();
    }

8.アドバイスの分類

8.1。Springアスペクトは、5種類の通知を定義します。

1)通知前(前):ターゲットメソッドが呼び出される前に通知関数が呼び出されます。

2)通知後(後):ターゲットメソッドが完了した後に通知を呼び出します。メソッドの出力が何であるかは関係ありません。(対象メソッドが正常に実行されたかどうかに関係なく、事後通知を実行する必要があります。)

3)アフターリターン:ターゲットメソッドが正常に実行された後に通知が呼び出されます。(事後通知の前に実行されるため、メソッドは実行される前に正常に実行される必要があります!)

4)例外通知(スロー後):ターゲットメソッドが例外をスローした後に通知を呼び出します。

5)アラウンド通知(アラウンド):通知は通知されたメソッドをラップし、通知されたメソッドが呼び出される前後にカスタム動作を実行します。(ProceedingJoinPointパラメーターは持つことができますが、JoinPointは存在できません。)

ProceedingJoinPointはJoinPointを継承します。ProceedingJoinPointには、proceed();とproceed(Object object);の2つのメソッドがあります。

9つのAOP用語

連絡先、接続ポイント、アスペクト、通知

接続ポイントは接点の集合であり、接続ポイントはエーテル的で大規模な概念です。アスペクトは、通知とポイントの組み合わせです。通知には「いつ?」と「何をすべきか」と書かれており、連絡先には「どこ?」と書かれています。

10、Aopのアスペクトクラスの実行順序

10.1実行の順序は、アノテーション@order(1)によって解決できます。数値が小さいほど、優先度が高くなります。

11、springAopはターゲットメソッドのパラメータを変更し、ターゲットメソッドの戻り値を変更します(around(サラウンド通知)にのみ適用可能)

変更したパラメータをターゲットメソッドのパラメータに渡して実行することもできます

    @Around("pointCut()")
    public void before(ProceedingJoinPoint joinPoint)  {
    
    
        Object[] args = joinPoint.getArgs();
        for (Object arg : args) {
    
    
            System.out.println("方法的参数是"+arg);
        }

        System.out.println("环绕之前。。。");
        try {
    
    
            String proceed = (String) joinPoint.proceed();
            proceed="改变后的返回值";
            System.out.println(proceed);
        } catch (Throwable throwable) {
    
    
            throwable.printStackTrace();
        }
        System.out.println("环绕之后。。。");


    }
テストコード
public class Demo {
    
    
    public static void main(String[] args) {
    
    
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AopConfig.class);
        TestService s = (TestService) applicationContext.getBean("s");
        s.ss("String参数。。");

    }
}
試験結果
方法的参数是String参数。。
环绕之前。。。
目标方法执行...String参数。。
改变后的返回值
环绕之后。。。

おすすめ

転載: blog.csdn.net/weixin_43983411/article/details/108125905