導入
誰もが知っているように、AOP(セクション指向のプログラミング)は、スプリングフレームワークの機能の1つです。 AOPは、クロスカットの懸念を設定することにより、非常に高いスケーラビリティを提供します。では、AOPは春にどのように機能しますか? Core Javaのみを使用できますが、AOPテクノロジーが必要な場合、この質問に対する答えは非常に重要になります。それだけでなく、高度な技術的ポジションのインタビューでは、そのような質問がテストの質問としてしばしば表示されます。見て、私の友人は最近インタビューに出席し、そのような難しい質問をされました - 春と関連するライブラリとコア・ジャワのみを使用せずにAOPを実装する方法。したがって、この記事では、Core Javaを使用してAOPを実装する方法を理解するのに役立つアウトラインを提供します(もちろん、このAOPには特定の機能的な制限があります)。この記事は、Spring AOPとJava AOPの比較研究ではなく、Core Javaの固有のデザインパターンの助けを借りてAOPの実装に関するチュートリアルであることに注意してください。
読者はすでにAOPが何であり、Springフレームワークでそれを使用する方法を知っていると思います。そのため、この記事ではSpringを使用せずにAOPを実装する方法にのみ焦点を当てています。まず第一に、SpringはJDKプロキシとCGLIBの2つのテクノロジーを使用してAOPを実装することを知っておく必要があります。 JDK Dynamic Proxyは、メソッドをフックして指定された操作を実行する柔軟な方法を提供しますが、操作を実行するときは制限が必要です。関連するインターフェイスとインターフェイスの実装クラスを最初に提供する必要があります。真の知識を作成するために練習し、ケースを通してこの文を理解しましょう!現在、いくつかの数学操作を行うための計算機プログラムがあります。分割関数を考えてみましょう。現時点での問題は、コアフレームワークに既に分割を実装するコードがある場合、コードが実行されたときにハイジャックして追加の検証を実行できますか?答えはイエスであり、以下に示されているコードスニペットでこれを証明します。まず、基本的なインターフェイスのコードを見てみましょう。
パブリックインターフェイス計算機{public int calculate(int a、int b);}このインターフェイス実装クラスのコードは次のとおりです。
パブリッククラスCalculaturimplはCalculatorを実装します{@Override public int calculate(int a、int b){return a/b; }}上記のコードを修復したり、コアライブラリに変更を加えることができないと仮定して、検証関数を完全に実装するにはどうすればよいですか? JDKダイナミックプロキシ関数を試してみませんか。
パブリッククラスSomehandler ImpocationHandler {//コードは簡単に省略されています….. @OverrideパブリックオブジェクトInvoke(Object Proxy、Method Method、Object [] Params)スロー可能{//複雑なビジネス検証とロジックオブジェクト結果= Method.Invoke(TargetObject、Params);返品結果; }}JDKダイナミックプロキシによって実装された検証機能が、テストクラスを通じてどのように機能するかを見てみましょう。
public static void main(string [] args){calculationimpl calcimpl = new calculaturimpl();電卓proxied =(calculator)proxyfactory.getProxy(calculator.class、calcimpl、new Somehandler(calcimpl)); int result = proxied.calculate(20、10); System.out.println( "最終結果:::" + result); }結果から、強力なInvocationHandlerインターフェイスを実装するだけで、フックの実装を取得できることがわかります。 JDKドキュメントによると、InvocationHandler Interfaceはプロキシインスタンスを使用してメソッド呼び出しを処理します。
Invoke()InvocationHandlerの方法が問題を解決するのに役立つことがわかっています。それでは、新しい問題を解決しましょう - メソッド実行の前後に操作を実行するにはどうすればよいですか?より具体的に言えば、複数のAOPSを追加して(前、後、周りに)メソッドをフックすることはできますか(翻訳者のメモ:元のテキストは複数のAOPSを追加しますが、ハンドラーはアスペクトとして機能すると思います)?答えもイエスです。以下の手順に従って、この要件を満たすために合理化されたコードテンプレートを作成します。
AOPを実装する2つの方法:
1。JDKが提供する動的プロキシ実装
インタフェース
public interface userbean {void getuser(); void adduser(); void updateUser(); void deleteuser(); }元の実装クラス
Public Class userbeanimplはuserbeanを実装します{private string user = null; public userbeanimpl(){} public userbeanimpl(string user){this.user = user; } public string getUsername(){return user; } public void getUser(){system.out.println( "これはgetUser()メソッドです!"); } public void setuser(string user){this.user = user; system.out.println( "これはsetuser()メソッドです!"); } public void adduser(){system.out.println( "これはadduser()メソッドです!"); } public void updateUser(){system.out.println( "これはupdateUser()メソッドです!"); } public void deleteuser(){system.out.println( "これはdeleteuser()メソッドです!"); }}エージェントクラス
java.lang.reflt.invocationhandlerをインポートします。 java.lang.reflt.methodをインポートします。 java.lang.reflt.proxyをインポートします。 com.cignacmc.finance.bean.userbeanimplをインポートします。 Public Class userbeanProxyは、InvocationHandlerを実装しています{private Object TargetObject; public userbeanProxy(Object TargetObject){this.targetObject = targetObject; } public object invoke(Object Proxy、Method Method、Object [] args)throws throwable {userbeanimpl userbean =(userbeanimpl)targetobject;文字列username = userbean.getusername();オブジェクト結果= null; //許可判断if(username!= null &&! ""。equals(username)){result = method.invoke(ターゲットオーブジェクト、args); } return result; }}
テストクラス
java.lang.reflt.proxyをインポートします。 com.cignacmc.finance.bean.userbeanをインポートします。 com.cignacmc.finance.bean.userbeanimplをインポートします。 com.cignacmc.finance.proxy.userbeanproxyをインポートします。 public class proxyexe {public static void main(string [] args){system.out.println( "証明........."); userbeanimpl targetobject = new userbeanimpl( "bob liang"); userbeanproxy proxy = new userbeanProxy(TargetObject); // proxy object userbean object =(userbean)proxy.newproxyinstance(targetobject.getClass()。getClassLoader()、ターゲットオーブジェクト.getClass()。getInterfaces()、プロキシ); object.adduser(); System.out.println( "証明されていない............");ターゲットオブジェクト= new userbeanimpl(); proxy = new userbeanProxy(ターゲットオブジェクト); //プロキシオブジェクトを生成=(userbean)proxy.newproxyinstance(targetobject.getClass()。getClassLoader()、ターゲットオーブジェクト.getClass()。getInterfaces()、proxy); object.adduser(); }}
出力:
証明された............これはAdduser()メソッドです!証明されていません..........
上記の例から、呼び出されたメソッドadduser()は、それに応じて正常に傍受して処理できます。
2。CGLIBを介してプロキシクラスを作成します
利点は、ターゲットオブジェクトがインターフェイスプリミティブクラスを実装する必要がないことです。
public class clientbean {private string name = null; public clientbean(){} public clientbean(string name){this.name = name; } public void addclient(){system.out.println( "これはaddclient()method!"); } public void deleteclient(){system.out.println( "これはdeleteclient()method!"); } public void getClient(){system.out.println( "これはgetclient()メソッドです!"); } public void getClient(){system.out.println( "これはgetclient())メソッド!"); } public void updateClient(){system.out.println( "これはupdateclient()method!"); } public string getClientName(){return name; } public void setClientName(string name){this.name = name; }}エージェントクラス
java.lang.reflt.methodをインポートします。 com.cignacmc.finance.bean.clientbeanをインポートします。 net.sf.cglib.proxy.enhancerをインポートします。 net.sf.cglib.proxy.methodInterceptorをインポートします。 net.sf.cglib.proxy.methodInterceptorをインポートします。 net.sf.cglib.proxy.methodproxyをインポートします。パブリッククラスcglibproxyはmethodEnterceptorを実装します{private object targetObject; public Object createproxyObject(object TargetObject){this.targetObject =ターゲットオブジェクト; Enhancer Enhancer = new Enhancer(); Enhancer.setsuperclass(this.targetobject.getClass()); Enhancer.setCallback(This); return enthancer.create(); } public Object intercept(Object Proxy、Method Method、Object args、MethodProxy MethodProxy)Throws {ClientBean ClientBean =(ClientBean)TargetObject;文字列username = clientbean.getClientName();オブジェクト結果= null; if(username!= null &&! ""。equals(username)){result = method.invoke(targetobject、args); } return result; }}テストクラス
java.lang.reflt.proxyをインポートします。 com.cignacmc.finance.bean.clientbeanをインポートします。 com.cignacmc.finance.bean.userbeanをインポートします。 com.cignacmc.finance.bean.userbeanimplをインポートします。 com.cignacmc.finance.proxy.cglibproxyをインポートします。 com.cignacmc.finance.proxy.userbeanproxyをインポートします。 public class proxyexe {public static void main(string [] args){system.out.println( "........ cglib proxy ............"); System.out.println( "証明................."); cglibproxy cproxy = new cglibproxy(); ClientBean ClientBean =(ClientBean)cproxy.createproxyobject(new ClientBean( "Bob Liang")); clientbean.addclient(); System.out.println( "証明されていない................."); cproxy = new cglibproxy(); clientBean =(clientbean)cproxy.createproxyobject(new ClientBean()); clientbean.addclient(); }}
出力:
..... cglibプロキシ..................証明されました............これはaddclient()メソッドです!証明されていない............