design patterns spring-4 - Analytical source

Simulation of dynamic proxy manually

  No need to manually create a class file (a class file because once created manually, will produce an explosion type), the interface generates a class file by the reflection, and then calls the vendor's compiler technology, the dynamically generated class files compiled into class file, and then using URLClassLoader (because among this class dynamically generated need not project so URLClassLoader) to load the class to the dynamic compilation jvm which, by reflecting the last instance of this class.

 

  Own simulation of dynamic proxy:

  Disadvantages: first Makefile

  Cons: dynamic compilation files class

  Disadvantages: a URLclassloader

  The simulation process:

  Fille - (reading file, generating a class object class) -> class (byte [] ) - ( class objects by class) -> to give the object (which may be clazz.newInstance (); directly or through a new constructor.newInstance ( "invoke"); a new constructor )

 

1, to create an interface to manually handle

public interface InterfaceHandle {
    public Object invoke(Method method, Object[] args);
}

 

2, to achieve handle interfaces

public class User_InvoctionHandle implements InterfaceHandle {
    private Object target;

    public User_InvoctionHandle(Object target) {
        this.target = target;
    }

    public Object invoke(Method method, Object[] args) {
        System.out.println("我是自定义invoke方法");
        try {
            return method.invoke(this.target, null);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return null;
    }
}

 

3, the handwriting proxy class (with a logical overwrite)

public class ProxyUtil {
    public static Object getInstance(Class targetInfo, User_InvoctionHandle handle) {
        Object proxy = null;
//        Class targetInfo = target.getClass().getInterfaces()[0];

        String tab = "\t";
        String line = "\n";

        String implName = targetInfo.getSimpleName();
        //创建java内容
        String javaContent = "";
        //package
        String packageContent = "package com.proxy;" + line;

        //importClass
        String impPackageContent = "import "+handle.getClass().getName()+";"+line+
                                   "import java.lang.reflect.Method;"+line+
                                   "import "+targetInfo.getName()+";"Line +; 

        // create a class body
        ClassContent = String "public class the implements $ Proxy" + implName + "{" + Line; 

        // create a private object handle 
        String privateObject the Tab + = "Private" + handle.getClass () getSimpleName () + "H;." + Line ; 

        // create a configuration, the handle is inapplicable 
        String constructorContent = Tab + "public $ the Proxy (" + handle.getClass () getSimpleName () + "{H.)" + Line; 
        constructorContent = Tab + + + Tab "the this. H = H; "; 
        constructorContent the Tab + = + Line +"} "+ Line; 

        // create methods 
        String methedContent = "";
        Method[] methods = targetInfo.getDeclaredMethods();
        for (Method method : methods) {
            // get the return type 
            String methodTypeName = Method.getReturnType () getSimpleName ();. 
            // get the name of the method 
            String methodName = method.getName();
            + = Tab + methedContent "public" methodTypeName + + "" + methodName + "("; 
            // Create Parameter 
            Object [] args = Method.getParameterTypes (); 
            String argContent = ""; 
            for (int I = 0; I < args.length -. 1; I ++) { 
                // Get parameter type 
                String argsTypeName = args [I] .getClass () getSimpleName ();. 
                // Get the name of the parameter I2 I1 
                argContent = argsTypeName + "I" + I; 
                IF ( ! i = args.length - 1) { 
                    case where a plurality of parameters required // ''The last but not required The last but not required 
                    argContent + = ",";
                } 
            } 
            // content assembling method, a method of automatically and methods consistent with the target 
            methedContent + = argContent + ") { "
                    + line + tab + tab +"try{"
                    + line + tab + tab + tab + "Method method = Class.forName(\""+targetInfo.getName()+"\").getDeclaredMethod(\""+method.getName()+"\");"+line + tab + tab + tab ;
            if(!"void".equals(methodTypeName)){
                methedContent+= "return ("+methodTypeName+")";
            }
                methedContent+=  "h.invoke(method,null);" + line
                    + tab + tab +"}catch(Exception e){"
                    + line + tab + tab + tab + "e.printStackTrace();"
                    + line + tab + tab +"}";
            if(!"void".equals(methodTypeName)){
                methedContent + = Line + Tab + Tab + "return null;"; 
            }
            methedContent + = Line + Tab + "}" + Line + Line; 

        } 
        javaContent = packageContent + impPackageContent + classContent + privateObject + 
                      constructorContent + 
                      methedContent + Line + "}"; 
        / / 1, IO String character stream will be created on D disk, used to see if there is a problem. 
        = FilePath String "D: \\ Proxy COM \\ \\"; 
        String = classFileName. "Com.proxy the Proxy $"; 
        File = filedir new new File ( "D: \\ Proxy COM \\ \\"); 
        the try { 
            {IF (fileDir.isDirectory ()!) 
                fileDir.mkdirs (); 
            }
            File File = new new File ( "D: \\ \\ Proxy \\ $ Proxy.java COM"); 
            IF {(File.Exists ()!) 
                File.createNewFile (); 
            } 
            FileWriter FileWriter = new new FileWriter (File); 
            FileWriter.write (javaContent); 
            fileWriter.flush (); 
            fileWriter.close (); 

            // create java compiler 
            JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler (); 
            // third-party manager 
            StandardJavaFileManager fileMgr = javaCompiler.getStandardFileManager (null, null , null); 
            // the java files into the Manager 
            Iterable Units = fileMgr.getJavaFileObjects (file); 
            // create a compilation task 
            JavaCompiler.CompilationTask Task = javaCompiler.getTask (null , filemgr, null, null, null, Units); 
            // started task
            task.call (); 
            fileMgr.close (); 

            // Get $ using the Proxy reflection compiled object 
            the URL [] = new new URLs the URL [] {new new the URL ( "File: D: \\\\")}; 
            the URLClassLoader the URLClassLoader = new new UCL (urls); 
            Class clazz = ucl.loadClass (classFileName); 
            constructor constructor = clazz.getConstructor (User_InvoctionHandle.class); 
            Proxy = Constructor.newInstance (handle); 
            System.out.println ( "success!") ; 
        } the catch (Exception E) { 
            System.out.println ( "failed!"); 
            e.printStackTrace (); 
        }
        return Proxy; 
    } 
}

  

4, the test

 public static void main(String args[]) {
        //调用手动写的代理
        ObjectDao objectDao = (ObjectDao) ProxyUtil.getInstance(ObjectDao.class, new User_InvoctionHandle(new User_Defined_Dao()));
        System.out.println(objectDao.queryStr());

      
    }

  

5, the regenerated test the Proxy $ proxy class and class

Automatically generated proxy class encoded

package com.dao;
import com.handle.User_InvoctionHandle;
import java.lang.reflect.Method;
import com.dao.ObjectDao;
public class $Proxy implements ObjectDao {
	private User_InvoctionHandle h;
	public $Proxy (User_InvoctionHandle h ){
		this.h = h;
	}
	public void query (){
		try{
			Method method = Class.forName("com.dao.ObjectDao").getDeclaredMethod("query");
			h.invoke(method,null);
		}catch(Exception e){
			e.printStackTrace();
		}
	}

	public String queryStr (){
		try{
			Method method = Class.forName("com.dao.ObjectDao").getDeclaredMethod("queryStr");
			return (String)h.invoke(method,null);
		}catch(Exception e){
			e.printStackTrace();
		}
		return null;
	}


}

  

result

 

 

JDK dynamic proxy source code analysis

  

Guess you like

Origin www.cnblogs.com/gnwzj/p/11117781.html