最近学んだJDKの動的プロキシは、それは簡単な手書きです。
アイデア:
1.エージェントインターフェイス、対応するJavaコードファイル生成
クラスファイルにコンパイル生成されたJavaファイル2.
3. URLClassLoaderのJVMがオブジェクトを使用してクラスにロードされたが、新たなに反映しました。
エージェントサービスのインタフェース
パッケージcom.michael.pl。 インポートにjava.lang.reflect.InvocationTargetException; 輸入java.lang.reflect.Methodオブジェクト。 パブリック インターフェイスのInvocationHandler { オブジェクトinvock(Objectオブジェクト、メソッドのメソッド、オブジェクト[]引数)がスローにInvocationTargetException、IllegalAccessExceptionがします。 }
プロキシへのインタフェース
パッケージcom.michael.pl.service。 パブリック インターフェースLogService { ボイド sayHi()スロー例外。 (文字列テキストは)outオブジェクトスロー例外。 }
パッケージcom.michael.pl.service.impl。 輸入com.michael.pl.service.LogService。 パブリック クラス LogServiceImplが実装LogService { @Override 公共 ボイドsayHi(){ System.out.printlnは( "こんにちは" )。 } @Override パブリックオブジェクトアウト(文字列テキスト){ 返すテキストを、 } }
コア動的プロキシクラス
パッケージcom.michael.pl。 輸入javax.tools.JavaCompiler。 輸入javax.tools.StandardJavaFileManager。 輸入javax.tools.ToolProvider。 インポートのjava.io.File; 輸入java.io.FileWriter; 輸入java.lang.reflect.Constructor。 輸入java.lang.reflect.Methodオブジェクト。 インポートのjava.net.URL; 輸入java.net.URLClassLoader。 パブリック クラスてMyProxy { パブリック 静的 最終 =「」文字列テーブル。 公共の 静的な 最終文字列=「\ n」をENTER 。 公 静的オブジェクトnewProxyInstance(<?>のClassLoaderクラスローダ、クラスinterfaceClass、 のInvocationHandlerのInvocationHandler)がスロー例外{ 文字列javaCode = buiderJavaFile(interfaceClass)。 // するSystem.out.println(javaCode)。 文字列クラス名 = interfaceClass.getName()サブストリング(interfaceClass.getName()のlastIndexOf()+ 1 "" ); ファイルファイル = 新しいファイル( "\\ COM \\日\\プロキシ\\ $" +クラス名+ "の.java" ); ファイルparentFile = file.getParentFile(); もし(! parentFile.exists()){ parentFile.mkdirs(); } IF(!File.Exists()){ file.createNewFile(); } // ハードディスクに書き込まれた優れたJavaファイルの中での戦い てFileWriter FW = 新しい新しいてFileWriter(ファイル); fw.write(javacode); fw.close( ); // ファイルをJavaクラスにコンパイルハードディスクに書き込まれ JavaCompilerコンパイラ= ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager filemgrに = compiler.getStandardFileManager(ヌル、ヌル、ヌル); 反復処理可能な単位 =ヌル fileMgr.getJavaFileObjects(ファイル); JavaCompiler.CompilationTask T = compiler.getTask(、filemgrに、NULL、NULL、NULL 、単位)。 t.call(); fileMgr.close(); // 吧编译上的クラス文件加载到JVM中 URL []のURL = 新しい URL [] { 新たな URL( "ファイル:G:\\\\" )}。 URLClassLoaderのURLClassLoaderの = 新しいURLClassLoaderの(のURL); クラスclazz = urlClassLoader.loadClass( "com.sun.proxy $。" + クラス名)。 コンストラクタコンストラクタ = clazz.getConstructor(のInvocationHandler。クラス)。 返すconstructor.newInstance(のInvocationHandlerを)。 } / ** *生成对应的のJava代码 * / パブリック 静的な文字列buiderJavaFile(クラス<?> interfaceClass)スロー例外{ 文字列クラス名 = interfaceClass.getName()。ストリング(interfaceClass.getName()。のlastIndexOf( "")+ 1 ); StringBuilderの内容 = 新しいStringBuilderの(); content.append( "パッケージcom.sun.proxy;" + ENTER)。 content.append( "輸入java.lang.reflect.Methodオブジェクト;" + ENTER)。 content.append( "輸入のjava.lang.Exception;" + "輸入com.michael.pl.InvocationHandler;" ENTER)。 content.append(入る); content.append( "パブリッククラス$" +クラス名+ "実装" + interfaceClass.getName()+ "{" + ENTER)。 content.append(TABLE + "私はプライベートのInvocationHandler;" + ENTER)。 // 添加构造方法 content.append(forTableは、(1)+ "公共$" +クラス名+ "(のInvocationHandler i)は、{" + ENTER)。 content.append(forTableは、( 1)+ "this.i = I;" + ENTER)。 content.append(forTable( 1)+ "}" + ENTER)。 方法[]メソッド = interfaceClass.getMethods()。 用(i = 0; iはmethods.length <。 方法メソッド = 法[I]。 文字列戻り値の = method.getReturnType()のgetName()。 int型 J = 0 ; 文字列paramContent = "" ; 文字列callParam = "" ; 文字列paramClass = "" ; 用(<?>クラスparamType:method.getParameterTypes()){ paramContent + = paramType.getName()+ "引数" + J + "" 。 callParam + = "引数" + J + "" ;+ = paramType.getName()+ "の.class" ; J ++ ; } であれば(paramContent.length()> 0 ){ paramContent = paramContent.substring(0、paramContent.length() - 1 )。 callParam = "新しいオブジェクト[] {" + callParam.substring(0、callParam.length() - 1)+ "}" 。 paramClass = paramClass.substring(0、paramClass.length() - 1 )。 } であれば(callParam.length()== 0 ){ callParam = "NULL" 。 } 文字列exceptionContent= "" ; 用(<?>クラスexceptionType:method.getExceptionTypes()){ exceptionContent + = exceptionType.getName()+ "" 。 } 場合(exceptionContent.lengthは()> 0 ){ exceptionContent =は"スロー" + exceptionContent.substring(0、exceptionContent.length() - 1 )。 } content.append(forTable( 1)+ "パブリック" +戻り値の+ "" + method.getName()+ "(" + paramContent + ")" + exceptionContent + "{" + ENTER)。 コンテンツ。 interfaceClass.getName() 返すプライベート content.toString(); } 静的文字列forTable(int型のI){ 文字列str = "" ; 用(INT J = 0; J <I、J ++ ){ STR + = 表。 } 戻りSTR。 } }
テストカテゴリ
パッケージcom.michael.pl。 輸入com.michael.pl.service.LogService。 輸入com.michael.pl.service.impl.LogServiceImpl。 インポートにjava.lang.reflect.InvocationTargetException; 輸入java.lang.reflect.Methodオブジェクト。 パブリック クラスTestDemo { 公共 静的 ボイドメイン(文字列[]引数)がスロー例外{ // 被代理的对象 LogServiceImpl logServiceImpl = 新しいLogServiceImpl()。 LogService logService =(LogService)MyProxy.newProxyInstance(TestDemo。クラス .getClassLoader()、LogService。クラス、 新規のInvocationHandler(){ @Override パブリックオブジェクトinvock(Objectオブジェクト、メソッドのメソッド、オブジェクト[] argss) スローにInvocationTargetException、IllegalAccessExceptionが{ するSystem.out.println( "代理类容!!"を)。 返すmethod.invoke(logServiceImpl、argssを)。 } })。 logService.sayHi(); logService.out( "你好" ); } }
ダウンロードコード:https://files.cnblogs.com/files/MichaelPL/MyProxy.zip