JDK动态代理的实现----详细易懂

JDK动态代理的实现----详细易懂

场景

假设A原本只负责做两件事情doLogin()doLogout(),后来需要A在doLogin()前后都要打印一次日志,但是这不是A要负责的业务范围,于是A就找来B,他俩就签订了一份协议(告诉代理类我的哪些方法需要被代理、增强),让B来完成doLogin()并且前后打印日志。

在这个场景中,B代理了A的doLogin 业务,并对业务进行了增强。A就是被代理类,B就是代理类,那份协议就是我们要定义的接口(interface);

下面就根据这个场景实现动态代理

代码实现

1.根据上面的场景,我们先把接口(协议)定义出来:

//定义接口,指明需要代理的方法
public interface Subject {
    void doLogin();
}

2. 让A实现接口Subject,

public class A implements Subject{    
    @Override    
    public void doLogin() {        
        System.out.println("doLogin>>>>>>>>>>>>>>>");    
    }
    
    public void doLogout(){        
        System.out.println("doLogout>>>>>>>>>>>>>");    

    }
}

3. 重点来了,接下来我们需要实现InvocationHandler接口,它是代理逻辑执行器,不是代理类,它的作用是实现代理类的逻辑:

在这里插入图片描述

至于为什么要实现这个接口,可以看一下:jdk动态代理源码解析;

有一些刚刚了解动态代理的小伙伴会把这个实现类误当做是代理类,InvocationHandler的实现类就是用来实现代理逻辑的,通过重写invoke()方法,对被代理的方法进行增强(比如:上面代码中,我们可以在执行代理方法前后加入其他业务逻辑)。

4. 获取代理对象:

为了便利,我将获取代理对象的业务封装了一个类,通过静态方法getProxy()获取代理对象:

通过java.lang.reflect.Proxy的静态方法newProxyInstance(...)获取我们想要的代理对象

newProxyInstance()需要的参数如下:

在这里插入图片描述

ClassLoader loader:类加载器;

Class<?>[] interfaces:代理类需要实现的接口集合(就是被代理类实现的接口);

InvocationHandler h:代理类会根据传进来的接口去实现需要实现的接口方法,但是接口方法的内部逻辑需要依赖InvocationHandler(就是上面实现InvocationHandler接口的类的invoke()中的内容);

5. 测试

在这里插入图片描述

上面代码中proxy就是A的代理对象,并且通过idea的提示可以看到,proxy只能调用doLogin()方法,并没有doLogout()方法,原因就是我们在接口(协议)中只定义了doLogin()方法(在这里之所以多说这么一句,是因为我在放学习jdk动态代理时出现过的疑问:怎么控制被代理类中的哪些方法需要被代理增强?原因就在这);

执行结果:
在这里插入图片描述

6.总结

实现JDK的动态代理功能主要步骤:

1). 分析业务场景,确定被代理类的业务需要和要被代理增强的方法;

2). 被代理类至少要实现一个接口,并且该接口中定义了需要被代理的方法;

3). 通过实现InvocationHandler接口并重写invoke()方法来实现被代理方法的业务扩展;

4). 通过java.lang.reflect.Proxy类的静态方法newProxyInstance()获取代理对象;
(以上内容有不足的地方欢迎大佬们指正,感谢!)

接下来这篇文章是对Proxy.newProxyInstance源码的分析

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值