大话java之JDK动态代理

本文介绍了Java动态代理的基本概念,通过示例展示了如何使用JDK动态代理实现方法调用的记录和耗时统计,并解释了动态代理相较于静态代理的优势。

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

上一篇讲到到java的代理模式以及java的静态代理的实现方式。静态代理的问题在于需要为每个委托类建立一个代理类,这样不仅耗费大量的精力,也不利于项目的解耦和维护。本篇就要讲讲java的动态代理,动态代理在spring等框架中十分重要,它不仅保留代理模式的优点,也更好地解耦项目,对于代码的复用和维护都是更有优势。

1.动态代理的简单例子

1)委托类接口

//委托类接口
public interface TestService {

    void business();

}

2)委托类的实现

//委托类的实现类
public class TestImplement implements TestService{

    @Override
    public void business() {
        try{
            System.out.println("do the busniess");
            Thread.sleep(200);
        }catch (Exception e) {
            e.printStackTrace();
        }

    }

}

3)处理类(和静态代理很大的区别就是处理类更通用)

public class LoggerInvocationHandler implements InvocationHandler {

    private Object target;// 目标类

    public LoggerInvocationHandler(Object target) {
        this.target = target;
    }

    //这是一个简单的日志处理类,会记录方法的执行时间和耗时
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Long timeStart = System.currentTimeMillis();
        System.out.println("-- invoke start---timeStart="+timeStart);
        Object result = method.invoke(this.target, args);
        System.out.println("-- invoke finish---takes="+(System.currentTimeMillis()-timeStart));//记录方法的调用耗时
        return result;
    }

}

4)测试代码

        TestService target = new TestImplement();
        LoggerInvocationHandler myInterceptor = new LoggerInvocationHandler(target);
        TestService proxyObj =  (TestService) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), myInterceptor);  
        proxyObj.business();  

运行结果:

– invoke start—timeStart=1504015240306
do the busniess
– invoke finish—takes=201

这就是动态代理的一个简单的例子,它能记录方法执行的时间和耗时,并且LoggerInvocationHandler.class是通用的。

2.动态代理的原理

首先我们从入口开始看

        TestService proxyObj =  (TestService) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), myInterceptor);  

点击进入Proxy.newProxyInstance()方法,先看下注释

    /**
     * Returns an instance of a proxy class for the specified interfaces
     * that dispatches method invocations to the specified invocation
     * handler.
     *
     * <p>{@code Proxy.newProxyInstance} throws
     * {@code IllegalArgumentException} for the same reasons that
     * {@code Proxy.getProxyClass} does.
     *
     * @param   loader the class loader to define the proxy class
     * @param   interfaces the list of interfaces for the proxy class
     *          to implement
     * @param   h the invocation handler to dispatch method invocations to
     * @return  a proxy instance with the specified invocation handler of a
     *          proxy class that is defined by the specified class loader
     *          and that implements the specified interfaces

从注释可以看出这个方法,是给指定接口的代理类生成实例。比如我们前面传入的是TestService,那么就是返回TestService的代理类。这就是动态代理和静态代理的区别,静态代理需要我们自己写代理类,而动态代理是动态生成的。

更详细的动态代理原理可以参考 终点的博客

以上的动态代理方式委托类必须是接口,一般称作JDK动态代理。那么委托类如果不是接口该怎么办?这就需要CGLIB等方式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值