栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java中的代理模式详解及实例代码

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java中的代理模式详解及实例代码

java 代理模式详解

前言:

在某些情况下,一个客户不想或者不能直接引用一个对象,此时可以通过一个称之为“代理”的第三者来实现间接引用。代理对象可以在客户端和目标对象之间起到 中介的作用,并且可以通过代理对象去掉客户不能看到 的内容和服务或者添加客户需要的额外服务。

简单来说代理模式就是通过一个代理对象去访问一个实际对象,并且可以像装饰模式一样给对象添加一些功能。

静态代理

所谓静态代理即在程序运行前代理类就已经存在,也就是说我们编写代码的时候就已经把代理类的代码写好了,而动态代理则是在程序运行时自动生成代理类。

描述起来太过抽象,看一下代码就明白是怎么回事了

main

public class Main {

  public static void main(String[] args) {
    Water water = new Water();
    WaterProxy waterProxy = new WaterProxy(water);
    waterProxy.drink();
  }

}

接口

//代理类与被代理类共同实现的接口
public interface Drink {
  void drink();
}

被代理类

//被代理的类
public class Water implements Drink {

  @Override
  public void drink() {
    System.out.println("drink water");
  }

}

代理类

//代理类
//与被代理类实现同一个接口
public class DrinkProxy implements Drink {
  
  private Drink drinkImpl;
  
  //通过构造函数传入Water对象
  public DrinkProxy(Drink drinkImpl) {
    this.drinkImpl = drinkImpl;
  }
  
  @Override
  public void drink() {
    //在执行被代理对象的方法前做一些事情
    System.out.println("before drink");
    //执行被代理对象的方法
    drinkImpl.drink();
    //在执行被代理对象的方法后做一些事
    System.out.println("after drink");
  }

}

执行结果

before drink
drink water
after drink

动态代理

有时候我们只想改变代理类所代理的类,但是代理对象执行实际对象的方法前后所做的事情是一样的,正所谓铁打的代理类,流水的被代理类。而采用静态代理就只能代理实现了同一接口的类,如果要代理任意类则必须写很多重复的代理类。此时我们可以采用动态代理,Java已经为实现动态代理提供了一套比较方便的工具。

java.lang.reflect.Proxy类中可以动态生成代理对象的方法


public static Object newProxyInstance(ClassLoader loader,Class[] interfaces, InvocationHandler h)

InvocationHandler接口


public interface InvocationHandler {

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


描述总是比较抽象,还是看实际例子比较好理解

例子

InvocationHandler接口的实现类

public class CommonInvocationHandler implements InvocationHandler {
  
  //被代理的对象
  private Object proxied;
  
  public CommonInvocationHandler(Object proxied) {
    this.proxied = proxied;
  }
  
  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    //在调用被代理对象的方法前做一些事情
    System.out.println("before doing something");
    //调用被代理对象的方法
    Object result = method.invoke(proxied, args);
    //在调用被代理对象的方法后做一些事情
    System.out.println("after doing something");;
    return result;
  }

}

Main

public class Main {

  public static void main(String[] args) {
    //被代理的对象
    Water water = new Water();
    //动态获取代理对象
    Drink waterProxy = 
 (Drink) Proxy.newProxyInstance(water.getClass().getClassLoader(),
     water.getClass().getInterfaces(), 
     new CommonInvocationHandler(water));
    //通过代理对象调用方法
    waterProxy.drink();
  }

}

输出结果

before doing something
drink water
after doing something

也可以不要具体的被代理对象,但是必须有相应的接口(没有实现接口的类可以使用cglib实现动态代理)才可以动态获取代理对象。像最近比较火的Retrofit就直接通过声明好的接口使用动态代理进行网络请求。

例子

简单的模拟一下retrofit

POST注解

//Post请求注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface POST {
 String value() default "";
}

Query注解

//Post请求注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface POST {
 String value() default "";
}

Service接口

public interface Service {
  //用POST注解声明请求的方式和相对路径
  @POST("/login")
  //@Query注解声明请求的参数名
  void login(@Query("username")String username, 
      @Query("password")String password);
}

Main

public class Main {

  public static void main(String[] args) {
    // 动态获取Service接口的代理
    Service service = (Service) Proxy.newProxyInstance(Service.class.getClassLoader(),
 new Class[] { Service.class }, new InvocationHandler() {

   @Override
   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
     // 通过注解获取请求的相对路径
     String retativePath = ((POST) method.getAnnotations()[0]).value();
     System.out.println("relative path: " + retativePath);
     // 获取参数的注解
     Annotation[][] parameterAnnotations = method.getParameterAnnotations();
     // 通过参数的注解获取请求参数
     for (int i = 0; i < parameterAnnotations.length; i++) {
if (parameterAnnotations[i].length != 0) {
  for (int j = 0; j < parameterAnnotations[i].length; j++) {
    Query query = (Query) parameterAnnotations[i][j];
    System.out.println(query.value() + ": " + args[i].toString());
  }
}
     }
     return null;
   }
 });
    // 调用代理对象的方法
    service.login("hello", "world");
  }

}

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/147865.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号