设计模式-一定能让你看懂的静态代理与动态代理

1、静态代理与动态代理的区别

  • 静态代理就是在程序运行前就已经存在代理类的字节码文件、代理类和原始类的关系在运行前就已经确定。

  • 而动态代理采用反射技术,在运行时才确定代理哪个方法。

动态代理的好处在哪儿?举个简单的例子

2、静态代理

  • 1.首先写一个Human这个接口,模拟人类的行为:吃饭,睡觉,学习,工作
/**
 * @author XiangYida
 * @version 2019/4/7 14:43
 * 模拟人的行为
 */
public interface Human {
    //吃饭
    public void eat();
    //睡觉
    public void sleep();
    //学习
    public void study();
    //工作
    public void work();
}
  • 2.写一个Student类,实现这个接口,实现里面的方法。
/**
 * @author XiangYida
 * @version 2019/4/7 14:45
 * 学生类
 */
public class Student implements Human {
    @Override
    public void eat() {
        System.out.println("I am eating");
        Thread.sleep(200);
    }

    @Override
    public void sleep() {
        System.out.println("I am sleeping");
        Thread.sleep(2000);
    }

    @Override
    public void study() {
        System.out.println("I am studying");
        Thread.sleep(1000);
    }

    @Override
    public void work() {
        System.out.println("I am working");
        Thread.sleep(1000);
    }
}
  • 3.然后是代理类,来记录每个行为的时间
/**
 * @author XiangYida
 * @version 2019/4/7 14:48
 */
public class MyProxy {
    Human student=new Student();
    public void eat(){
        long l1=System.currentTimeMillis();
        student.eat();
        System.out.println("===============your eat time is  "+(System.currentTimeMillis()-l1));
    }

    public void sleep() {
        long l1=System.currentTimeMillis();
        student.sleep();
        System.out.println("===============your sleep time is  "+(System.currentTimeMillis()-l1));
    }

    public void study() {
        long l1=System.currentTimeMillis();
        student.study();
        System.out.println("===============your study time is  "+(System.currentTimeMillis()-l1));
    }

    public void work() {
        long l1=System.currentTimeMillis();
        student.work();
        System.out.println("===============your work time is  "+(System.currentTimeMillis()-l1));
    }
}
  • 4.测试
/**
 * @author XiangYida
 * @version 2019/4/7 14:52
 */
public class Test {
    public static void main(String[] args) {
        MyProxy proxy=new MyProxy();
        proxy.eat();
        proxy.sleep();
        proxy.work();
        proxy.study();
    }
}
  • 5.结果
I am eating
===============your eat time is  201
I am sleeping
===============your sleep time is  2001
I am working
===============your work time is  1002
I am studying
===============your study time is  1000
  • 为什么要用静态代理呢:代理保证了业务类只需关注逻辑本身,代理对象的一个接口只服务于一种类型的对象说通俗一点就是我只管我要做的事情,其他的事儿由代理来完成,比如你要去旅游,你只管去玩,其他订票日程安排啥的都有代理公司来帮你完成。

  • 那么,静态代理的缺点是什么呢。前面已经说过了,在程序运行前就已经存在代理类的字节码文件、代理类和原始类的关系在运行前就已经确定。这里模拟的人的行为只有四个,那假如有一万个行为呢,那是不是得在代理类中写一万个代理的方法。还有加入需要代理的对象不是Student了,而是Teacher了。是不是还得再来代理这个对象的行为?
    所以就引出了动态代理,使用反射技术,在程序运行时根据需要来确定代理相应的对象方法

3、动态代理

我们还是用Human这个例子,先上代码
Human接口以及Student类跟前面一样,这里就不写了。

  • 代理类(需要实现InvocationHandler接口,并重写invok方法)
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
 * @author XiangYida
 * @version 2019/4/7 15:18
 */
public class MyProxy implements InvocationHandler {
    private Object target=null;
    //绑定需要代理的对象
    public Object bind(Object target){
        this.target=target;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
    }
    //实现具体逻辑
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        long l1=System.currentTimeMillis();
        Object obj=method.invoke(target,args);
        System.out.println("===============your sleep time is  "+(System.currentTimeMillis()-l1));
        return obj;
    }
}
  • 测试
public class Test {
    public static void main(String[] args) {
        MyProxy myProxy=new MyProxy();
        Human student=(Human)myProxy.bind(new Student());
        student.eat();
        student.study();
        student.sleep();
        student.work();
    }
}
  • 运行结果
I am eating
===============your sleep time is  205
I am studying
===============your sleep time is  1001
I am sleeping
===============your sleep time is  2001
I am working
===============your sleep time is  1000
  • 现在我要添加代理一个Teacher类
/**
 * @author XiangYida
 * @version 2019/4/7 15:35
 */
public class Teacher implements Human {
    @Override
    public void eat() {
        System.out.println("I am a teacher~~~");
        System.out.println("I am eating");
        Thread.sleep(200);
    }
    @Override
    public void sleep() {
        System.out.println("I am a teacher~~~");
        System.out.println("I am sleeping");
        Thread.sleep(2000);
    }

    @Override
    public void study() {
        System.out.println("I am a teacher~~~");
        System.out.println("I am studying");
        Thread.sleep(1000);
    }

    @Override
    public void work() {
        System.out.println("I am a teacher~~~");
        System.out.println("I am working");
        Thread.sleep(1000);
    }
}
  • 测试(是不是感觉很方便呢_
public static void main(String[] args) {
        MyProxy myProxy=new MyProxy();
        Human student=(Human)myProxy.bind(new Student());
        student.eat();
        student.study();
        student.sleep();
        student.work();
        Human teacher=(Human)myProxy.bind(new Teacher());
        teacher.work();
        teacher.sleep();
        teacher.study();
        teacher.eat();
    }
  • 结果
I am eating
===============your sleep time is  201
I am studying
===============your sleep time is  1000
I am sleeping
===============your sleep time is  2001
I am working
===============your sleep time is  1000
I am a teacher~~~
I am working
===============your sleep time is  1002
I am a teacher~~~
I am sleeping
===============your sleep time is  2001
I am a teacher~~~
I am studying
===============your sleep time is  1000
I am a teacher~~~
I am eating
===============your sleep time is  201
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值