浅谈代理模式

代理模式是一种对象结构型设计模式,它为对象提供代理以控制对这个对象的访问。代理对象在客户端和目标对象之间起到中介和增强的作用,支持静态代理和动态代理。静态代理需要预先定义接口或父类,而动态代理则能在运行时动态生成代理类,如JDK代理和CGLIB代理。
摘要由CSDN通过智能技术生成

一.模式定义

  • 代理模式是常见的设计模式之一,代理模式给某一个对象提供一个代理对象,代理对象具备真实对象的功能,并代替真实对象完成相应操作,并能够在操作执行的前后,对操作进行增强处理,是一种对象结构型模式。

 

二.模式结构

 

  • Subject抽象类

  定义了RealSubject和Proxy的共同接口,这样就在任何使用RealSubject的地方都可以使用Proxy。

public abstract class Subject {

    public abstract void request();

}
  • RealSubject类

  定义了Proxy所代表的真实实体。

public class RealSubject extends Subject {

    @Override
    public void request() {
        System.out.println("真实的请求RealSubject");
    }

}
  • Proxy类

  代理类。一个代理类可以代理多个被委托者或被代理者,因此一个代理类具体代理哪个真实主题角色,是由场景类决定的。

public class Proxy extends Subject {

    private RealSubject realSubject = null;

    public Proxy() {
        this.realSubject = new RealSubject();
    }

    @Override
    public void request() {
        this.before();
        this.realSubject.request();
        this.after();
    }

    //预处理
    private void before() {
        System.out.println("-------before------");
    }

    //善后处理
    private void after() {
        System.out.println("-------after-------");
    }
}

  • 代理模式又分为静态代理和动态代理。动态代理常用 JDK 代理和 CGLIB 代理。

静态代理

  • 静态代理在使用时,需要定义接口或者父类,被代理对象(即目标对象)与代理对象一起实现相同的接口或者是继承相同父类。
  • 由程序员创建或特定工具自动生成源代码,也就是在编译时就已经将接口、被代理类、代理类等确定下来。在程序运行之前,代理类的.class文件就已经生成。
  • 静态代理主要是在代理类中将被代理类的对象关联起来,将代码写死,无法更改代理对象。

定义一个 Person 接口确认具体行为。

//定义 Person 接口
public interface Person {
    void do();
}

定义 Student 类,实现具体业务逻辑(被代理类)

public class Student implements Person {

    private String name;
    public Student(String name){
        this.name = name;
    }
    @Override
    public void do() {
        System.out.println(name + "写作业");
    }
}

 定义代理类 MonitorProxy ,持有一个 Student 类对象,外界可通过这个类来访问 Student 类的方法。

public class MonitorProxy implements Person {

    private Student student;

    public MonitorProxy(Student student){
        this.student = student;
    }

    @Override
    public void do() {
        System.out.println("交作业!");
        student.do();
    }
}

通过 MonitorProxy 来代理执行 Student 操作。

public class ProxyDemoTest {
    public static void main(String[] args) {
        MonitorProxy monitor = new MonitorProxy(new Student("张三"));
        monitor.do();
    }
}

动态代理-jdk

  • 在编译期间无法确定需要代理的类。运行期间动态生成代理类。
  • 在 java 的 java.lang.reflect 包下提供了一个 Proxy 类和一个 InvocationHandler 接口,通过这个类和这个接口可以生成 JDK 动态代理类和动态代理对象。
  • 只能为接口实现类创建代理对象
  • 创建出来的代理都是java.lang.reflect.Proxy的子类
  • 代理对象,不需要实现接口,但是目标对象要实现接口,否则不能用动态代理;
  • 代理对象的生成,是利用JDK的API,动态的在内存中构建代理对象;

定义一个接口规范。

public interface Person {
    void do();

 
}

 实现接口规范的业务类。

public class Student implements Person {
    private String name;
    public Student(String name){
        this.name = name;
    }

    @Override
    public void do() {
        System.out.println(name + "写作业");
    }

}

 定义处理器,实现 InvocationHandler 接口,invoke 方法定义了代理需要做的事情

(事情处理器,执行目标对象的方法时,会触发事情处理器方法, 会把当前执行的目标对象方法作为参数传入

public class ProxyHandle<T> implements InvocationHandler {

    T target;
    public ProxyHandle(T target){
        this.target = target;
    }

    /**
     * proxy 表示代理对象
     * method 表示正在执行的方法
     * args 表示调用方法时的参数
     * */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        
        System.out.println("代理执行:" + method.getName() + "方法");

        //执行代理方法
        Object invoke = method.invoke(target, args);
        return invoke;
    }
}

动态生成代理对象

public class ProxyTest {
    public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {

        Person p = new Student("张三");

        ProxyHandle<Person> personProxyHandle = new ProxyHandle<>(p);
 
        //ClassLoader loader : 指定当前目标对象使用的类加载器, 获取加载器的方法固定;
        // Class<?>[] interfaces: 目标对象实现的接口类型,使用泛型方法确认类型;
        // personProxyHandle : 事情处理器,执行目标对象的方法时,会触发事情处理器方法, 会把当前执行的目标对象方法作为参数传入

        Person o = (Person)Proxy.newProxyInstance(Person.class.getClassLoader(), new Class<?>[]{Person.class}, personProxyHandle);

        o.do();
       

      
    }
}

动态代理-cglib

1、静态代理和JDK代理模式都要求目标对象是实现一个接口,但是有时候目标对象只是一个单独的对象,并没有实现任何的接口,这个时候可使用目标对象子类来实现代理-这就是Cglib代理 ;

2、Cglib代理也叫作子类代理,它是在内存中构建一个子类对象从而实现对目标对象功能扩展,有些书也将Cglib代理归属到动态代理;

3、Cglib是一个强大的高性能的代码生成包,它可以在运行期扩展java类与实现java接口。它广泛的被许多AOP的框架使用,例如SpringAOP,实现方法拦截;

4、在AOP编程中如何选择代理模式:

  • 目标对象需要实现接口,用JDK代理;
  • 目标对象不需要实现接口,用Cglib代理。

5、Cglib包的底层是通过使用字节码处理框架ASM来转换字节码并生成新的类。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值