単純な動的プロキシ(プロキシ)

  最近学んだ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に、NULLNULLNULL 、単位)。
        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



 

おすすめ

転載: www.cnblogs.com/MichaelPL/p/11615756.html