为什么要用动态代理?静态代理与动态代理详解

代理模式:

代理模式在Java中特别常见,如spring AOP功能就是用代理来实现的。代理模式作用是:在不修改被代理对象功能的基础上,通过对代理类进行扩展,进行一些功能上的附加与增强。
一般使用代理模式我们需要先定义一个接口,静态代理只是一种简单的java代码功能扩展。而动态代理利用了反射机制,使用更简单,但背后逻辑…先说明一点,动态代理代理的是接口,而不是类Proxy类产生的代理对象是Proxy的一个实例,这个实例实现了我们定义的接口


静态代理:

举一个黄牛代理买票的例子:

public interface BuyTicket {
    //买票
    void buyTicket();
}

我自己买票,买不到

public class CommonPerson implements BuyTicket {
    @Override
    public void buyTicket() {
        System.out.println("我自己在12306买不到票!");
    }
}

我在智行火车票上加钱抢票,找黄牛代理

public class HuangNiu implements BuyTicket {

    //我买不到票,我需要被代理
    CommonPerson person = new CommonPerson();

    @Override
    public void buyTicket() {
        person.buyTicket();
        System.out.println("我是黄牛,买票找我,出票成功!");
    }

    public static void main(String[] args) {
        HuangNiu huangNiu = new HuangNiu();
        huangNiu.buyTicket();
    }
}

打印结果:
在这里插入图片描述
可以看出,我们自己买不到票,找黄牛代理,代理类可以帮助我们实现功能增强。


动态代理(jdk):

动态代理通过java反射机制,获取某个被代理类的所有接口,并创建代理类。接口类和被代理类同上:

import Proxy.BuyTicket;
import Proxy.CommonPerson;

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

/**
 * Description:
 * Created by CWG on 2020/8/29 10:34
 */
public class HuangNiu implements InvocationHandler {

    private CommonPerson person;

    public HuangNiu(CommonPerson person) {
        this.person = person;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object res = method.invoke(person, args);
        System.out.println("我是黄牛,买票找我,出票成功!");

        return res;
    }

    public static void main(String[] args) {
        //被代理类
        CommonPerson person = new CommonPerson();

        //代理类
        HuangNiu huangNiu = new HuangNiu(person);

        //生成代理对象:注意这里生成的代理对象只能是接口
        BuyTicket buyTicket = (BuyTicket) Proxy.newProxyInstance(
                CommonPerson.class.getClassLoader(),
                CommonPerson.class.getInterfaces(),
                huangNiu);

        //调用代理对象方法
        buyTicket.buyTicket();

    }
}

打印结果:
在这里插入图片描述
可以发现功能与静态代理一样,不同的是静态代理每次都要重写接口中方法,而动态代理使我们免于去重写接口中的方法,着重于去扩展相应的功能或是方法的增强,虽然在此示例中可能看不出,可能看上去比静态代理更复杂,当我们在实际开发环境下,接口中方法很多的时候,就可以发现动态代理的便捷,会大大减少项目中的业务量。


动态代理解读:

Proxy类

在上例main测试方法中,用到了Proxy.newProxyInstance()方法。动态代理涉及了一个非常重要的类Proxy。正是通过Proxy的静态方法newProxyInstance才会动态创建代理

public static Object newProxyInstance(ClassLoader var0, 
			Class<?>[] var1, InvocationHandler var2) throws IllegalArgumentException
  • ClassLoader var0:对应参数 CommonPerson.class.getClassLoader()即被代理类的类加载器
  • Class<?>[] var1:对应参数 CommonPerson.class.getInterfaces()即获取被代理类实现的所有接口
  • InvocationHandler var2:对应参数 代理类huangNiu, 为一个InvocationHandler实现对象

InvocationHandler接口

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

代理类需要实现InvocationHandler 接口,invoke()虽然没有被显式调用,但该方法也一定被执行了,对应的三个参数分别传入的是:代理类的实例,method是调用的方法,即需要执行的方法;args是方法的参数;

就本人目前水平,想看懂动态代理背后如何实现有点吃力,以后看懂再接着写吧,现在也只是知道动态代理是干嘛用的,如果有兴趣继续探究可以参考下面的参考文章3。

参考文章
1、jdk动态代理与cglib动态代理实现原理
2、为什么要使用java动态代理
3、JDK的动态代理原理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值