java代理模式

代理模式

  • 定义:给某一个对象提供一个代理,并由代理对象控制对原对象的引用。
    代理(Proxy)是一种设计模式,提供了间接对目标对象进行访问的方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的功能上,增加额外的功能补充,即扩展目标对象的功能。在java中代理模式很常见。代理模式就是一种思维方式。

这就符合了设计模式的开闭原则,即在对既有代码不改动的情况下进行功能的扩展。
举个例子,比如在国内想要买国外的商品,就需要有代购,需要告诉代购你想买的东西。代购会帮你找到目标商店帮你买。其中这个代购就可以看作是一个代理。目标商店就是被代理的类。
下面来说一下java中三种代理模式。

静态代理

  • 静态代理需要目标类和代理类都实现同一个接口。

被代理类

//目标类
public class Ps4Factory implements GameFactory{
    public void make() {
        System.out.println("Ps4已出库");
    }
}

代理类

public class Proxy implements GameFactory{
   private GameFactory game;

   public Proxy(GameFactory game) {
       this.game = game;
   }
   public void make() {
       doBefore();
       game.make();
       doAfter();
   }
   private void doAfter() {
       System.out.println("After is OK");
   }
   private void doBefore() {
       System.out.println(" Befor is OK");
   }
}

测试

public static void main(String[] args) {
       //此模式为Proxy的静态代理模式
       //优点:可以在不改变目标对象的代码的情况下,增加功能。
       //缺点:Proxy和目标对象都需要实现一个共同的接口,这样的话,就会导致Proxy的类中也需要实现这个方法。不益于拓展。
       GameFactory ps4Factory = new Ps4Factory();
       GameFactory proxy=new Proxy(ps4Factory);
       proxy.make();
   }

结果

 Befor is OK
Ps4y已出库
Afte ris OK

已经是现在在不改变目标类的情况下增加功能。静态代理的前提是需要代理类和被代理类都实现统一个接口。

动态代理

jdk动态代理

  • 动态代理是在程序运行过程中,动态生成一个代理对象。

被代理类

public class Ps4Factory implements GameFactory {
  public void make() {
      System.out.println("Ps4  make。。。");
  }
  public void sall() {
      System.out.println("Ps4  sall。。。");
  }

代理类

**
* 动态代理需要实现一个叫invocationHandler的接口。 主要是用来让生成的代理对象动态(代理)的调用目标方法,并且添加对应的辅助功能!!!
*/

public class JdkProxy implements InvocationHandler {
   private Object target;
   public Object getTarget() {
       return target;
   }
   public void setTarget(Object target) {
       this.target = target;
   }
   public Object getProxy(){
      return  Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
   }
   public Object invoke(Object proxyy, Method method, Object[] args) throws Throwable {
       doBefore();
       Object invoke = method.invoke(target, args);
       deAfter();
       return invoke;
   }
   private void deAfter() {
       System.out.println(" invoke  end!!!!");
   }
   private void doBefore() {
      System.out.println(" invoke  start!!!!");
   }
}

测试类

   public static void main(String[] args) {
       GameFactory ps4Factory = new Ps4Factory();
       GameFactory gameFactory = new GameBoy();
       JdkProxy cglibProxy = new JdkProxy();
       cglibProxy.setTarget(ps4Factory);
       GameFactory proxy = (GameFactory) cglibProxy.getProxy();//此处生成了一个类似于静态代理的代理对象。可以看成是静态代理了。 由于是动态生成的,所以叫动态代理
       proxy.make();
       proxy.sall();
   }

测试结果

 invoke  start!!!!
Ps4  make。。。
invoke  end!!!!
invoke  start!!!!
Ps4  sall。。。
invoke  end!!!!

可以看到在每个方法执行之前都实现了,功能拓展。但是此模式要求被代理类要实现某一接口,并且代理类要实现InvocationHandler方法。

cglib动态代理

被代理类

public class User {
  public void know(){
      System.out.println(" i know !!");
  }
}

代理类

public class CglibProxyFactory implements MethodInterceptor {
 private Enhancer enhancer = new Enhancer();
 public Object getProxy(Class<?> clazz){
     enhancer.setSuperclass(clazz);
     enhancer.setCallback(this);
     return enhancer.create();
 }
 public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
     System.out.println("警卫正在通知领导!!");
     methodProxy.invokeSuper(o, objects);
     System.out.println("警卫通知领导完毕!!");
     return new Object();
 }
}

测试类

 public static void main(String[] args) {
       CglibProxyFactory proxy=new CglibProxyFactory();
       User userProxy = (User)proxy.getProxy(User.class);
       userProxy.know();
   }
警卫正在通知领导!!
i know !!
警卫通知领导完毕!!

在代理类没有实现任何接口的情况下也同样实现了功能拓展。

总结

jdk动态代理就是在与目标类实现同一接口的情况下,创建一个与被代理对象的一个兄弟类,在代理类被调到一个方法是,通过放射去被代理类执行。完成功能拓展。
cglib代理则是创建了一个与被代理类的一个子类,通过继承的规则,在子类中调用某一方法是,通过super来调用父类(被代理类)的方法。从而实现功能拓展。
所以在平时开发中,如果目标类实现类某一接口可以使用jdk动态代理。没有的话,就使用cglib代理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值