zoukankan      html  css  js  c++  java
  • 设计模式-代理模式

    设计模式-代理模式

    代理模式:

    代理模式是指为其他对象提供一种代理,以控制对这个对象的访问。

    代理对象在客户端与服务端之间起到中介作用。

    属于结构型设计模式。

    使用场景

    • 保护目标对象
    • 增强目标对象

    静态代理

    代码示例:

    package com.black.design.pattern.proxy;
    
    /**
     * 被代理类
     * @author black
     *
     */
    public class Target implements TargetInterface{
        public void doSomething() {
            System.out.println(" do something...");
        }
    
        public String doSomWork(String work) {
            System.out.println(" do " + work + "...");
            return "work done!";
        }
    }
    
    package com.black.design.pattern.proxy.staticc;
    
    import com.black.design.pattern.proxy.Target;
    
    /**
     * 静态代理对象
     * @author black
     *
     */
    public class StaticProxy {
    
        //目标对象
        private Target target ;
    
        public StaticProxy(Target target) {
            this.target = target;
        }
        
        public void invokeDoSomething(String param) {
            System.out.println("before do something.");
            target.doSomething();
            System.out.println("after do something.");
        }
    }
    

    测试:

    package com.black.design.pattern.proxy.staticc;
    
    import com.black.design.pattern.proxy.Target;
    
    /**
     * 静态代理对象测试类
     * @author black
     *
     */
    public class StaticProxyTest {
        
        public static void main(String[] args) {
            //真实对象
            Target target = new Target();
            //代理对象
            StaticProxy proxy = new StaticProxy(target);
            //调用代理对象的方法
            proxy.invokeDoSomething(null);
            
        }
    }
    
    

    结果:

    before do something.
     do something...
    after do something.
    
    

    动态代理

    JDK动态代理

    使用JDK动态代理规则

    1.编写一个实现 Demo 接口的实现类或接口类(我这里称为“目标类”);
    2.编写一个InvocationHandler接口的实现类;
    3.使用 Proxy.newProxyInstance... 创建代理类实例,并赋值给 Demo 接口类型一个变量 p,此时 p 指向的就是名字叫$Proxy0并且实现了 Demo 接口的实例;
    4.通过调用 p 变量的方法,就会触发 InvocationHandler 实现类的invoke方法。

    注意目标类必须是接口实现类或接口类!

    编码实现

    使用动态生成代理类步骤:

    1. 编写一个 Printer 接口类;
    2. 编写一个 Printer 接口实现类BlackPrinter;
    3. 编写一个实现 InvocationHandler 接口的实现类JDKInvocationHandler;
    4. 获取代理类,并调用目标方法;

    具体如下:
    编写一个 Printer 接口类:

    package com.black.design.pattern.proxy.blackproxy;
    
    //打印机
    public interface Printer {
        
        //打印
        public void print() ;
    }
    
    

    编写一个实现类BlackPrinter:

    package com.black.design.pattern.proxy.blackproxy;
    
    //黑色打印机
    public class BlackPrinter implements Printer{
    
        public void print() {
            System.out.println("这是一台黑色打印机....");
        }
    }
    

    编写一个实现 InvocationHandler 接口的实现类 JDKInvocationHandler:

    package com.black.design.pattern.proxy.blackproxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    // InvocationHandler 实现类
    public class JDKInvocationHandler implements InvocationHandler{
        //目标类 target
        Object target ;
        //构造器传入目标类 t
        public JDKInvocationHandler(Object t ) {
            this.target = t;
        }
            
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("JDK代理:方法执行前....");
            //调用目标类方法
            Object result = method.invoke(this.target, args);
            System.out.println("JDK代理:方法执行结束。");
            return result;
        }
    }
    
    

    获取代理类,并调用目标方法

    package com.black.design.pattern.proxy.blackproxy;
    
    import java.lang.reflect.Proxy;
    //测试类
    public class BlackProxyTest {
    
        public static void main(String[] args) {
        
        //sun.misc.ProxyGenerator.saveGeneratedFiles 属性设置为true 可保存生成的代理类到工程目录下
        //System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
            //创建目标类 bp
            Printer bp = new BlackPrinter();
            Class clazz = bp.getClass();
            //生成代理类 proxy 传入 3 个参数:
            //  (1)目标类加载器: 这里传入bp的类加载器
            //  (2)目标类的接口类数组: 这里传入 b.getClass().getgetInterfaces()
            //  (3)InvocationHandler实现类 : 当调用代理类的方法时会回调 InvocationHandler实现类的invoke 方法。
            Printer proxy= (Printer) Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), new JDKInvocationHandler(bp));
            //调用打印方法
            proxy.print();
        }
    }
    
    

    测试结果:

    JDK代理:方法执行前....
    这是一台黑色打印机....
    JDK代理:方法执行结束。
    

    CGlib动态代理

    使用CGlib动态代理规则

    1. 引入cglib-3.3.0.jar包
    2. 编写一个目标类
    3. 编写 MethodInterceptor 接口的实现类并重写 invoke 方法
    4. new Enhancer().create() 生成代理对象:
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(clazz);//目标类clazz
    enhancer.setCallback(this);//this 是 MethodInterceptor的实现类
    Object proxy = enhancer.create();//创建代理对象proxy 
    
    1. proxy 强制转换为 目标类类型,并调用目标类的方法。

    编码实现

    1. POM 引入cglib-3.3.0.jar包
     <!-- cglib jar  -->
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.3.0</version>
        </dependency>
    
    1. 编写一个目标类
    package com.black.design.pattern.proxy;
    
    /**
     * 目标类
     * @author black
     *
     */
    public class Target implements TargetInterface{
        public void doSomething() {
            System.out.println(" do something...");
        }
    
        public String doSomWork(String work) {
            System.out.println(" do " + work + "...");
            return "work done!";
        }
    }
    
    1. 编写 MethodInterceptor 接口的实现类并重写 invoke 方法
    package com.black.design.pattern.proxy.dynamic.cglib;
    
    import java.lang.reflect.Method;
    
    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    /**
     * cglib 动态代理
     * @author black
     *
     */
    public class CglibDynamicProxy implements MethodInterceptor{
    
        //获取代理实例
        public Object getInstance(Class<?> clazz) {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(clazz);//把目标类
            enhancer.setCallback(this);
            return enhancer.create();
        }
        
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            before();
            //调用代理类的方法
            Object resultObject =  proxy.invokeSuper(obj, args);
            after();
            return resultObject;
        }
        public void before() {
            System.out.println("CGlib代理:do before ...");
        }
        
        public void after() {
            System.out.println("CGlib代理:do after ...");
        }
        
    }
    

    编写测试类:

    package com.black.design.pattern.proxy.dynamic.cglib;
    
    import com.black.design.pattern.proxy.Target;
    
    /**
     * cglib 动态代理测试类
     * @author black
     *
     */
    public class CglibDynamicProxyTest{
    
        public static void main(String[] args) {
            CglibDynamicProxy proxy = new  CglibDynamicProxy();
            Target target = (Target)proxy.getInstance(Target.class);
            target.doSomWork("编写设计文档");
        }
    }
    
    

    测试结果:

    CGlib代理:do before ...
     do 编写设计文档...
    CGlib代理:do after ...
    

    手写JDK动态代理

    1. 保存 $Proxy0.class文件

    调试代码时经常看到 代理类的实现类是 $Proxy0 类,但是工程里又没有这个.class类文件,如下:
    image

    但是,工程下并没有 $Proxy0.class 文件,怎么能看到 $Proxy0.class 文件文件呢?
    参考两个博文:

    我这里选择:

    在调用Proxy.newProxyInstance之前,加一句System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");,就会在项目的根目录的com/sun/proxy文件夹下生成一个 $Proxy0.class

        //保存生成的$Proxy0.class文件
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
    
        Printer bp = new BlackPrinter();
        Class clazz = bp.getClass();
        //生成代理类
        Printer proxy= (Printer) Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), new JDKInvocationHandler(bp));
    //调用打印方法
        proxy.print();
    

    执行后,

    image

    经过测试,不同接口类会生成不同的$Proxy.class,只是序号不同,如下图:
    image

    2. 反编译 $Proxy0.class文件

    $Proxy0.class 反编译后:

    package com.sun.proxy;
    
    import com.black.design.pattern.proxy.blackproxy.Printer;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.lang.reflect.UndeclaredThrowableException;
    
    public final class $Proxy0
      extends Proxy
      implements Printer
    {
      private static Method m1;
      private static Method m3;
      private static Method m2;
      private static Method m0;
      
      public $Proxy0(InvocationHandler paramInvocationHandler)
      {
        super(paramInvocationHandler);
      }
      
      public final boolean equals(Object paramObject)
      {
        try
        {
          return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
        }
        catch (Error|RuntimeException localError)
        {
          throw localError;
        }
        catch (Throwable localThrowable)
        {
          throw new UndeclaredThrowableException(localThrowable);
        }
      }
      
      public final void print()
      {
        try
        {
          this.h.invoke(this, m3, null);
          return;
        }
        catch (Error|RuntimeException localError)
        {
          throw localError;
        }
        catch (Throwable localThrowable)
        {
          throw new UndeclaredThrowableException(localThrowable);
        }
      }
      
      public final String toString()
      {
        try
        {
          return (String)this.h.invoke(this, m2, null);
        }
        catch (Error|RuntimeException localError)
        {
          throw localError;
        }
        catch (Throwable localThrowable)
        {
          throw new UndeclaredThrowableException(localThrowable);
        }
      }
      
      public final int hashCode()
      {
        try
        {
          return ((Integer)this.h.invoke(this, m0, null)).intValue();
        }
        catch (Error|RuntimeException localError)
        {
          throw localError;
        }
        catch (Throwable localThrowable)
        {
          throw new UndeclaredThrowableException(localThrowable);
        }
      }
      
      static
      {
        try
        {
          m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
          m3 = Class.forName("com.black.design.pattern.proxy.blackproxy.Printer").getMethod("print", new Class[0]);
          m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
          m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
          return;
        }
        catch (NoSuchMethodException localNoSuchMethodException)
        {
          throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
        }
        catch (ClassNotFoundException localClassNotFoundException)
        {
          throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
        }
      }
    }
    
    
    

    $Proxy0 类实现了接口类,继承了Proxy;
    $Proxy0 类重写了 equalsprinttoStringhashCode 方法;

    3. 编写自己的动态代理类

    步骤:

    1. 编写一个 BlackInvocationHandler 类 替代 InvocationHandler 类
    2. 编写一个 BlackProxy 类 替代 Proxy 类
    3. BlackProxy.newProxyInstance 方法需要生成$Proxy0.java文件,进行编译后加载ClassLoader中
    4. 编写自己的类加载器

    编码实现

    1. 从 InvocationHandler 类 将invoke方法拷贝到 BlackInvocationHandler接口类中
    public interface BlackInvocationHandler {
    
        public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable;
    }
    

    编写一个 BlackInvocationHandlerImpl 实现类:

    package com.black.design.pattern.proxy.blackproxy;
    
    import java.lang.reflect.Method;
    // BlackInvocationHandler 的一个实现类
    public class BlackInvocationHandlerImpl implements BlackInvocationHandler {
        Object target;
    
        public BlackInvocationHandlerImpl(Object t) {
    
            this.target = t;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("black代理:方法执行前....");
            Object result = method.invoke(this.target, args);
            System.out.println("black代理:方法执行结束。");
            return result;
        }
    }
    
    
    1. 编写类加载器 BlackClassLoader,用于加载动态生成的$Proxy0.class代理文件
    package com.black.design.pattern.proxy.blackproxy;
    
    import java.io.ByteArrayOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    
    //自定义类加载器 
    public class BlackClassLoader extends ClassLoader {
    
        private File classPathFile;
    
        public BlackClassLoader() {
            String classpath = BlackClassLoader.class.getResource("").getPath();
            this.classPathFile = new File(classpath);
        }
    
        @Override
        public Class<?> loadClass(String name) throws ClassNotFoundException {
            if (classPathFile != null) {
    
                FileInputStream fi = null;
                ByteArrayOutputStream bo = null;
                // class 文件,路径
                File classFile = new File(classPathFile, name.replace("\.", "/") + ".class");
                if (classFile.exists()) {
                    try {
                        // 读取 class 文件
                        fi = new FileInputStream(classFile);
                        bo = new ByteArrayOutputStream();
                        byte[] bytes = new byte[1024];
                        int len;
                        while ((len = fi.read(bytes)) != -1) {
                            bo.write(bytes, 0, len);
                        }
                        // 委托父类加载器加载 class 文件
                        // 类名 com.black.design.pattern.proxy.blackproxy.$Proxy0
                        String className = BlackClassLoader.class.getPackage().getName() + "." + name;
                        // 委托父类加载器加载 class 文件,并返回 $Proxy0 的class对象
                        Class class1 = defineClass(className, bo.toByteArray(), 0, bo.size());
                        return class1;
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        try {
                            fi.close();
                        } catch (IOException e) {
                        }
                        try {
                            bo.flush();
                        } catch (IOException e) {
                        }
                        try {
                            bo.close();
                        } catch (IOException e) {
                        }
                    }
                }
            }
    
            return super.loadClass(name);
        }
    }
    
    
    1. 编写一个 BlackProxy 类 替代 Proxy 类
    package com.black.design.pattern.proxy.blackproxy;
    
    import java.io.File;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.lang.reflect.Constructor;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Modifier;
    import java.lang.reflect.UndeclaredThrowableException;
    import java.util.Arrays;
    
    import javax.tools.DiagnosticCollector;
    import javax.tools.JavaCompiler;
    import javax.tools.JavaCompiler.CompilationTask;
    import javax.tools.JavaFileObject;
    import javax.tools.StandardJavaFileManager;
    import javax.tools.ToolProvider;
    
    //代理类
    public class BlackProxy {
    
        private static String ln = "
    ";
    
        //私有构造方法,使用 newProxyInstance 创建代理类实例
        private BlackProxy() {
        }
    
        public static Object newProxyInstance(ClassLoader loader, Class<?>[] intfs, BlackInvocationHandler h)
                throws Exception {
            // 生成 $Proxy0 类
            Class<?> cl = getProxyClass0(loader, intfs, h);
            // 实例化 $Proxy0对象
            Constructor c = cl.getConstructor(BlackInvocationHandler.class);
            return c.newInstance(h);
        }
    
        // 获取 $Proxy0 类
        private static Class<?> getProxyClass0(ClassLoader loader, Class<?>[] interfaces, BlackInvocationHandler h)
                throws IOException, ClassNotFoundException {
    
            // 1.、生成 $Proxy0.java 文件
            String proxy0Path = createProxy0File(loader, interfaces, h);
            // 2、 编译 $Proxy0.java 为 $Proxy0.class
            compileProxy0(proxy0Path);
            // 3、加载到 ClassLoader 中,并获取 $Proxy0 的 class 对象
            Class proxy0Class = loadProxy0(proxy0Path);
            return proxy0Class;
        }
    
        // 生成 Proxy0.java 文件
        private static String createProxy0File(ClassLoader loader, Class<?>[] interfaces, BlackInvocationHandler h)
                throws IOException {
            // $Proxy0.java 文件内容
            String content = createProxy0FileContent(interfaces, h);
    
            // $Proxy0.java 文件存放路径
            Class blackProxyClass = BlackProxy.class;
            String blackProxyName = blackProxyClass.getName();
            String rootPath = loader.getResource("").getPath();
            String blackProxyPath = rootPath + File.separator
                    + blackProxyName.substring(0, blackProxyName.lastIndexOf(".")).replaceAll("\.", "/");
    
            // 生成文件
            File file = new File(blackProxyPath + File.separator + "$Proxy0.java");
            FileWriter writer = new FileWriter(file);
            writer.write(content);
            writer.flush();
            writer.close();
            // 返回 $Proxy0.java 文件存放路径
            return file.getAbsolutePath();
        }
    
        // 生成$Proxy0.java的内容
        private static String createProxy0FileContent(Class<?>[] interfaces, BlackInvocationHandler h) {
    
            StringBuilder sBuilder = new StringBuilder();
    
            Class<?> itf = interfaces[0];
            // 拼接包
            sBuilder.append(BlackProxy.class.getPackage()).append(";").append(ln);
            // 拼接import
            sBuilder.append("import java.lang.ClassLoader;").append(ln);
            sBuilder.append("import java.lang.Exception;").append(ln);
            sBuilder.append("import java.lang.reflect.*;").append(ln);
            sBuilder.append("import ").append(itf.getName()).append(";").append(ln);
    
            // 拼接类
            String handlerName = h.getClass().getInterfaces()[0].getName();
            sBuilder.append("public class $Proxy0 implements ").append(itf.getSimpleName());
            sBuilder.append(" {").append(ln);
            // 拼接属性 InvocationHandler h;
            sBuilder.append(handlerName + " h;").append(ln);
    
            // 拼接构造方法
            sBuilder.append(" public $Proxy0(").append(handlerName + " " + h.getClass().getSimpleName());
            sBuilder.append("){").append(ln);
            sBuilder.append("this.h = ").append(h.getClass().getSimpleName()).append(";").append(ln);
            sBuilder.append("}").append(ln);
    
            // 拼接实现接口的方法
            Method[] ms = itf.getMethods();
            for (int i = 0; i < ms.length; i++) {
                Method m = ms[i];
    
                // 方法修饰符
                int modfs = m.getModifiers();
                if (Modifier.isPublic(modfs)) {
                    sBuilder.append("public ");
                } else if (Modifier.isPrivate(modfs)) {
                    sBuilder.append("private ");
                } else if (Modifier.isProtected(modfs)) {
                    sBuilder.append("protected ");
                } else {
                    sBuilder.append(" ");
                }
    
                if (Modifier.isStatic(modfs)) {
                    sBuilder.append(" static ");
                }
                if (Modifier.isFinal(modfs)) {
                    sBuilder.append(" final ");
                }
                if (Modifier.isSynchronized(modfs)) {
                    sBuilder.append(" synchronized ");
                }
                // 方法返回类型
                String returnTypeName = m.getReturnType().getSimpleName();
                sBuilder.append(returnTypeName);
    
                // 方法名
                String mn = m.getName();
                sBuilder.append(" " + mn + "(");
                // 方法参数
                Class<?>[] prameterTypes = m.getParameterTypes();
                if (prameterTypes != null && prameterTypes.length > 0) {
                    for (int j = 0; j < prameterTypes.length; j++) {
                        Class pc = prameterTypes[j];
                        sBuilder.append(pc.getName() + " " + pc.getSimpleName());
                        if (j == prameterTypes.length - 1) {
                            sBuilder.append("");
                        } else {
                            sBuilder.append(",");
                        }
                    }
                }
                sBuilder.append(") ");
                // 方法体{}
                sBuilder.append("{").append(ln);
    
                // 真正调用方法
                if (mn.equals("toString")) {
                    //toString 方法
                    sBuilder.append("try
    " + "    {
    " + "Method realMethod = null;
    "
                            + "realMethod = Class.forName("java.lang.Object").getMethod("toString", new Class[0]); ");
                    sBuilder.append("return (String)this.h.invoke(this, realMethod, null);");
                    sBuilder.append("    }catch (Error|RuntimeException localError){
    " + "      throw localError;
    "
                            + "    } catch (Throwable localThrowable){
    "
                            + "      throw new UndeclaredThrowableException(localThrowable);
    " + "    }");
                } else if (mn.equals("hashCode")) {
                    //hashCode 方法
                    sBuilder.append("try
    " + "    {
    " + "Method realMethod = null;
    "
                            + "realMethod = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]); ");
                    sBuilder.append(ln);
                    sBuilder.append("return ((Integer)this.h.invoke(this, m0, null)).intValue();");
                    sBuilder.append(ln);
                    sBuilder.append("    }catch (Error|RuntimeException localError){
    " + "      throw localError;
    "
                            + "    } catch (Throwable localThrowable){
    "
                            + "      throw new UndeclaredThrowableException(localThrowable);
    " + "    }");
                } else if (mn.equals("equals")) {
                    //equals 方法
                    sBuilder.append("try
    " + "    {
    " + "Method realMethod = null;
    "
                            + "realMethod = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });");
                    sBuilder.append(ln);
                    sBuilder.append("return ((Boolean)this.h.invoke(this, m1, new Object[] { ");
    
                    if (prameterTypes != null && prameterTypes.length > 0) {
                        for (int j = 0; j < prameterTypes.length; j++) {
                            Class pc = prameterTypes[j];
                            sBuilder.append(pc.getSimpleName());
                            if (j != prameterTypes.length - 1) {
                                sBuilder.append(",");
                            }
                        }
                    }
    
                    sBuilder.append(" })).booleanValue();");
                    sBuilder.append(ln);
                    sBuilder.append("    }catch (Error|RuntimeException localError){
    " + "      throw localError;
    "
                            + "    } catch (Throwable localThrowable){
    "
                            + "      throw new UndeclaredThrowableException(localThrowable);
    " + "    }");
    
                } else {
                    // 实现接口的方法
                    sBuilder.append(
                            "try
    " + "    {
    " + "Method realMethod = null;
    " + "realMethod = Class.forName(""
                                    + itf.getTypeName() + "").getMethod("" + m.getName() + "", new Class[] { ");
                    for (int k = 0; k < prameterTypes.length; k++) {
                        sBuilder.append(prameterTypes[k].getTypeName());
                        if (k != prameterTypes.length - 1) {
                            sBuilder.append(",");
                        }
                    }
                    sBuilder.append("});
    ");
    
                    if (returnTypeName.equals("void")) {
                        sBuilder.append("this.h.invoke(this, realMethod, null);");
                    } else {
                        sBuilder.append("return ");
                        sBuilder.append("this.h.invoke(this, realMethod, new Object[]{");
                        if (prameterTypes != null && prameterTypes.length > 0) {
                            for (int j = 0; j < prameterTypes.length; j++) {
                                Class pc = prameterTypes[j];
                                sBuilder.append(pc.getSimpleName());
                                if (j != prameterTypes.length - 1) {
                                    sBuilder.append(",");
                                }
                            }
                        }
                        sBuilder.append("});");
    
                    }
    
                    sBuilder.append("    }catch (Error|RuntimeException localError){
    " + "      throw localError;
    "
                            + "    } catch (Throwable localThrowable){
    "
                            + "      throw new UndeclaredThrowableException(localThrowable);
    " + "    }");
                }
                sBuilder.append("}").append(ln);
            }
    
            sBuilder.append("} ").append(ln);
            return sBuilder.toString();
        }
    
        // 编译 $Proxy.java 生成 $Proxy.class 文件
        private static void compileProxy0(String proxy0Path) throws IOException {
            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
            DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
            StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null);
    //    	Iterable<? extends JavaFileObject> javaFileObjects = fileManager.getJavaFileObjects(new File(proxy0Path));
            Iterable<? extends JavaFileObject> javaFileObjects = fileManager
                    .getJavaFileObjectsFromStrings(Arrays.asList(proxy0Path));
            CompilationTask task = compiler.getTask(null, fileManager, diagnostics, null, null, javaFileObjects);
            task.call();
            fileManager.close();
        }
    
        // 使用自定义类加载器加载 $Proxy0 类
        private static Class loadProxy0(String proxy0Path) throws ClassNotFoundException {
            BlackClassLoader classLoader = new BlackClassLoader();
            return classLoader.loadClass("$Proxy0");
        }
    }
    

    在Java 代码中编译编译 Java 文件为 class 文件。可以参考这个博客 《java中的CompileAPI入门及使用》

    1. 编写 BlackProxyTest 测试类
    package com.black.design.pattern.proxy.blackproxy;
    
    import java.io.IOException;
    import java.lang.reflect.Proxy;
    
    import com.black.design.pattern.proxy.Target;
    import com.black.design.pattern.proxy.TargetInterface;
    // 测试类
    public class BlackProxyTest {
    
        public static void main(String[] args) {
            // 黑色打印机
            Printer bp = new BlackPrinter();
            Class clazz = bp.getClass();
            try {
                // 黑色打印机的代理类
                Printer printer = (Printer) BlackProxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(),
                        new BlackInvocationHandlerImpl(bp));
    			// 调用打印方法
                printer.print();
    
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    

    结果:

    black代理:方法执行前....
    这是一台黑色打印机....
    black代理:方法执行结束。
    
    1. 看看生成的 $Proxy0.java 和 $Proxy0.class 文件

    image

    $Proxy0.java 文件内容:

    package com.black.design.pattern.proxy.blackproxy;
    
    import java.lang.ClassLoader;
    import java.lang.Exception;
    import java.lang.reflect.*;
    import com.black.design.pattern.proxy.blackproxy.Printer;
    
    public class $Proxy0 implements Printer {
        com.black.design.pattern.proxy.blackproxy.BlackInvocationHandler h;
    
        public $Proxy0(com.black.design.pattern.proxy.blackproxy.BlackInvocationHandler BlackInvocationHandlerImpl) {
            this.h = BlackInvocationHandlerImpl;
        }
    
        public void print() {
            try {
                Method realMethod = null;
                realMethod = Class.forName("com.black.design.pattern.proxy.blackproxy.Printer").getMethod("print",
                        new Class[] {});
                this.h.invoke(this, realMethod, null);
            } catch (Error | RuntimeException localError) {
                throw localError;
            } catch (Throwable localThrowable) {
                throw new UndeclaredThrowableException(localThrowable);
            }
        }
    }
    
    

    结束。

    本文来自博客园,作者:不安分的黑娃,转载请注明原文链接:https://www.cnblogs.com/lihw-study/p/15120748.html

  • 相关阅读:
    初来乍到
    OpenGl基础篇(1.0)
    说说结构化方法和面向对象方法
    浅谈软件项目管理
    测试篇
    结构化与面向对象化之应用比较
    敏捷软件开发VS传统软件开发
    SOSO街景地图 API (Javascript)开发教程(1)- 街景
    阿里实习内推面经
    Android工程开发笔记<一>
  • 原文地址:https://www.cnblogs.com/lihw-study/p/15120748.html
Copyright © 2011-2022 走看看