Simple dynamic proxy (Proxy)

  Recently learned Jdk dynamic proxy, then it is a simple handwriting. 
  
  Ideas:
      1. The agent interface, generate the corresponding Java code file
      2. The generated Java files compiled into class files
      3. Use URLClassLoader Jvm loaded into the class using the object reflected in new.


Agent Service Interface
package com.michael.pl;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public interface InvocationHandler {

    Object invock(Object object, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException;

}
 

 

Interfaces to proxy

 
package com.michael.pl.service;

public interface LogService {

    void sayHi() throws Exception;

    Object out(String text) throws Exception;

}
 
package com.michael.pl.service.impl;

import com.michael.pl.service.LogService;

public class LogServiceImpl implements LogService {

    @Override
    public void sayHi() {

        System.out.println("hello");

    }

    @Override
    public Object out(String text) {
        return text;
    }
}
 

 

The core dynamic proxy class
package com.michael.pl;

import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;

public class MyProxy {

    public static final String TABLE = "    ";
    public static final String ENTER = "\n";

    public static Object newProxyInstance(ClassLoader classLoader, Class<?> interfaceClass,
        InvocationHandler invocationHandler) throws Exception {

        String javaCode = buiderJavaFile(interfaceClass);
//        System.out.println(javaCode);

        String className = interfaceClass.getName().substring(interfaceClass.getName().lastIndexOf(".") + 1);
        File file = new File("\\com\\sun\\proxy\\$" + className + ".java");

        File parentFile = file.getParentFile();
        if (!parentFile.exists()) {
            parentFile.mkdirs ();
        } 

         fileMgr.getJavaFileObjects ( file);IF (! File.Exists ()) { 
            file.createNewFile (); 
        } 

        // The fight among good Java file written to the hard disk 
        FileWriter fw = new new FileWriter (File); 
        fw.write (javacode); 
        fw.close ( ); 

        // the file is written to the hard disk compiled into Java class 
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler (); 
        StandardJavaFileManager filemgr = compiler.getStandardFileManager ( null , null , null ); 
        Iterable Units = 
        JavaCompiler.CompilationTask t = compiler.getTask ( null, fileMgr, null, null, null, units);
        t.call();
        fileMgr.close();


        // 吧编译上的class文件加载到JVM中
        URL[] urls = new URL[]{new URL("file:G:\\\\")};


        URLClassLoader urlClassLoader = new URLClassLoader(urls);
        Class clazz = urlClassLoader.loadClass("com.sun.proxy.$" + className);

        Constructor constructor = clazz.getConstructor(InvocationHandler.class);
        return constructor.newInstance(invocationHandler);
    }

    /**
     * 生成对应的Java代码
     */
    public static String buiderJavaFile(Class<?> interfaceClass) throws Exception {

        String className = interfaceClass.getName().substring(interfaceClass.getName().lastIndexOf(".") + 1);

        StringBuilder content = new StringBuilder();
        content.append("package com.sun.proxy;" + ENTER );
        content.append("import java.lang.reflect.Method;" + ENTER);
        content.append("import java.lang.Exception;" + ENTER);
        content.append("import com.michael.pl.InvocationHandler;" + ENTER);
        content.append("public class $" + className + " implements " + interfaceClass.getName() + "{" + ENTER);

        content.append(TABLE + "private InvocationHandler i;" + ENTER);

        // 添加构造方法
        content.append(forTable(1) + " public $" + className + "(InvocationHandler i){"+ENTER);
        content.append(forTable(1) + "this.i = i;" + ENTER);
        content.append(forTable(1) + "}" + ENTER);


        Method[] methods = interfaceClass.getMethods();
        for (int i = 0; i < methods.length; i++) {
            Method method = methods[i];

            String returnType = method.getReturnType().getName();

            int j = 0;
            String paramContent = "";
            String callParam = "";
            String paramClass = "";
            for (Class<?> paramType : method.getParameterTypes()) {
                paramContent += paramType.getName() + " args" + j + ",";
                callParam += "args" + j + ",";
                paramClass += paramType.getName() + ".class,";
                j++;
            }
            if (paramContent.length()>0) {
                paramContent = paramContent.substring(0, paramContent.length() - 1);
                callParam = "new Object[]{" + callParam.substring(0, callParam.length() - 1) + "}";
                paramClass = paramClass.substring(0, paramClass.length() - 1);
            }

            if (callParam.length() == 0) {
                callParam = "null";
            }


            String exceptionContent = "";
            for (Class<?> exceptionType : method.getExceptionTypes()) {
                exceptionContent += exceptionType.getName() + ",";
            }
            if (exceptionContent.length()>0) {
                exceptionContent = "throws " + exceptionContent.substring(0, exceptionContent.length() - 1);
            }

            content.append(forTable(1) + "public " + returnType + " " + method.getName() + "(" + paramContent + ") "
                + exceptionContent + "  {" + ENTER);
            content.append(forTable(2) + "Method declaredMethod = Class.forName(\"" + interfaceClass.getName()
                + "\").getDeclaredMethod(\"" + method.getName() + "\"" + (paramClass.length() == 0 ? "" :
                "," + paramClass) + ");" + ENTER);
            if (!"void".equals(method.getReturnType().getName())) {
                content.append(forTable(2) + "return (" + returnType + ")");
            }
            content.append("i.invock(this,declaredMethod,"+callParam+");" + ENTER);

            content.append(forTable(1) + "}" + ENTER);
        }


        content.append("}" + ENTER);

        return content.toString();

    }


    private static String forTable(int i) {
        String str = "";
        for (int j = 0; j < i; j++) {
            str += TABLE;
        }
        return str;

    }


}
View Code
 

 

Test category

package com.michael.pl;

import com.michael.pl.service.LogService;
import com.michael.pl.service.impl.LogServiceImpl;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class TestDemo {

    public static void main(String[] args) throws Exception {


        // 被代理的对象
        LogServiceImpl logServiceImpl = new LogServiceImpl();

        LogService logService = (LogService)MyProxy.newProxyInstance(TestDemo.class.getClassLoader(), LogService.class,
            new InvocationHandler() {

                @Override
                public Object invock(Object object, Method method, Object[] argss)
                    throws InvocationTargetException, IllegalAccessException {
                    System.out.println(" 代理类容!!");
                    return method.invoke(logServiceImpl, argss);
                }

            });

        logService.sayHi();
        logService.out("你好");



    }

}

 

 Download Code: https://files.cnblogs.com/files/MichaelPL/MyProxy.zip



 

Guess you like

Origin www.cnblogs.com/MichaelPL/p/11615756.html