代理模式--动态代理--jdk代理

动态代理

jdk代理--基于接口代理

cglib--基于类代理

javassist --基于字节码

一个jdk动态代理类代理的是一个接口,一般归属于一个业务。在不改动源代码的同时可以很方便的低成本的进行加工附属改造。

jdk代理主要是通过java.lang.reflect 包中的 Proxy类 和 InvacationHandler接口,实现的。首先看下这两个类的源码。

InvacationHandler interface

public interface InvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;
}

只有一个invoke 方法。这个方法是处理代理实例并返回结果。在里面要用反射方法调用,method.invoke(Object obj ,Object[] args) 第一个参数就是要代理的接口类。第二个就是对应方法有关的参数。

回到源代码,第一个参数理论上就是要代理的对象,但是实际上并没有用到,第二个就是接口中对应的方法,第三个就是对应的参数。

其次看Proxy类

里面包含着一个重要也是常用的方法

    @CallerSensitive
    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)

获得一个对应代理类的实例。通常要用这个方法动态的获得代理实例。

使用jdk代理的步骤

1.创建一个实现接口InvocationHandler的类,它必须实现invoke方法
2.创建被代理的类以及接口
3.通过Proxy的静态方法
newProxyInstance(ClassLoaderloader, Class[] interfaces, InvocationHandler h)创建一个代理
4.通过代理调用方法
实现代码:

真实角色(要被代理的对象):

package com.heaboy.proxyExcise.JDkProxy;

/**
 * @Author:XK
 * @Date: Created in 11:23 2022/2/19
 * @Description:
 **/
public class Host implements Rent {

    @Override
    public void rent() {
        System.out.println("房东出租房子");
    }

    @Override
    public void run() {
        System.out.println("房东跑了");
    }
}

抽象角色(要被代理的接口)

package com.heaboy.proxyExcise.JDkProxy;

/**
 * @Author:XK
 * @Date: Created in 11:20 2022/2/19
 * @Description:
 **/
public interface Rent {
    public void rent();
    public void run();
}

继承InvacationHanler并动态生成代理对象的角色

package com.heaboy.proxyExcise.JDkProxy;

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

/**
 * @Author:XK
 * @Date: Created in 15:45 2022/2/19
 * @Description:
 **/
public class RentProxy implements InvocationHandler {

    private Rent target;

    public  RentProxy(Rent 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);
        fare();
        return result;
    }
    public void seeHouse(){
        System.out.println("中介带你去看房");
    }
    public void fare(){
        System.out.println("中介带你收费");
    }
}

客户角色;调用代理

package com.heaboy.proxyExcise.JDkProxy;
/**
 * @Author:XK
 * @Date: Created in 15:52 2022/2/19
 * @Description:
 **/
public class client {
    public static void main(String[] args) {
        Host host = new Host();

        RentProxy rentProxy = new RentProxy(host);

        Rent proxy = (Rent)rentProxy.getProxy();

        //proxy.rent();

        proxy.run();
    }
}

猜你喜欢

转载自blog.csdn.net/Yoke______/article/details/123019984