动态代理基础

动态代理

代理模式

  • 代理模式:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户类和目标对象之间起到中介的作用
  • 使用代理对象,是为了在不修改目标对象的基础上,实现对功能的增强。
  • 代理模式的作用的另一种表述:
    (1)功能增强:在你原有的功能上,增加了额外的功能。
    (2)控制访问:代理类不让你访问目标。例如:商家不让用户访问厂家。
  • 客户类真正想要访问的对象是目标对象,但客户类真正可以访问的对象是代理对象。客户类对目标对象的访问是通过访问代理对象来实现的。 当然,代理类和目标类要实现同一个接口。
  • 示例:A 类想调用 C 类中的方法,但 C 类不允许 A 类调用,但 B 类可以调用 C 类中的方法。于是 A 类就通过 B 类调用 C 类的方法。因此 B 就是 C 的代理,A 通过 代理 B 访问 C。
  • 图示:
    图示

静态代理

  • 静态代理的定义:我们需要手动为目标类编写一个代理类
// 创建接口
interface Person{
    void doWork();
}
// 创建目标类
class Student implements Person{
    @Override
    public void doWork() { System.out.println("学习"); }
}
// 静态代理
class StaticProxy implements Person{
    private Person person;
    public StaticProxy(Person person){ this.person = person; }
    @Override
    public void doWork() {
        System.out.println("doSome before");
        person.doWork();
        System.out.println("doSome after");
    }
}

public class Test {
    public static void main(String[] args) {
        Student student = new Student();
        StaticProxy proxy = new StaticProxy(student);
        proxy.doWork();
    }
}
  • 优点:实现简单;容易理解
  • 缺点:
    (1)在目标类比较多的时候,会产生大量的代理类。
    (2)当接口中功能增加或修改时,影响的目标类和代理类会比较多,都需要修改。

动态代理

  • 动态代理的定义:在程序运行过程中,通过 jdk 的反射机制自动生成代理类对象
  • 优点:(1)不用创建代理类文件
               (2)代理的目标类是活动的,可设置的。
  • 动态代理可以做什么:
    在不改变原来目标方法的前提下,可以在代理中增强自己的功能代码。
  • 动态代理的实现方式通常有两种:使用 JDK 动态代理和通过 CGLIB 动态代理。
    (1)JDK 的动态代理:JDK 的动态代理是基于 java 的反射机制实现的。使用过 JDK 中接口和类实现代理对象的动态创建。jdk 的动态代理要求目标对象必须实现接口,这是 java 设计上的要求。java 语言通过 java.lang.reflect 包提供的三个类支持代理模式:Proxy、Method 和 InvocationHandler。
    (2)CGLIB 动态代理:CGLIB 是一个开源项目。CGLIB 代理的生成原理是生成目标类的子类,而子类是增强过的,这个子类对象就是代理对象。所以,使用 CGLIB 生成动态代理,要求目标类必须能够被继承,即不能是 final 的类。

jdk 动态代理的实现

  • 反射包 java.lang.reflect,里面有三个类支持代理模式:InvocationHandler、Method、Proxy。
InvocationHandler 接口
  • InvocationHandler 接口(调用处理器):该接口里面只有一个方法 invoke()。invoke():表示代理对象要执行的功能代码,你的代理类要完成的功能就写在 invoke() 方法中。
  • 代理类的功能(主要做两件事情):
    (1)调用目标方法,执行目标方法的功能。
    (2)功能增强,在目标方法调用时,增强额外的功能。
  • InvocationHandler 接口中的 invoke() 方法:
参数:
     Object proxy:表示 jdk 创建的代理对象,无需赋值。
     Method method:表示目标类中的方法,无需赋值。
     Object[] args:目标类中方法的参数。     
public Object invoke(Object proxy, Method method, Object[] args)
  • 怎么使用 InvocationHandler 接口:
    (1)创建类实现接口 InvocationHandler。
    (2)重写 invoke() 方法,把原来静态代理中代理类要完成的功能,写在这里。
Method 类
  • Method 类:表示方法的,其实就是目标类中的方法。
  • 作用:通过 Method 可以执行某个目标类中的方法,method.invoke(目标对象,方法的参数)。
Proxy 类
  • Proxy 类:是用来创建代理对象的。
  • 使用的方法:newProxyInstance()。
参数:
    ClassLoader loader:类加载器,负责向内存中加载对象的。使用反射机制获取目标对象的 ClassLoaderClass<?>[] interfaces:接口,目标对象实现的接口。也是使用反射机制获取的。
    InvocationHandler h:我们自己写的,代理类要完成的功能。

    返回值:就是代理类对象
public static Object newProxyInstance(ClassLoader loader,
                                      Class<?>[] interfaces,
                                      InvocationHandler h)
实现动态代理的步骤

(1)创建接口,定义目标类要完成的功能。
(2)创建目标类实现接口。
(3)创建 InvocationHandler 接口的实现类,在 invoke() 方法中完成代理类的功能。(主要干两件事情:1、调用目标方法;2、功能增强)
(4)使用 Proxy 类的静态方法,创建代理对象,并把返回值转为接口类型。

// 创建接口
interface Person{
    void doWork();
}
// 创建目标类
class Student implements Person{
    @Override
    public void doWork() {
        System.out.println("学习");
    }
}

class MyInvocationHandler implements InvocationHandler {
    private Object target;
    public MyInvocationHandler(Object target){
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("doSome before");
        Object invoke = method.invoke(target, args); // 执行目标类的方法,通过 Method 类实现
        System.out.println("doSome after");
        return invoke;
    }
}

public class Test {
    public static void main(String[] args) {
        Student student = new Student();
        MyInvocationHandler handler = new MyInvocationHandler(student);
        // 生成代理类对象
        Person proxy = (Person)Proxy.newProxyInstance(student.getClass().getClassLoader(),student.getClass().getInterfaces(), handler);
        proxy.doWork();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

静波波呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值