设为首页 加入收藏

TOP

动态代理类的实现和解析(一)
2019-09-25 11:18:24 】 浏览:166
Tags:动态 代理 实现 解析

 静态代理类

  由程序员创建或由特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了

动态代理类:
   与静态代理类对照的是动态代理类,动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java 反射机制可以生成任意类型的动态代理类。java.lang.reflect 包中的Proxy类和InvocationHandler 接口提供了生成动态代理类的能力。

话不多说看代码。。

 

package proxyBase;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.util.Arrays;

import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

public class MyProxy {
    static Class<?>[] parameterTypes = { InvocationHandler.class };
    protected InvocationHandler h;

    protected MyProxy(InvocationHandler h) {
        this.h = h;
    }

    public static Object newInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) {
        // :产生一个代理类的字节码对象
        Class<?> c1 = null;
        try {
            // :通过getClass0方法可以得到一个代理类的字节码对象
            c1 = getClass0(loader, interfaces);
        } catch (MalformedURLException e1) {
            e1.printStackTrace();
        }
        Constructor<?> constructor = null;
        try {
            /**
             * 调用子类$Proxy0(InvocationHandler h)构造函数,由于继承了MyProxy类,
             * 所以又会继续调用父类的MyProxy(InvocationHandler h)构造函数给 h初始化一个值;
             */
            constructor = c1.getDeclaredConstructor(InvocationHandler.class);
            /**
             * 返回一个生成的代理类对象,并将InvocationHandler 的实现类对象传入进去。从而达到给h赋值的目的
             * 
             */
            return constructor.newInstance(h);
        } catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException
                | IllegalArgumentException | InvocationTargetException e) {
            e.printStackTrace();
        }
        return null;
    }

    // :用来生成一个代理类对象
    private static Class<?> getClass0(ClassLoader loader, Class<?>[] interfaces) throws MalformedURLException {
        Class<?> forName = null;
        try {
            GennerateClass.generate(interfaces[0]);
            // :动态编译
            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
            StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null);
            Iterable units = fileMgr.getJavaFileObjects(System.getProperty("user.dir") + "/src/"
                    + interfaces[0].getPackage().getName() + "/" + interfaces[0].getSimpleName() + "$proxy0.java");
            // :"-d", System.getProperty("user.dir")+"/bin/" 用来指定java文件编译后存放的地方
            Iterable<String> options = Arrays.asList("-d", System.getProperty("user.dir") + "/bin/");
            CompilationTask t = compiler.getTask(null, fileMgr, null, options, null, units);
            t.call();
            try {
                fileMgr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            // :得到代码自动生成代理类的实例对象
            forName = Class.forName(interfaces[0].getName() + "$proxy0");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return forName;
    }
}

 这个GennerateClass类是用来生成代理类的Java文件的,是通过字符串拼接而成,仅供参考.

  1 package proxyBase;
  2 
  3 import java.io.BufferedWriter;
  4 import java.io.File;
  5 import java.io.FileWriter;
  6 import java.io.IOException;
  7 import java.lang.reflect.Method;
  8 
  9 public class G
首页 上一页 1 2 3 4 下一页 尾页 1/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇06.Django基础五之django模型层(.. 下一篇通俗易懂设计模式解析——模板方..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目