欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

动态代理的实现方式

程序员文章站 2022-06-17 20:21:48
...

动态代理是一个设计模式,大多数老师都不会讲的,需要自己去寻找答案,我就是自己去找到的答案,现在分享给大家!
动态代理的定义:
为其它对象提供一种代理以控制对这个对象的访问控制;在某些情况下,客户不想或者不能直接引用另一个对象,这时候代理对象可以在客户端和目标对象之间起到中介的作用。
从定义里面我们可以了解到动态代理有三个角色,一个是客户对象,一个是代理对象,一个是另一个对象。
程序源于生活,我们使用例子来了解印象会更加深刻:
一个客户需要一台电脑,我们假设这台电脑价格是一万块钱,客户不会自己生产电脑的,所有我们需要一个生产者厂家,刚开的时候业务不是很多,厂家完全可以应付电脑的销售和售后,渐渐地业务扩大了,生产的厂家应付不过来了,就这样代理商顺应市场的发展登场了。这里再给大家画一个图,我不是专业的画家,画不好还请体谅一下;
动态代理的实现方式
现在我们流程思路理解清楚了,那我们就可以开始写代码了:
生产电脑的厂家:

package org.news.proxy;

/**
 * @author think
 * 生产电脑的厂家
 * @Date 2020/5/16
 */
public class Producer implements IProducer{

    /**
     * 销售
     * @param money
     */

    @Override
    public void saleProduct(float money) {
        System.out.println("销售产品,并拿到钱:"+money);
    }

    /**
     * 售后
     * @param money
     */

    @Override
    public void afterService(float money) {
        System.out.println("提供稍后服务:并拿到钱:"+money);
    }
}


你以为那个接口是代理吗?那你太天真了。。。
这里是对生产厂家要求的接口,电脑的销售和售后:

package org.news.proxy;

/**
 *
 * @author think
 * 对生产厂家要求的接口
 * @Date 2020/5/16
 */
public interface IProducer {

    /**
     * 销售
     * @param money
     */
    public void saleProduct(float money);

    /**
     * 售后
     * @param money
     */
    public void afterService(float money);

}

第三个是客户类:

package org.news.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author think
 * 客户类
 * @Date 2020/5/16
 */
public class Client {

    public static void main(String[] args) {

        final Producer producer = new Producer();

        // producer.saleProduct(10000f);

        /**
         * 动态代理的:
         * 特点:字节码随用随创建,随用随加载
         * 作用:不修改源码的基础上对方法增强
         * 分类:
         *      基于接口的动态代理
         *      基于子类的动态代理
         * 基于接口的动态代理:
         *          涉及的类:Proxy
         *          提供者:JDK官方
         * 如何创建代理对象:
         *          使用Proxy类中的newProxyInstance方法
         *  创建代理对象的要求:
         *      被代理类最少实现一个借口,如果没有则不能使用
         *   newProxyInstance方法的参数:
         *              ClassLoder:  类加载器
         *                      它是用于加载代理对象字节码的,和被代理对象使用相同的类加载器
         *                      代理谁就,谁.getClass().getClassLoader()固定写法
         *              Class[] :字节码数组
         *                      它是用于让代理对象和被代理对象有相同方法
         *                      代理了谁,谁.getClass().getInterfaces(),也是固定的写法
         *              InvocationHandler: 用于提供增强的代码
         *                      它是让我们如何代理,我们一般都是些一个该接口的实现类,通常情况下都是匿名内部类,但不是必须的。
         *                      此接口的实现类都是谁用谁写。
         */
        IProducer proxyProducer = (IProducer) Proxy.newProxyInstance(producer.getClass().getClassLoader(), producer.getClass().getInterfaces(),
                new InvocationHandler() {
                    /**
                     * 作用:执行被代理对象的任何接口方法都会经过该方法
                     * 方法参数的含义
                     * @param proxy 代理对象的引用
                     * @param method  当前执行的方法
                     * @param args    当前执行方法所需的参数
                     * @return         和被代理对象有相同的返回值
                     * @throws Throwable
                     */
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        //提供增强的代码
                        Object returnValue=null;
                        //1、获取执行方法的参数
                        Float money = (Float) args[0];
                        //2、判断当前方法是不是销售
                        if ("saleProduct".equals(method.getName())){
                            returnValue= method.invoke(producer,money*0.4f);
                        }
                        return returnValue;
                    }
                });
        proxyProducer.saleProduct(10000f);
    }
}

这样运行之后就可以看到代理商拿到了4000块钱了。
动态代理的实现方式
学到的朋友麻烦点个赞!你的支持是我最大的动力!

相关标签: 笔记 设计模式