zoukankan      html  css  js  c++  java
  • 手写实现JDK的动态代理

    Person接口

    package com.zhoucong.proxy.jdk;
    
    public interface Person {
    
    //    寻找真爱
        void findlove();
    
    }

    人物实现类

    package com.zhoucong.proxy.jdk;
    
    public class Zhangsan implements Person{
        
        @Override
        public void findlove() {
            System.out.println("我叫张三,性别女,我找对象的要求如下:
    ");
            System.out.println("高富帅");
            System.out.println("有房有车");
            System.out.println("身高180cm以上,体重70kg");
        }
    
    }

    自定义InvocationHandler接口

    package com.zhoucong.custom;
    
    import java.lang.reflect.Method;
    
    public interface GPInvocationHandler {
        
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable;
    
    }

    代理类

    package com.zhoucong.custom;
    
    import java.lang.reflect.Method;
    
    import com.zhoucong.proxy.jdk.Person;
    
    public class GPMeiPo implements GPInvocationHandler{
    
        private Person target;
        
    //  获取被代理人的个人资料
        public Object getInstance(Person target) throws Exception {
            this.target = target;
            Class clazz = target.getClass();
            System.out.println("被代理对象的class是:"+ clazz);
            return GPProxy.newProxyInstance(new GPClassLoader(), clazz.getInterfaces(), this);
            
        }
        
        
        
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
             System.out.println("我是媒婆!");
             System.out.println("开始信息海选");
             System.out.println("-------------");
             method.invoke(this.target, args);
             System.out.println("-------------");
             System.out.println("如果合适的话,就准备办事");
             return null;
        }
    
    }

    生成代理对象类

    package com.zhoucong.custom;
    
    import java.io.File;
    import java.io.FileWriter;
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Method;
    
    import javax.tools.JavaCompiler;
    import javax.tools.JavaCompiler.CompilationTask;
    import javax.tools.StandardJavaFileManager;
    import javax.tools.ToolProvider;
    
    
    /**
     * 生成代理对象的代码
     * 
     * @author ZhouCong
     *
     */
    public class GPProxy {
    
        private static String ln = "
    ";
    
        public static Object newProxyInstance(GPClassLoader loader, Class<?>[] interfaces, GPInvocationHandler h)
                throws IllegalArgumentException {
            try {
    //        1.生成源代码
            String proxySrc = generateSrc(interfaces[0]);
    
    //        2.将生成的源代码输出到磁盘,保存.java文件
                String path = GPProxy.class.getResource("").getPath();
                File f = new File(path + "$Proxy0.java");
                FileWriter fw = new FileWriter(f);
                fw.write(proxySrc);
                fw.flush();
                fw.close();
                
    //        3.编译源代码,并且生成.class文件
            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
            StandardJavaFileManager manager = compiler.getStandardFileManager(null, null, null);
            Iterable iterable = manager.getJavaFileObjects(f);
            CompilationTask task = compiler.getTask(null, manager, null, null, null, iterable);
            task.call();
            manager.close();
            
    //        4.将class文件中的内容,动态加载到JVM中
            Class<?> proxyClass = loader.findClass("$Proxy0");
            Constructor<?> constructor = proxyClass.getConstructor(GPInvocationHandler.class);
            f.delete(); //删除生成的Java文件
    
    //        5.返回被代理后的代理对象
            return constructor.newInstance(h);
            
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return null;
        }
    
        /**
         * 生成代码
         * @param interfaces
         * @return
         */
        private static String generateSrc(Class<?> interfaces) {
    
            StringBuffer src = new StringBuffer();
            src.append("package com.zhoucong.custom;" + ln);
            src.append("import java.lang.reflect.Method;" + ln);
            src.append("public class $Proxy0 implements " + interfaces.getName() + "{" + ln);
            src.append("GPInvocationHandler h;" + ln);
            src.append("public $Proxy0(GPInvocationHandler h){" + ln);
            src.append("this.h = h;" + ln);
            src.append("}" + ln);
            
            for (Method m : interfaces.getMethods()) {
                src.append("public " + m.getReturnType().getName() + " " + m.getName() + "() {" + ln);
                src.append("try {" + ln);
                src.append("Method m = " + interfaces.getName() + ".class.getMethod("" + m.getName() +"",new Class[]{});" + ln);      
                src.append("this.h.invoke(this,m,null);" + ln);
                src.append("} catch(Throwable e){e.printStackTrace();}" + ln);
                src.append("}" + ln);
            }
            
            
            src.append("}");
            return src.toString();
        };
    }

    自定义ClassLoader类

    package com.zhoucong.custom;
    
    import java.io.ByteArrayOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    
    /**
     * 代码生成、编译、重新动态load到JVM中
     * @author ZhouCong
     *
     */
    public class GPClassLoader extends ClassLoader{
    
        private File baseDir;
        
        public GPClassLoader() {
            String path = GPClassLoader.class.getResource("").getPath();
            this.baseDir = new File(path);
        }
        
        
        @Override
        protected Class<?> findClass(String name) throws ClassNotFoundException {
            String className = GPClassLoader.class.getPackage().getName() + "." + name;
            if(baseDir != null) {
                File classFile = new File(baseDir,name.replaceAll("\.", "/")+".class");
                if(classFile.exists()) {
                    FileInputStream in = null;
                    ByteArrayOutputStream out = null;
                    try {
                        in = new FileInputStream(classFile);
                         out = new ByteArrayOutputStream();
                        byte [] buff = new byte[1024];
                        int len;
                        while((len = in.read(buff)) != -1) {
                            out.write(buff,0,len);
                        }
                        return defineClass(className,out.toByteArray(),0,out.size());
                        
                    }catch (Exception e) {
                        e.printStackTrace();
                    }finally {
                    
                        if(null != in) {
                            try {
                                in.close();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                        if(null != out) {
                            try {
                                out.close();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
    //                    删除class文件
                        classFile.delete();
                    }
                }
                
            }
            
            return null;
        }
        
        
    }

    运行类

    package com.zhoucong.proxy.jdk;
    
    import com.zhoucong.custom.GPMeiPo;
    
    
    public class TestFindLove {
    
        public static void main(String[] args) {
    
            try {
    
                Person obj = (Person) new GPMeiPo().getInstance(new Zhangsan());
                System.out.println(obj.getClass());
                obj.findlove();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
    }
  • 相关阅读:
    java图片加文字
    [转]NetBeans优化技巧 提升启动速度
    重建win7桌面图标缓存
    负载测试(Load Test)
    乐观锁与悲观琐的区别
    事物锁表问题
    建立silverlight安装环境
    持续集成ccnet
    C# AppDomain
    Windows Services
  • 原文地址:https://www.cnblogs.com/itzhoucong/p/12144339.html
Copyright © 2011-2022 走看看