Java动态代理

1 Java动态代理

1.1 代理模式

1.2 静态代理

package com.cl.dynamicproxy;

import com.cl.utils.TimeUtils;

/**
 * @Author chenlan
 * @Date 2020/10/11 14:13
 * @Description 静态代理的实现:
 *
 *  需求:创建代理对象,代理学生上交学费
 *
 *  01 目标对象与代理对象应该具备相同的功能(公共接口、抽象主体)
 *      class Student implements IPerson{}
 *      class StudentProxy implements IPerson{}
 *
 *  02  代理对象应该持有目标对象的引用,可以随意的访问目标对象
 *      (mybatis dao的实现类、动态代理处理事务、动态代理处理日志、动态代理处理连接,动态代理计算程序的执行时间)
 *      private IPerson student;
 *
 *  03  代理对象相对于目标对象来说可以扩展功能
 *
 *  04  目标对象不直接依赖客户,依赖代理对象即可,降低了耦合度
 *
 *      实际开发中,dao接口有很多的实现类,使用静态代理要分别去写他们的代理对象,会使代理类暴增
 *      所以我们希望在程序运行时动态代理
 */
public class DynamicProxyDemo {
    public static void main(String[] args) {
        // 创建真实对象
        IPerson student = new Student("alex");
        student.payMoney();
        System.out.println(student.add(1, 100));

        System.out.println("-------------------");

        // 创建代理对象
        StudentProxy studentProxy = new StudentProxy(student);
        studentProxy.payMoney();
        System.out.println(studentProxy.add(1, 100));


    }
}

/**
 * 定义抽象主体[公共接口]
 */
interface IPerson {

    void payMoney();

    long add(int m, int n);
}

/**
 * 定义目标对象,即真实对象
 */
class Student implements IPerson {

    private String name;

    public Student() {
    }

    public Student(String name) {
        this.name = name;
    }

    @Override
    public void payMoney() {
        System.out.println(this.name + "上交学费");
    }

    @Override
    public long add(int m, int n) {
        int sum = 0;
        for (int i = m; i <= n; i++) {
            sum += i;
        }
        return sum;
    }
}

class StudentProxy implements IPerson {

    private IPerson student;

    public StudentProxy(IPerson student) {
        if (student instanceof Student) {
            this.student = student;
        }
    }

    @Override
    public void payMoney() {
        this.prePay();
        student.payMoney();
        this.postPay();
    }

    public void prePay() {
        System.out.println("StudentProxy.prePay");
    }

    public void postPay() {
        System.out.println("StudentProxy.postPay");
    }

    @Override
    public long add(int m, int n) {
        TimeUtils.start();
        long addVar = student.add(m, n);
        TimeUtils.finish("add");
        return addVar;
    }
}

1.3 动态代理

1.4 动态代理原理分析

package com.cl.dynamicproxy;

import sun.misc.ProxyGenerator;

import java.io.FileOutputStream;
import java.io.IOException;

/**
 * @Author chenlan
 * @Date 2020/10/11 14:54
 * @Description 动态代理的实现
 *
 * 三个角色
 * 抽象主体(最核心)
 * 目标对象
 * 代理对象
 *
 * jdk提供生成代理的方法
 */
public class DynamicProxyDemo2 {

