23种设计模式之jdk动态代理设计模式实战

本文介绍了如何使用JDK动态代理来计算一个类中每个被调用方法的运行时长。首先定义了一个IProduct接口及其实现类Product,接着创建了一个抽象调用处理器MyHandler和其具体实现类CalcTimeHandler,用于动态计算方法执行时间。最后通过MyJdkProxyFactory静态工厂创建了代理对象,并在客户端调用中无感地实现了方法增强。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

JDK中的动态代理是通过反射类Proxy以及InvocationHandler回调接口实现的;
JDK中所要进行动态代理的类必须要实现一个接口
需求:
计算一个类中,每个被调用的方法运行时长

二、具体代码

1.定义接口IProduct

package design.patterns.proxy;

public interface IProduct {
    String sell(Float money);
    void afterSell();
}

2.定义实现类Product

package design.patterns.proxy;

import java.util.concurrent.TimeUnit;

public class Product implements IProduct {
    @Override
    public String sell(Float money) {
        System.out.println("代理员交给工厂:" + money);
        return "aaa";
    }

    @Override
    public void afterSell() {
        System.out.println("代理员做售后。。等待5秒");
        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (Exception ignore) {

        }
    }
}

3.定义抽象调用处理器

package design.patterns.proxy;

import java.lang.reflect.InvocationHandler;

/**
 * 类名: MyHandler
 * 描述: 添加获取目标实例的方法
 * 日期: 2022/6/28-14:08
 */
public abstract class MyHandler<T> implements InvocationHandler {
    protected T targetInstance;

    public MyHandler(T targetInstance) {
        this.targetInstance = targetInstance;
    }

    public T getTargetInstance() {
        return targetInstance;
    }
}

4.定义调用实际处理器实现类

动态计算方法运行时长

package design.patterns.proxy;

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

/**
 * 类名: CalcTimeHandler
 * 描述: 动态计算方法运行时长
 * 日期: 2022/6/28-10:59
 */
public class CalcTimeHandler<T> extends MyHandler<T> implements InvocationHandler {

    public CalcTimeHandler(T targetInstance) {
        super(targetInstance);
    }


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //这些方法不进行增强处理控制 //边界判断
        if ("equals getClass hashCode toString wait notifyAll".contains(method.getName())) {
            return method.invoke(targetInstance, args);
        }
        long startTime = System.currentTimeMillis();
        Object invoke = method.invoke(targetInstance, args);
        long end = System.currentTimeMillis();
        System.out.format("%s方法执行时间:%s毫秒%n", method.getName(), end - startTime);
        return invoke;
    }
}

5.定义jdk动态代理工厂

该静态工厂使用的是泛型类

package design.patterns.proxy;

import design.patterns.decorate.CalcTimeHandler;

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

/**
 * 类名: MyJdkProxyFactory
 * 描述:
 * 日期: 2022/6/27-17:25
 *
 */
public class MyJdkProxyFactory {
    /**
     * 泛型静态工厂方法:
     * 被代理的对象一定要实现一个接口
     * @param interfaces
     *              被代理对象实例.getClass().getInterfaces()
     * @param handler
     *             {@link InvocationHandler} 接口的实现类
     * @param <T>
     * @return
     */
    private static <T> T getProxy(Class<?>[] interfaces, InvocationHandler handler) {
        return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), interfaces, handler);
    }
    /**
     *   对 {@link #getProxy(Class[], InvocationHandler)} 方法的简化
     *   增加了一层抽象父类,以方便获取目标实例的class对象 方便扩展
     *  泛型静态工厂方法:
     * 被代理的对象一定要实现一个接口
     * @param handler {@link MyHandler} 接口的实现类
     * @param <T>
     * @return
     */
    private static <T> T getProxy(MyHandler handler) {
        return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), handler.getTargetInstance().getClass().getInterfaces(), handler);
    }

    private static <T> T getProxy2(MyHandler handler) {
        return (T) Proxy.newProxyInstance(handler.getClass().getClassLoader(), handler.getTargetInstance().getClass().getInterfaces(), handler);
    }

}

客户端调用


    public static void main(String[] args) {
        IProduct product = new Product();
        IProduct productProxy = MyJdkProxyFactory.getProxy(new CalcTimeHandler<>(product));
        //无感地对代码进行了动态的增强控制
        //调用代理实例的方法对原实例进行动态增强
        System.out.println(productProxy.sell(3f));
        productProxy.afterSell();

        System.out.println(productProxy.hashCode());
        System.out.println(product.hashCode());
    }

在这里插入图片描述


总结

提示:这里对文章进行总结:

在不改变原有代码的基础上对代理对象的方法进行了动态的增强
核心代码逻辑:对代理对象的每个方法进行计算方法调用运行时长
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值