Java设计模式——代理模式

代理模式

根据创建代理类的创建方式和时间不同可以分为:
1、静态代理 2、动态代理
代理模式的特征是什么?
代理类与委托类有相同的接口,代理类主要负责为委托类预处理事件以及其它消息。
代理类与委托类之间的联系
一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法。

1、静态代理

静态代理是什么
静态代理:编译时就将接口,代理类确定下来。在程序运行前就生成代理类的.class文件。
一个简单的静态代理实现
假如我给一个同学钱,让同学帮我写作业。这里,同学就是代理我写作业。
同学就是我的代理,程序编写的步骤如下:
1,创建一个Student接口。这个接口就是我(委托)和同学(代理)的公共接口,我们都有写作业的行为。这样,我的作业就可以通过同学来代理执行。
2、StudentImplements类(委托类)实现Student接口。
3、StudentProxy类(代理类)也实现Student这个接口。同时持有一个StudentImplements对象用来执行写作业这一行为。
4、创建代理模式的测试类ProxyTest。
Student接口:

/**
 * 创建Student接口
 * @author zzx
 * */
public interface Student {
    void doHomework();
}

StudentImplements类:

public class StudentImplements implements Student{
    private  String name;

    public StudentImplements() {
    }

    public StudentImplements(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

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

StudentProxy类:

/**
 * 代理类实现Student接口,保存StudentImplements实体,这样可以代理StudentImplements产生的行为
 * @author zzx
 * */
public class StudentProxy implements Student{
    //被代理的对象
    StudentImplements stu;

    public StudentProxy(Student stu) {
        //通过判断只代理StudentImplements对象
        if(stu.getClass()==StudentImplements.class){
           this.stu= (StudentImplements) stu;
        }
    }


    @Override
    public void doHomework() {
        System.out.println("给我钱");
        stu.doHomework();
    }
}

ProxyTest:

public class ProxyTest {
    public static void main(String[] args) {
        //被代理的学生我,我的作业有代理对象同学完成
        Student me=new StudentImplements("zzx");
        Student student=new StudentProxy(me);
        student.doHomework();
    }
}

在代理类中重写的方法中,我们可以做一些额外的处理。就是在Spring中的面向切面编程(AOP),我们能在一个切点执行一些操作。

2、动态代理

动态代理是什么
代理类在程序运行时创建的代理方式。
动态代理与静态代理的区别
动态代理的代理类是在Java代码中的“指示”动态生成的,相比于静态代理可以更方便的对代理类的函数进行统一的处理,而不用修改每个代理类中的方法。
一个动态代理实现过程
字Java的Java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过这个类和这个接口可以生成动态代理类和动态代理对象。
1、创建一个InvocationHandler对象
2、使用Proxy类的getProxyClass方法生成一个动态代理类stuProxyClass
3、获得stuProxyClass中一个带InvocationHandler参数的构造器constructor
4、通过构造器constructor来创建一个动态实例stuProxy
上面的4个步骤可以通过Proxy类newProxyInstances方法简化。
一个例子
张三上交班费由班长代缴:
MonitorUtil:

public class MonitorUtil {
    private static ThreadLocal<Long>  time= new ThreadLocal<>();

    public static void setTime(ThreadLocal<Long> time) {
        MonitorUtil.time = time;
    }

    public static void start(){
        time.set(System.currentTimeMillis());
    }
    //结束时打印消耗
    public static void finish(String methodName){
        long finishTime =System.currentTimeMillis();
        System.out.println(methodName+"方法耗时"+(finishTime-time.get())+"ms");
    }
}

Person接口:

/**
* 创建Person接口
* @author zzx
* */
public interface Person {
    //上交班费
    void giveMoney();
}

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

public class ProxyTest {
    public static void main(String[] args) {
        //创建一个实例对象,这个对象是被代理的对象
        Person zhangSan= new Student("张三");
        //创建一个与代理对象相关联的InvocationHandler
        InvocationHandler stuHandler= new StuInvocationHandler<>(zhangSan);
        //创建一个代理对象stuProxy来代理zhangSan,代理对象的每个执行方法都会替换
        //执行Invocation中的invoke方法
        Person stuProxy=(Person) Proxy.newProxyInstance(Person.class.getClassLoader(),new Class<?>[]{Person.class},stuHandler);
        //代理执行上交班费的方法
        stuProxy.giveMoney();
    }
}

Student

public class Student implements Person{
    private String name;

    public Student() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Student(String name) {
        this.name = name;
    }
    @Override
    public void giveMoney(){
        try {
            Thread.sleep(1000);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        System.out.println(name+"上交班费50元");
    }
}

StuInvocationHanlder:

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

public class StuInvocationHandler<T> implements InvocationHandler {
    //invocationHandler持有的被代理对象
    T target;
    public StuInvocationHandler(T target){
        this.target=target;
    }
    /**
     * proxy:代表动态代理对象9*
     * method:代表正在执行的方法
     * args:代表调用目标方法时传入的实参*/
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("代理执行"+method.getName()+"方法");
        //代理过程中插入监测方法,计算该方法耗时
        MonitorUtil.start();
        Object result=method.invoke(target,args);
        MonitorUtil.finish(method.getName());
        return  result;
    }
}

如果想进行深究动态代理原理
添加链接描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值