不安分的黑娃
踏踏实实,坚持学习,慢慢就懂了~

设计模式-代理模式

代理模式:

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

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

属于结构型设计模式。

使用场景

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

静态代理

代码示例:

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 文件文件呢?
参考两个博文:

  • java动态代理 $Proxy0 源码分析

  • [获得JDK动态代理生成类\(Proxy0的内容](https://blog.csdn.net/u012736913/article/details/87098795 "获得JDK动态代理生成类\)Proxy0的内容" )

我这里选择:

在调用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 = "\r\n";

    //私有构造方法,使用 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\r\n" + "    {\r\n" + "Method realMethod = null;\r\n"
                        + "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){\r\n" + "      throw localError;\r\n"
                        + "    } catch (Throwable localThrowable){\r\n"
                        + "      throw new UndeclaredThrowableException(localThrowable);\r\n" + "    }");
            } else if (mn.equals("hashCode")) {
                //hashCode 方法
                sBuilder.append("try\r\n" + "    {\r\n" + "Method realMethod = null;\r\n"
                        + "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){\r\n" + "      throw localError;\r\n"
                        + "    } catch (Throwable localThrowable){\r\n"
                        + "      throw new UndeclaredThrowableException(localThrowable);\r\n" + "    }");
            } else if (mn.equals("equals")) {
                //equals 方法
                sBuilder.append("try\r\n" + "    {\r\n" + "Method realMethod = null;\r\n"
                        + "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){\r\n" + "      throw localError;\r\n"
                        + "    } catch (Throwable localThrowable){\r\n"
                        + "      throw new UndeclaredThrowableException(localThrowable);\r\n" + "    }");

            } else {
                // 实现接口的方法
                sBuilder.append(
                        "try\r\n" + "    {\r\n" + "Method realMethod = null;\r\n" + "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("});\r\n");

                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){\r\n" + "      throw localError;\r\n"
                        + "    } catch (Throwable localThrowable){\r\n"
                        + "      throw new UndeclaredThrowableException(localThrowable);\r\n" + "    }");
            }
            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);
        }
    }
}

结束。

posted on 2021-08-16 23:03  不安分的黑娃  阅读(28)  评论(0编辑  收藏  举报