美文网首页JavaJava 杂谈
第一章1.2 动态代理-自己实现一个

第一章1.2 动态代理-自己实现一个

作者: yust5273 | 来源:发表于2019-06-07 16:13 被阅读0次
//代码生成、编译、重新动态loader到JVM中
public class YustClassLoader  extends ClassLoader{
    private File baseDir;
    public YustClassLoader() {
        String baseDir = YustClassLoader.class.getResource("").getPath();
        this.baseDir = new File(baseDir)  ;
    }
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        String className = YustClassLoader.class.getPackage().getName();
        if(Objects.nonNull(baseDir)){
            File classFile = new File(baseDir, name.replaceAll("\\.", "/") + ".class");
            if (classFile.exists()){
                try(FileInputStream in =new FileInputStream(classFile); ByteArrayOutputStream 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 (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }finally {
                    classFile.delete();
                }
            }
        }
        return null;
    }
}
public interface YustInvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}
public class YustMeipo implements YustInvocationHandler {
    private Person target;//被代理对象的引用作为一个成员变量进行保存下来了
    public Object getInstance(Person target)throws  Exception{
        this.target=target;
        Class clazz = target.getClass();
        System.out.println("被代理对象的class是:"+clazz);
        return YustProxy.newProxyInstance(new YustClassLoader(), clazz.getInterfaces(), this);
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("我是媒婆:你的性别是:"+this.target.getSex()+"得给你找个异性");
        System.out.println("-----------------------------");
        method.invoke(this.target, args);
        System.out.println("-----------------------------");
        return null;
    }
}
public class YustProxy {
    private static String ln = "\r\n";
    public static Object newProxyInstance(YustClassLoader classLoader,Class<?>[] interfaces,YustInvocationHandler h){
        try{
            //1、生成源代码
            String proxySrc = generateSrc(interfaces[0]);
            //2、将生成的源代码输出到磁盘,保存为.java文件
            String filePath = YustProxy.class.getResource("").getPath();
            File f = new File(filePath + "$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 = classLoader.findClass("$Proxy0");
            Constructor c = proxyClass.getConstructor(YustInvocationHandler.class);
            f.delete();
            //5.返回被代理后的代理对象
            return c.newInstance(h);

        }catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    private static String generateSrc(Class<?> interfaces){
        StringBuffer src = new StringBuffer();
        src.append("package com.yust5273.proxy.custom;" + ln);
        src.append("import java.lang.reflect.Method;" + ln);
        src.append("import com.yust5273.proxy.custom.YustInvocationHandler" + ln);
        src.append("public class $Proxy0 implements " + interfaces.getName() + "{" + ln);
        src.append("YustInvocationHandler h;" + ln);
        src.append("public $Proxy0(YustInvocationHandler 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();
    }
}
public class YustTestFindLove {
    public static void main(String[] args){
        try {
            Person obj =(Person) new YustMeipo().getInstance(new XiaoXingXing());
            System.out.println(obj.getClass());
            obj.findLove();
            //代理对象的实现原理
            //1.拿到被代理对象的引用,然后获取它的接口、
            //2.JDK代理 就会重新生成一个类同时实现我们给的代理对象的所实现的接口
            //3.把被代理对象的引用也拿到了
            //4.重新生成一个class字节码
            //5.然后编译
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

相关文章

  • 动态代理(二)

    动态代理的原理 我们可以看到动态代理是根据反射实现的,那么我们可以自己实现动态代理吗? 1、每个动态代理的类都实现...

  • Java动态代理原理剖析(一)

    这篇文章将深入的分析Java的动态代理实现原理,首先将自己实现一个动态代理,然后顺势分析JDK中的动态代理实现并与...

  • 第一章1.2 动态代理-自己实现一个

  • 动态代理-jdk代理实现原理

    动态代理-jdk代理实现原理 JDK中提供了一个Proxy类用于实现动态代理,JDK的动态代理是基于接口实现的,被...

  • Java 动态代理

    前言 关于动态代理 JDK动态代理 CGLIB动态代理 区别 java动态代理是利用反射机制生成一个实现代理接口的...

  • mybatis中的动态代理解析

    动态代理的目的: 一个接口需要通过动态代理对象为自己产生一个匿名的实现类,平时我们都是自己实现这个接口,然后通过...

  • java面试宝典 五分钟了解spring代理 @Transact

    spring代理分为jdk动态代理和cglib代理 jdk动态代理 jdk动态代理是利用反射机制生成一个实现代理接...

  • CGlib动态代理

    动态代理比起静态代理方便的多,但是jdk动态代理实现必须通过接口,如果要代理一个没有接口的类jdk动态就无法实现了...

  • 代理

    普通的动态代理可以继承实现方法实现super方法前后实现代理 动态代理的步骤①创建一个接口,目标类实现这个接口②创...

  • 编程常用的设计模式

    动态代理和静态代理 静态代理 动态代理 静态代理与动态代理的区别 JDK中的动态代理和CGLIB 实现动态代理的方...

网友评论

    本文标题:第一章1.2 动态代理-自己实现一个

    本文链接:https://www.haomeiwen.com/subject/euzmxctx.html