Java中Jdk动态代理的实现过程

1.静态代理模式

1.1 编写接口

public interface Person {
    String sing(String name);
    String dance(String name);
}

1.2 代理类与被代理类都实现该接口,代理类中定义被代理类对象,同时增强被代理类中的同名方法

//被代理类
public class Kun implements Person{
    @Override
    public String sing(String name) {
        System.out.println("坤坤唱了"+name);
        return "打篮球";
    }
    @Override
    public String dance(String name) {
        System.out.println("坤坤跳了"+name);
        return "爆炸了";
    }
}
//代理类
public class KunProxy implements Person{
    //被代理对象
    private Person person = new Kun();

    @Override
    public String sing(String name) {
        System.out.println("收600w");
        String res = person.dance(name);
        return res+"。。。。灭火";
    }
    @Override
    public String dance(String name) {
        System.out.println("收900w");
        String res = person.sing(name);
        return res+"。。。。摔一跤";
    }
}

1.3 对外只使用代理类对象来进行方法调用

public class Test {
    public static void main(String[] args) {
        //1.创建代理对象
        Person person = new KunProxy();
        //2.调用代理对象方法
        String res = person.sing("鸡你太美");
        System.out.println(res);
    }
}

2.动态代理

相比静态代理,进行动态代理的对象是动态创建的

2.1 编写共同的接口

public interface Person {
    String sing(String name);
    String dance(String name);
}

2.2 编写被代理类

//被代理类
public class Kun implements Person{
    @Override
    public String sing(String name) {
        System.out.println("坤坤唱了"+name);
        return "打篮球";
    }
    @Override
    public String dance(String name) {
        System.out.println("坤坤跳了"+name);
        return "爆炸了";
    }
}

jdk动态代理,程序运行时动态产生代理类并创建其代理类对象

2.3 编写创建动态代理类及其对象的工具类

public class KunProxyUtils {
    //被代理对象
    private Person person = new Kun();

    //动态创建代理对象
    public Person createProxy(){
        //运行时动态生成动态代理类,并将其加载到内存中,再创建动态代理类对象
        //参数1:类加载器,用于加载动态代理类
        //参数2,自定义接口,即代理类与被代理类实现的同一接口
        //参数3,实现InvocationHandler接口的类对象,再底层会调用其中的invoke方法
        //        因为通过jdk动态代理生成的代理类虽然实现了同一接口,但不知道接口中的方法具体应该执行什么工作
        //        所以需要将其中要进行的工作封装到一个方法中,并传给jdk动态代理方法
        //        jdk动态代理机制就定义了这样的一个接口InvocationHandler,其中的invoke方法定义好了方法的名字和参数
        return (Person) Proxy.newProxyInstance(KunProxyUtils.class.getClassLoader(),person.getClass().getInterfaces(),new MethodHandler());
    }
}

jdk动态代理机制生成代理类的过程:
在这里插入图片描述

(可以使用匿名内部类省略下面编写实现InvocationHandler接口中invoke方法的步骤)

public static Person createProxy(){
        return (Person) Proxy.newProxyInstance(KunProxyUtils.class.getClassLoader(), person.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println(method.getName()+"被调用了");
                if(method.getName().equals("sing")){
                    //要进行增强的代码
                    System.out.println("收600w");
                    //让被代理对象执行要调用的方法
                    Object res = method.invoke(person,args);
                    //要进行增强的代码
                    System.out.println("谢谢");
                    return res;
                }else if(method.getName().equals("dance")){
                    //要进行增强的代码
                    System.out.println("收900w");
                    //让被代理对象执行要调用的方法
                    Object res = method.invoke(person,args);
                    //要进行增强的代码
                    System.out.println("再爆炸");
                    return res;
                }else {
                    System.out.println("不支持该服务");
                    return null;
                }
            }
        });
    }

2.4 编写实现InvocationHandler接口中invoke方法的类,其中定义想要代理类执行的代码

public class MethodHandler implements InvocationHandler {
    private Person person;
    //接收被代理对象
    public MethodHandler(Person person){
        this.person = person;
    }
    /**
     * 其中定义代理类对象要进行的工作,jdk动态代理机制在底层调用,代理对象任意方法被调用时都会调用该invoke方法
     * @param proxy 代理对象自身
     * @param method    要调用的代理对象的方法
     * @param args  要调用的代理对象的方法的参数
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println(method.getName()+"被调用了");
        if(method.getName().equals("sing")){
            //要进行增强的代码
            System.out.println("收600w");
            //让被代理对象执行要调用的方法
            Object res = method.invoke(person,args);
            //要进行增强的代码
            System.out.println("谢谢");
            return res;
        }else if(method.getName().equals("dance")){
            //要进行增强的代码
            System.out.println("收900w");
            //让被代理对象执行要调用的方法
            Object res = method.invoke(person,args);
            //要进行增强的代码
            System.out.println("再爆炸");
            return res;
        }else {
            System.out.println("不支持该服务");
            return null;
        }
    }
}

2.5 编写测试

public class Test {
    public static void main(String[] args) {
        //通过创建代理工具类得到的person是一个代理类对象
        Person person = KunProxyUtils.createProxy();
        Object res1 = person.sing("鸡你太美");
        System.out.println(res1);
        Object res2 = person.dance("蠢蠢欲动");
        System.out.println(res2);
    }
}

输出结果
在这里插入图片描述
整个调用过程:
在这里插入图片描述
由此可见,在调用动态代理对象中任意方法时,都会调用InvocationHandler接口中的invoke方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值