JDK动态代理

JDK动态代理是面向接口的。这是很多框架的基础。

JDK动态代理的原理是接口的实现, 所以接口一定要存在, 而且只能代理接口存在的方法.

首先动态代理类要实现InvocationHandler接口,该接口只有一个方法。

public Object invoke(Object proxy, Method method, Object[] args)
// proxy 参数是代理对象本身,在整个动态代理实现的过程中没有用到。
// method是代理对象调用的方法,args是方法的参数

需求:现在有一个房东host要出租房子,但是自己又非常懒,不想自己带人看房,议价之类,所以想让中介帮其租房子,此时中介就是个代理。

由于JDK动态代理是面向接口的,所以先有一个Rent接口代表出租的动作。

package com.ldt.pojo;

public interface Rent {
    void rent();
}

再有一个房东。

package com.ldt.pojo;

public class Host implements Rent{
    @Override
    public void rent() {
        System.out.println("房东要把房子租出去");
    }
}

再有一个动态代理类。

package com.ldt.pojo;

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

public class ProxyInvocationHandler implements InvocationHandler {

    // 被代理的接口
    private Object target;

    public void setTarget(Object target) {
        this.target = target;
    }

    // 动态生成代理类
    public Object getProxy() {
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }

    // 处理代理实例,并返回结果
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        seeHouse();
        Object result = method.invoke(target, args);
        hetong();
        return result;
    }

    private void seeHouse() {
        System.out.println("中介带看房子");
    }

    private void hetong() {
        System.out.println("签合同");
    }
}

需要注意的是Proxy.newProxyInstance方法,该方法是动态生成代理对象的,第一个参数是classloader,第二个参数是要代理的类的接口,此处是Rent接口,第三个参数是handler对象本身。可以看出handler类并不是代理类,只是生成代理需要的一个元素,我们实现的invoke方法也不是代理类的方法,而是代理类要调用的方法,就是说代理类中会调用handler.invoke方法。

开始测试:

这里有一个client要来租房子。

package com.ldt.pojo;

public class Client {
    public static void main(String[] args) {
        Host host = new Host();
        ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();
        proxyInvocationHandler.setTarget(host);
        // 生成代理类
        Rent proxy = (Rent) proxyInvocationHandler.getProxy();
        // 调用代理类的rent方法,就是这个方法中调用了handler的invoke方法
        proxy.rent();
    }
}

由于代理对象是动态生成的,如何通过调用rent方法进而调用invoke不是一个显示的过程,但是查看源码可以知道,Proxy.newProxyInstance方法在生成代理对象时,动态的实现了rent方法,并且在rent方法中调用了handler的invoke方法。

posted @   远大光明  阅读(46)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
点击右上角即可分享
微信分享提示