    public static void main(String[] args) {
        byte[] bytes = ProxyGenerator.generateProxyClass("$Proxy0", Student.class.getInterfaces());
        try (FileOutputStream fos = new FileOutputStream("e:\\test\\StudentProxy.class")) {
            fos.write(bytes);
            fos.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Student代理对象源码:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

import com.cl.dynamicproxy.IPerson;
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 IPerson {

    private static Method m1;  // equals方法
    private static Method m2;  // toString方法
    private static Method m3;  // add方法
    private static Method m4;  // payMoney方法
    private static Method m0;  // hashCode方法


     // 反射获取目标对象的同名方法
     static {
            try {
                m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
                m2 = Class.forName("java.lang.Object").getMethod("toString");
                m3 = Class.forName("com.cl.dynamicproxy.IPerson").getMethod("add", Integer.TYPE, Integer.TYPE);
                m4 = Class.forName("com.cl.dynamicproxy.IPerson").getMethod("payMoney");
                m0 = Class.forName("java.lang.Object").getMethod("hashCode");
            } catch (NoSuchMethodException var2) {
                throw new NoSuchMethodError(var2.getMessage());
            } catch (ClassNotFoundException var3) {
                throw new NoClassDefFoundError(var3.getMessage());
            }
        }

    // 当外界调用该构造方法的时候,需要传入一个InvocationHandler接口
    // 反射创建该对象的时候会传入该对象的实现类
    public $Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }


    public final long add(int var1, int var2) throws  {
            try {
                /**
                 * h:   外界传递过来的InvocationHandler
                 * h.invoke:   本质是外界传递过来的InvocationHandler.invoke
                 * @param this:   动态代理对象
                 * @param m3:  add方法
                 * @param new Object[]{var1, var2}:  参数
                 */
                return (Long)super.h.invoke(this, m3, new Object[]{var1, var2});
            } catch (RuntimeException | Error var4) {
                throw var4;
            } catch (Throwable var5) {
                throw new UndeclaredThrowableException(var5);
            }
     }

    public final boolean equals(Object var1) throws  {
        try {
            return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }


    public final void payMoney() throws  {
        try {
            super.h.invoke(this, m4, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final int hashCode() throws  {
        try {
            return (Integer)super.h.invoke(this, m0, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }


}

Proxy类部分源码:

public class Proxy implements java.io.Serializable {


    protected InvocationHandler h;

    protected Proxy(InvocationHandler h) {
            Objects.requireNonNull(h);
            this.h = h;
        }

    // 创建代理类对应的class对象,有了class对象就能够通过反射创建代理对象

    public static Class<?> getProxyClass(ClassLoader loader,
                                             Class<?>... interfaces)
            throws IllegalArgumentException
        {
            final Class<?>[] intfs = interfaces.clone();
            final SecurityManager sm = System.getSecurityManager();
            if (sm != null) {
                checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
            }

            return getProxyClass0(loader, intfs);
        }


     public static Object newProxyInstance(ClassLoader loader,
                                              Class<?>[] interfaces,
                                              InvocationHandler h)
            throws IllegalArgumentException
        {
            Objects.requireNonNull(h);

            final Class<?>[] intfs = interfaces.clone();
            final SecurityManager sm = System.getSecurityManager();
            if (sm != null) {
                checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
            }

            /*
             * Look up or generate the designated proxy class.
             */
            Class<?> cl = getProxyClass0(loader, intfs);

            /*
             * Invoke its constructor with the designated invocation handler.
             */
            try {
                if (sm != null) {
                    checkNewProxyPermission(Reflection.getCallerClass(), cl);
                }

                final Constructor<?> cons = cl.getConstructor(constructorParams);
                final InvocationHandler ih = h;
                if (!Modifier.isPublic(cl.getModifiers())) {
                    AccessController.doPrivileged(new PrivilegedAction<Void>() {
                        public Void run() {
                            cons.setAccessible(true);
                            return null;
                        }
                    });
                }
                return cons.newInstance(new Object[]{h});
            } catch (IllegalAccessException|InstantiationException e) {
                throw new InternalError(e.toString(), e);
            } catch (InvocationTargetException e) {
                Throwable t = e.getCause();
                if (t instanceof RuntimeException) {
                    throw (RuntimeException) t;
                } else {
                    throw new InternalError(t.toString(), t);
                }
            } catch (NoSuchMethodException e) {
                throw new InternalError(e.toString(), e);
            }
        }


}


interface InvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable;
}



实现动态代理:

package com.cl.dynamicproxy;

import com.cl.utils.TimeUtils;

import java.lang.reflect.*;

/**
 * @Author chenlan
 * @Date 2020/10/11 14:54
 * @Description 动态代理的实现
 *
 */
public class DynamicProxyDemo4 {

    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Student student = new Student("coco");
        // 创建动态代理类对应的class对象

        /**
         * @params ClassLoader loader 类加载器:这里使用加载Strudent类的加载器来加载代理类(将代理类装载到内存)
         * @params Class<?>... interfaces :用来创建代理类
         */
        final Class<?> proxyClass = Proxy.getProxyClass(Student.class.getClassLoader(), Student.class.getInterfaces());
        final Constructor<?> conn = proxyClass.getDeclaredConstructor(InvocationHandler.class);
        final IPerson s = (IPerson) conn.newInstance(new MyInvocationHandler<Student>(student));
        s.payMoney();
        System.out.println(s.add(1, 100));

    }


}

// 代理过程

class MyInvocationHandler<Student> implements InvocationHandler{

    // 持有目标对象的引用

    private Student student;

    public MyInvocationHandler(Student student) {
        this.student = student;
    }

    /**
     *
     * @param proxy  代理对象
     * @param method 实际上调用的方法
     * @param args 参数
     * @return  最终返回给代理对象的调用者
     * @throws Throwable
     *
     * 代理对象调用方法 -> 触发invoke方法 -> 传递参数(实际上调用目标对象的同名方法) -> 返回值给代理对象 -> 代理对象返回给代理对象的调用者
     */

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        final String methodName = method.getName();
        Object result = null;
        switch (methodName) {
            case "payMoney":
                System.out.println("prePay");
                result = method.invoke(student, args);
                System.out.println("postPay");
                break;
            case "add":
                TimeUtils.start();
                result = method.invoke(student, args);
                TimeUtils.finish("add");
                break;
        }
        return result;
    }
}

实现动态代理:

package com.cl.dynamicproxy;

import com.cl.utils.TimeUtils;
import sun.misc.ProxyGenerator;

import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @Author chenlan
 * @Date 2020/10/11 14:54
 * @Description 动态代理的实现
 *
 */
public class DynamicProxyDemo3 {

    public static void main(String[] args) {
        Student student = new Student("coco");
        final IPerson proxy = (IPerson) Proxy.newProxyInstance(Student.class.getClassLoader(), Student.class.getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                final String methodName = method.getName();
                Object result = null;
                switch (methodName) {
                    case "payMoney":
                        System.out.println("prePay");
                        result = method.invoke(student, args);
                        System.out.println("postPay");
                        break;
                    case "add":
                        TimeUtils.start();
                        result = method.invoke(student, args);
                        TimeUtils.finish("add");
                        break;
                }
                return result;
            }
        });

        proxy.payMoney();
        System.out.println(proxy.add(1, 100));
    }


}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值