详解 Java静态代理

所属分类: 软件编程 / java 阅读数: 127
收藏 0 赞 0 分享

  今天要介绍的是一个Java中一个很重要的概念——代理。

  什么是代理?联系生活想想看,代理似乎并不陌生,最形象的代表便是经纪人,明星一般都有经纪人,经纪人作为中间人,负责代理明星的相关事宜,比如说,有人要请明星去唱歌表演,一般不会直接跟明星联系,而是联系他的经纪人,他的经纪人来负责安排行程,而真正唱歌表演的还是明星本人,经纪人仅仅作为一个附加物存在。

  在Java中,代理也是这样的概念,来看个栗子:

  先来创建一个明星类Stars:

public class Stars implements IStars{
  private String name;

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

  public String getName() {
    return name;
  }

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

  public void sing(){
    System.out.println(getName() + " 唱了一首歌.");
  }

  public void dance(){
    System.out.println(getName() + " 跳了一支舞.");
  }
}

  这是相应的接口:

public interface IStars {
  void sing();
  void dance();
}

  现在创建一个代理类:

public class StarsProxy implements IStars{
  //保存接收的代理对象
  private IStars stars;

  public StarsProxy(IStars stars){
    this.stars = stars;
  }

  @Override
  public void sing() {
    System.out.println("我是代理,我收到了唱歌请求。");
    stars.sing();
    System.out.println("唱歌完毕");
  }

  @Override
  public void dance() {
    System.out.println("我是代理,我收到了跳舞请求。");
    stars.dance();
    System.out.println("跳舞完毕");
  }
}

  来测试一下:

public class Test {
  public static void main(String[] args){
    //创建目标对象
    IStars stars = new Stars("Frank");//代理对象,把目标传给代理对象,建立关系
    IStars starsProxy = new StarsProxy(stars);
    starsProxy.sing();
    starsProxy.dance();
  }
}

  运行结果:

我是代理,我收到了唱歌请求。
Frank 唱了一首歌.
唱歌完毕
我是代理,我收到了跳舞请求。
Frank 跳了一支舞.
跳舞完毕

  我们可以看到,实际上代理类只是保存了Stars类的一个实例,因为实现的是相同的接口,StarsProxy类必须实现需要代理的Stars类的方法,比如这里的dance和sing,而这个接口正是链接两者的关键,因为实现接口就代表必定存在接口中声明的方法。

  那么,为什么要使用代理呢?

  其实主要目的是为了扩展原有类的功能,想想看,如果那个Stars类不是你写的,而是别人写的,现在要将原有的sing或者dance方法进行改造,比如需要统计唱歌和跳舞的次数,次数大于10则不进行该操作直接返回,这时候用代理就很好实现了,来把代理类稍作修改:

public class StarsProxy implements IStars{
  //保存接收的代理对象
  private IStars stars;
  //保存sing和dance的次数
  private int num;

  public StarsProxy(IStars stars){
    this.stars = stars;
  }

  @Override
  public void sing() {
    if (!ifWork()) {
      return;
    }
    System.out.println("我是代理,我收到了唱歌请求。");
    stars.sing();
    System.out.println("唱歌完毕");
  }

  @Override
  public void dance() {
    if (!ifWork()) {
      return;
    }
    System.out.println("我是代理,我收到了跳舞请求。");
    stars.dance();
    System.out.println("跳舞完毕");
  }

  /**
   * 是否继续工作
   * @return 是返回true,否则返回false
   */
  private boolean ifWork(){
    if (num > 3){
      System.out.println("明星今天已经很累了,明天再来吧。");
      return false;
    }else {
      num++;
      return true;
    }
  }
}

  修改一下测试类:

public class Test {
  public static void main(String[] args){
    //创建目标对象
    Stars stars = new Stars();
    stars.setName("Frank");

    //代理对象,把目标传给代理对象,建立关系
    StarsProxy starsProxy = new StarsProxy(stars);
    for (int i = 0;i < 5; i++){
      starsProxy.sing();
    }
  }
}

  测试结果如下:

我是代理,我收到了唱歌请求。
Frank 唱了一首歌.
唱歌完毕
我是代理,我收到了唱歌请求。
Frank 唱了一首歌.
唱歌完毕
我是代理,我收到了唱歌请求。
Frank 唱了一首歌.
唱歌完毕
我是代理,我收到了唱歌请求。
Frank 唱了一首歌.
唱歌完毕
明星今天已经很累了,明天再来吧。

  看,简单粗暴。

  但其实并没有多少干货,这里仅仅是一种代理的思想,用这种思想可以比较方便的在不直接修改原有类的前提下对原有类的方法进行扩展。为某个对象提供一个代理,以控制对这个对象的访问。 代理类和委托类有共同的父类或父接口,这样在任何使用委托类对象的地方都可以用代理对象替代。代理类负责请求的预处理、过滤、将请求分派给委托类处理、以及委托类执行完请求后的后续处理。可以使业务类只关注业务逻辑本身,保证了业务类的重用性,这也是代理的共有优点。

  但是限制也显而易见:

  1.代理类需要跟被代理类实现相同的接口,这样才能一起向上转型后实现多态。

  2.当被代理的类需要进行的扩展增多时,管理会变得更加困难,之后对被代理类的修改,需要同时修改代理类,增加了修改成本。

  所以不要为了使用而使用,应用在合适的场景才能发挥它真正的作用。

  至此,本篇讲解完毕,欢迎大家继续关注!

以上就是详解 Java静态代理的详细内容,更多关于Java静态代理的资料请关注脚本之家其它相关文章!

更多精彩内容其他人还在看

Java实现一个简单的文件上传案例示例代码

这篇文章主要介绍了Java实现一个简单的文件上传案例,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
收藏 0 赞 0 分享

详解在spring中使用JdbcTemplate操作数据库的几种方式

这篇文章主要介绍了详解在spring中使用JdbcTemplate操作数据库的几种方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

java中的switch case语句使用详解

这篇文章主要介绍了java中的switch case语句使用详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

深入理解Java 线程池

这篇文章主要介绍了Java 线程池的相关资料,文中讲解非常细致,帮助大家更好的理解和学习,感兴趣的朋友可以了解下
收藏 0 赞 0 分享

详解mybatis #{}和${}的区别、传参、基本语法

这篇文章主要介绍了mybatis #{}和${}的区别、传参、基本语法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
收藏 0 赞 0 分享

MyBatis 中 ${}和 #{}的正确使用方法(千万不要乱用)

这篇文章主要介绍了MyBatis 中 ${}和 #{}的正确使用方法,本文给大家提到了MyBatis 中 ${}和 #{}的区别,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
收藏 0 赞 0 分享

详解Mybatis中的 ${} 和 #{}区别与用法

这篇文章主要介绍了Mybatis中的 ${} 和 #{}区别与用法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
收藏 0 赞 0 分享

Maven安装过程图文详解

这篇文章主要介绍了Maven安装过程,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
收藏 0 赞 0 分享

SpringBoot登录拦截配置详解(实测可用)

这篇文章主要介绍了SpringBoot登录拦截配置详解(实测可用),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

JAVA 内存溢出案例汇总

这篇文章主要介绍了JAVA 内存溢出案例的汇总,文中讲解非常细致,帮助各位工作学习时避免内存溢出,感兴趣的朋友可以了解下
收藏 0 赞 0 分享
查看更多