AOPとは何ですか
AOP(アスペクト指向のプログラミング、アスペクト指向プログラミング)は、OOP(オブジェクト指向プログラミング)の補足と改善であると言えます。 OOPは、カプセル化、相続、多型などの概念を導入して、オブジェクトの階層を確立して、公的行動のコレクションをシミュレートします。散らばったオブジェクトに公共の行動を導入する必要があるとき、OOPは無力に見えます。つまり、OOPを使用すると、上から下への関係を定義できますが、左から右への関係を定義するのに適していません。たとえば、ロギング機能。ログコードは、多くの場合、散乱するオブジェクトのコア機能に関連することなく、すべてのオブジェクトレベルに水平に散在しています。同じことは、セキュリティ、例外処理、透明性など、他のタイプのコードにも当てはまります。どこにでも散在するこの種の無関係なコードは、クロスカットコードと呼ばれます。 OOP設計では、各モジュールの再利用を助長しない多くのコード複製を引き起こします。
導入
私がしばらく前に書いたJavaデザインパターン - プロキシパターン。最近、Spring AOPを見ていたとき、プロキシパターンに密接な接続があるべきだと感じたので、Spring AOPの実装原則を理解することにしました。
AOPといえば、OOPについて話さなければなりません。カプセル化、継承、多型の概念は、OOPで紹介され、公共行動のコレクションをシミュレートするオブジェクト階層を確立します。ただし、一部のオブジェクトに共通部品を導入する必要がある場合、OOPは多くの重複コードを導入します。例:ロギング機能。
AOPテクノロジーは、「CrossCutting」と呼ばれる手法を使用して、カプセル化されたオブジェクトの内部を分析し、複数のクラスに影響を与える共通の動作を再利用可能なモジュールにカプセル化します。 AOPは、ソフトウェアシステムを2つの部分に分割します。コアの懸念とクロスカットの注意。ビジネス処理の主なプロセスは中心的な焦点であり、それとはほとんど関係がない部分は横断的な焦点です。交差懸念の特徴の1つは、それらがしばしば複数のコアの懸念で発生し、基本的にどこでも似ていることです。たとえば、許可認証、ロギング、およびトランザクション処理。
実装の原則
プロキシモードを学んでいたとき、プロキシモードが動的プロキシと静的プロキシに分割されることを知りました。次に、最初にプロキシモデルに基づいて独自のAOPフレームワークを実装し、次にSpringのAOPの実装原則を研究します。
まず、静的プロキシで実装されます。静的プロキシの鍵は、プロキシオブジェクトとターゲットオブジェクトの間に共通のインターフェイスを実装することであり、プロキシオブジェクトはターゲットオブジェクトへの参照を保持します。
パブリックインターフェイスコード:
パブリックインターフェイスihello {/*** business Method*@param str*/void sayhello(string str);}ターゲットクラスコード:パブリッククラスのHello emplmenes ihello {@overridepublic void sayhello(string str){system.out.println( "hello"+str);}}}}プロキシクラスコードの場合、ロギング関数を追加し、メソッドの開始前後に特定のメソッドを実行します。 AOPに特に似ていませんか?
パブリッククラスProxyhelloはihello {private ihello hello; public proxyhello(ihello hello){super(); this.hello = hello;}@overridepublic void sayshello(string str){logger.start(); //特定のメソッドを追加hello.sayhello(str); logger.end();}}}ログクラスコード:
public class logger {public static void start(){system.out.println(new date()+ "say hello start ...");} public static void end(){system.out.println(new date()+ "say hello end");}}}テストコード:
パブリッククラステスト{public static void main(string [] args){ihello hello = new proxyhello(new hello()); //ロギング機能が必要な場合は、プロキシクラスを使用// ihello hello(); }}このようにして、最も単純なAOPを実装しますが、問題があります。こんにちは、Helloのような多くのクラスがある場合、Helloproxyのような多くのクラスを書く必要がありますか?実際、それは非常に厄介なことでもあります。 JDK1.3の後、JDKはAPI java.lang.reflt.invocationhandlerクラスを提供します。このクラスを使用すると、JVMが特定のクラスのメソッドを呼び出す場合、いくつかのメソッドに対して動的に何かを行うことができます。動的プロキシの実装を実装しましょう。
動的プロキシの実装は、主にInvocationHandlerを実装し、ターゲットオブジェクトをプロキシオブジェクトに注入し、反射メカニズムを使用してターゲットオブジェクトメソッドを実行します。
インターフェイスの実装は、静的プロキシ、プロキシクラスコードと同じです。
パブリッククラスのDynaproxyhelloは、InvocationHandler {private object target; // Target Object/*** Reflection* @param object* @return*/public object bind(this.target = object; return proxy.newproxyinstance(this.target.getclass()。 this.target.getClass()。getInterfaces()、this);}@overridepublicオブジェクトInvoke(オブジェクトプロキシ、メソッドメソッド、オブジェクト[] args)スロー可能{オブジェクト結果= null; logger.start(); //追加のメソッドを追加する//ターゲットオブジェクトを実行して反射メカニズムを介してターゲットオブジェクトを実行するためのメソッドを実行します。 結果;}}テストクラスコード:
public class dynatest {public static void main(string [] args){ihello hello =(ihello)new dynaproxyhello()。bind(new hello()); //プロキシクラスを使用する場合、ihello hello = new hello();上記のコードを読んだ後、Spring AOPと比較して問題が発生する可能性があります。ログクラスはメソッドの前後にのみ印刷できますが、AOPは条件を満たしたときに実行できるはずです。すべてのdynapoxyhelloオブジェクトとログ操作オブジェクト(ロガー)を分離できますか?
次のコードの実装を見ると、Dynapoxyhelloオブジェクトとログ操作オブジェクト(ロガー)が分離されます。
プロキシオブジェクトの方法の前または後にログ操作コード(またはその他の操作コード)を追加する必要があります。次に、インターフェイスを抽象化できます。これには、2つのメソッドのみがあります。1つは、プロキシオブジェクトがメソッドを実行する前に実行されるメソッドです。開始と命名され、2番目の方法は、プロキシオブジェクトがメソッドを実行した後に実行されたメソッドであり、終了しました。
ロガーのインターフェイス:
public interface ilogger {void start(method method); void end(method method);} Logger Interfaceの実装:
パブリッククラスのdloggerはilogger {@overridepublic void start(method method){system.out.println(new date() + method.getName() + "say hello start ...")動的プロキシクラス:
パブリッククラスのDynaproxyhelloは、InvocationHandlerを実装しています{//コールオブジェクトプライベートオブジェクトプロキシ; //ターゲットオブジェクトプライベートオブジェクトターゲット;パブリックオブジェクトバインド(オブジェクトターゲット、オブジェクトプロキシ){this.target =ターゲット; this.proxy = proxy; return proxy.newproxyinstance(this.target.getclass() this.target.getClass()。getInterfaces()、this);}@overridePublicオブジェクトInvoke(Object Proxy、Method Method、object [] args)スロースロー{オブジェクト結果= null; // operatorのインスタンスクラスclazz = this.proxy.getclass(); clazz.getDeclaredMethod( "start"、new class [] {method.class}); // reffection start method start.invoke(this.proxy、newオブジェクト[] {this.proxy.getClass()); clazz.getDeclaredMethod( "end"、new class [] {method.class}); //反射はend method end.invoke(this.proxy、new object [] {method}); return result;}}}を実行します。テストコード:
public class dynatest {public static void main(string [] args){ihello hello =(ihello)new dynaproxyhello()。bind(new hello()、new dlogger()); hello.sayhello( "明日");}}上記の例を通じて、動的なプロキシおよびトランスミッションテクノロジーを通じて、AOPの機能が基本的に実装されていることがわかります。メソッドが実行される前にログを印刷する必要がある場合は、印刷タイミングを制御できるように、end()メソッドを実装することはできません。指定されたメソッドがログを印刷する場合は、メソッド名の判断をInvoke()メソッドに追加するだけです。メソッド名はXMLファイルに記述できるため、構成ファイルでデコープルできるようにして、単純なSpring AOPフレームワークを実装できます。
上記のコンテンツは、編集者が紹介したSpring AOP実装の原則です。それがあなたに役立つことを願っています!