首页 > 编程语言 > 详细

Java中的静态代理和动态代理

时间:2020-05-31 17:45:00      阅读:39      评论:0      收藏:0      [点我收藏+]

静态代理

电影是电影公司委托给影院进行播放的,但是影院可以在播放电影的时候,产生一些自己的经济收益,比如卖爆米花、可乐等,然后在影片开始结束时播放一些广告。

现在用代码来进行模拟。

首先写一个接口,有播放电影的功能

public interface Movie {

void play(); }

然后,创建一个真正实现Movie接口的类

public class RealMovie implements Movie {

    @Override
    public void play() {
        // TODO Auto-generated method stub
        System.out.println("您正在观看电影 《肖申克的救赎》");
    }

}

写一个代理类(电影院),除了有播放电影的功能外,还有其他附加功能

Cinema 就是 Proxy 代理对象,它有一个 play() 方法。不过调用 play() 方法时,它进行了一些相关利益的处理,那就是广告。

public class Cinema implements Movie {
 4 
 5     RealMovie movie;
 6 
 7     public Cinema(RealMovie movie) {
 8         super();
 9         this.movie = movie;
10     }
11 
12 
13     @Override
14     public void play() {
15 
16         guanggao(true);
17 
18         movie.play();
19 
20         guanggao(false);
21     }
22 
23     public void guanggao(boolean isStart){
24         if ( isStart ) {
25             System.out.println("电影马上开始了,爆米花、可乐、口香糖9.8折,快来买啊!");
26         } else {
27             System.out.println("电影马上结束了,爆米花、可乐、口香糖9.8折,买回家吃吧!");
28         }
29     }
30 
31 }

 

测试代码

public class ProxyTest {

    public static void main(String[] args) {

        RealMovie realmovie = new RealMovie();

        Movie movie = new Cinema(realmovie);

        movie.play();

    }

}

 

 

动态代理

与静态代理的功能与目的是没有区别的,区别在于:

上一节代码中 Cinema 类是代理,我们需要手动编写代码让 Cinema 实现 Movie 接口,而在动态代理中,我们可以让程序在运行的时候自动在内存中创建一个实现 Movie 接口的代理,而不需要去定义 Cinema 这个类。这就是它被称为动态的原因。

 

动态代理的例子:

假设有一个大商场,商场有很多的柜台,有一个柜台卖茅台酒。我们进行代码的模拟。

1.创建一个卖酒的接口

public interface SellWine {

     void mainJiu();

}

2.创建一个茅台酒的类

public class MaotaiJiu implements SellWine {

    @Override
    public void mainJiu() {
        // TODO Auto-generated method stub
        System.out.println("我卖得是茅台酒。");

    }

}

3.还需要一个柜台来卖酒(InvocationHandler )

public class GuitaiA implements InvocationHandler {

    private Object pingpai;


    public GuitaiA(Object pingpai) {
        this.pingpai = pingpai;
    }



    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        // TODO Auto-generated method stub
        System.out.println("销售开始  柜台是: "+this.getClass().getSimpleName());
        method.invoke(pingpai, args);
        System.out.println("销售结束");
        return null;
    }

}

 

4.测试

public class Test {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        MaotaiJiu maotaijiu = new MaotaiJiu(); //实际的对象


        InvocationHandler jingxiao1 = new GuitaiA(maotaijiu); //创建一个InvocationHandler对象


        SellWine dynamicProxy = (SellWine) Proxy.newProxyInstance(MaotaiJiu.class.getClassLoader(),
                MaotaiJiu.class.getInterfaces(), jingxiao1); //动态生成代理对象

        dynamicProxy.mainJiu();  //通过代理对象调用卖酒方法

    }

}

 

动态代理语法

Proxy

通过 Proxy 的静态方法 newProxyInstance 可以动态创建代理。

public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
  • loader 自然是类加载器
  • interfaces 代码要用来代理的接口
  • h 一个 InvocationHandler 对象

InvocationHandler

InvocationHandler 是一个接口,官方文档解释说,每个代理的实例都有一个与之关联的 InvocationHandler 实现类,如果代理的方法被调用,那么代理便会通知和转发给内部的 InvocationHandler 实现类,由它决定处理。

public interface InvocationHandler {

    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;
}

InvocationHandler 内部只是一个 invoke() 方法,正是这个方法决定了怎么样处理代理传递过来的方法调用。

  • proxy 代理对象
  • method 代理对象调用的方法
  • args 调用的方法中的参数

因为,Proxy 动态产生的代理会调用 InvocationHandler 实现类,所以 InvocationHandler 是实际执行者。

具体实现可参考源码

 

代理的作用

在不修改被代理对象的源码上,进行功能的增强,这在 AOP 面向切面编程领域经常见。

在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。
AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,
从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。 主要功能 日志记录,性能统计,安全控制,事务处理,异常处理等等。

总结

  1. 代理分为静态代理和动态代理两种。
  2. 静态代理,代理类需要自己编写代码写成。
  3. 动态代理,代理类通过 Proxy.newInstance() 方法生成。
  4. 不管是静态代理还是动态代理,代理与被代理者都要实现两样接口,它们的实质是面向接口编程。
  5. 静态代理和动态代理的区别是在于要不要开发者自己定义 Proxy 类。
  6. 动态代理通过 Proxy 动态生成 proxy class,但是它也指定了一个 InvocationHandler 的实现类。
  7. 代理模式本质上的目的是为了增强现有代码的功能。 

 

 

 

 

  

转载来自:https://blog.csdn.net/briblue/article/details/73928350

Java中的静态代理和动态代理

原文:https://www.cnblogs.com/karinemo/p/13019574.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!