Java静态代理与动态代理

先粘贴一篇大佬的博文 「Java动态代理作用是什么」,本文是对其学习笔记。

代理(Proxy)是一种设计模式,通过代理对象来访问目标对象,目的是在目标对象的基础上进行增强,例如增加一些额外的功能。Java中的代理主要分为静态代理动态代理

静态代理

在这里插入图片描述
为每一个类都编写一个对应的代理类,两个类都实现同样的接口。在创建一个代理对象的时候,需要向其构造器中塞入一个目标对象,然后在代理对象的方法内部调用目标对象的同名方法(并可以加入一些额外的功能)。如下图所示:
在这里插入图片描述
可见 代理对象=目标对象+增强代码(即上图中的打印日志信息)。因此在使用了代理对象以后,就不用再使用目标对象了。

但是静态代理有一个严重的缺点,在项目中我们的类可能有成千上万个,如果要用静态代理的话,需要给每一个类写一个对应的代理类,显然是非常冗余的。因此我们需要考虑,如果有一种方法,能够绕开编写代理类,而可以直接生成相应的代理对象,这样就会方便简洁很多。这就是动态代理的出发点。

动态代理

感觉一些具体的细节开头的博客解释的很棒了,这里就梳理一下流程。首先上一段代码:

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

interface Calculator
{
    int add(int a, int b);
    int subtract(int a, int b);
}

class CalculatorImp1 implements Calculator
{
    public int add(int a, int b)
    {
        return a+b;
    }
    public int subtract(int a, int b)
    {
        return a-b;
    }
}

public class ProxyTest {
    public static void main(String[] args) throws Throwable{
        CalculatorImp1 target = new CalculatorImp1();
        Calculator proxy = (Calculator)getProxy(target);
        System.out.println(proxy.getClass().getName());
        System.out.println(proxy instanceof CalculatorImp1);
        proxy.add(1, 2);
        proxy.subtract(1, 2);
    }

    public static Object getProxy(final Object target) throws Exception {
        Class proxyClazz = Proxy.getProxyClass(target.getClass().getClassLoader(), target.getClass().getInterfaces());
        Constructor constructor = proxyClazz.getConstructor(InvocationHandler.class);
        Object proxy = constructor.newInstance(new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println(method.getName() + "方法开始执行");
                Object result = method.invoke(target, args);
                System.out.println(result);
                System.out.println(method.getName() + "方法结束执行");
                return result;
            }
        });
        return proxy;
    }
}

我们有一个接口Calculator,以及一个目标类CalculatorImp1。动态代理是在不写代理类的情况下,直接生成代理对象proxy。

这里用到了JDK中的java.lang.reflect.InvocationHandler接口和 java.lang.reflect.Proxy类。其中Proxy有一个静态方法getProxyClass(只需要传入类加载器和接口,就可以生成代理Class对象)。有了代理Class对象后,就可以利用代理Class的构造器创建对象,此时需要传入InvocationHandler,每次调用代理对象的方法,最终都会调用InvocationHandler的invoke()方法。

在创建代理对象的时候用到匿名内部类的方式,实现了接口InvocationHandler()的方法,对invoke方法进行了重写实现。其中的method.invoke部分实现的是目标类的方法,其他代码则是进行的额外的扩充。这样就非常灵活了,无论现在系统有多少类,只要把实例传进来,getProxy()都能给你返回对应的代理对象。就这样,我们完美地跳过了代理类,直接创建了代理对象!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值