动态代理

动态代理

理解这个问题之前 我们先来复习一下通过反射怎么调用运行时类的指定的方法

先来一个Person类

package com.zyk;

public class Person {
    private int id;
    private String name;
    private String show(String nation){
        System.out.println("我的国籍是"+nation);
        return nation;
    }
}

我们来看怎么调用

package com.zyk;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ReflectTest {
    public static void main(String[] args) throws Exception {
        //获取Class实例
        Class clazz=Person.class;
        //创建运行时类的对象
        Object o = clazz.newInstance();
        //获取指定的某个方法
        //参数1 获取的方法的名称
        //参数2 获取方法的形参列表
        Method show = clazz.getDeclaredMethod("show", String.class);
        //保证当前方法可以访问
        show.setAccessible(true);
        //去执行该运行时类的方法 就是执行Person的show方法
        //参数一 该方法的调用者 参数2 给方法形参赋值的实参
        //invoke方法的返回值就是对应类中调用方法的返回值
        Object returnValue=show.invoke(o,"china");
        System.out.println(returnValue);
    }
}

结果

我的国籍是china
china

下面我们来看动态代理

这里 我们要把握一个核心 (自己总结的)

调用代理类的方法 就是在代理类的方法中调用被代理类的同名方法

始终把这句话贯穿理解 我相信可以理解清楚动态代理

(说一个小插曲 你是不是想到了动态规划呢? 哈哈 都是劝退我们的东西 但我们要坚持下去 才会有收获啊)

我们来看一下动态代理要解决的两个核心问题

  1. 如何根据被代理对象 动态的生成一个代理类对象

2)当我们通过代理类对象调用方法a时 如何动态的去调取被代理类中的同名方法a

package test;

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

//接口
interface Human{
    String getBelief();
    void eat(String food);
}

//被代理类
class SuperMan implements Human{

    @Override
    public String getBelief() {
        return "I believe I can fly";
    }

    @Override
    public void eat(String food) {
        System.out.println("我喜欢吃"+food);
    }
}

//代理类
class ProxyFactory {
    //此方法 返回一个代理类对象
    public static Object getProxyInstance(Object object){//object被代理类对象

        MyInvocationHandler myInvocationHandler=new MyInvocationHandler();

        myInvocationHandler.bind(object);
        //第一个参数 object.getClass().getClassLoader() 该被代理对象的类加载器

        //第二个参数 object.getClass().getInterfaces() 被代理对象实现的接口数组
        //也就是被代理对象实现了那些接口 因为我们的代理对象和被代理对象要实现同一个接口
        //所以第二个参数要拿到 被代理对象实现了哪些接口

        //第三个参数  MyInvocationHandler的对象

        //这个方法动态的创建了一个代理类对象
        return Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces(),myInvocationHandler);
    }

}


class MyInvocationHandler implements InvocationHandler{

    private Object object;//需要使用被代理类的对象进行赋值

    public void bind(Object object){
        this.object=object;
    }

    //当我们通过代理类的对象 调用方法a时 就会自动调用下面的invoke()方法
    //我们这个MyInvocationHandler类的对象作为了newProxyInstance这个方法的第三个参数
    //当执行到newProxyInstance这个方法是 就会自动进入我们这个invoke方法
    //所以我们将被代理类要执行的方法a声明在invoke()中


    //该方法的第一个参数 Object proxy 我们创建的代理类对象newProxyInstance
    //method 就是代理类对象要调用的那个方法
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //被代理类去调用同名方法 注意第一个参数是object
        //也就是说这里利用反射调用了被代理类的指定方法
        Object returnValue=method.invoke(object,args);
        return  returnValue;
    }
}
public class ProxyTest {
    public static void main(String[] args) {
        SuperMan superMan=new SuperMan();
        //创建代理类对象
        Human proxyInstance = (Human) ProxyFactory.getProxyInstance(superMan);

        proxyInstance.eat("麻辣烫");
        String belief=proxyInstance.getBelief();
        System.out.println(belief);
    }

}

结果

我喜欢吃麻辣烫
I believe I can fly

最后 希望大家不管生活有多难 我们都要勇敢的面对他 坚持下去 我们共勉!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值