zoukankan      html  css  js  c++  java
  • Java 从静态代理到动态代理

    先举个静态代理的例子,可能多少有些不恰当,不过本次学习记录,重点不在于通信协议。 比如你在一个机房里,你不能联网,只能连通过一台能连公网的代理机器上网。你发送了一个http请求,将由代理帮你上网。

    首先有一个HttpMessage接口,InternetProxy(公网代理)和LANMessage(局域网发消息) 都实现HttpMessage接口。公网代理将代理LANMessage上网。实际上代理模式,增强了原来对象的方法,并且无侵入性,不需要修改原有代码。

    1 public interface HttpMessage {
    2     void sendMsg(String msg);
    3 }
    1 public class LANMessage implements  HttpMessage {
    2     @Override
    3     public void sendMsg(String msg) {
    4         System.out.println("lan send msg");
    5     }
    6 }
     1 public class InternetProxy implements HttpMessage {
     2 
     3     //被代理的对象
     4     LANMessage message;
     5 
     6     @Override
     7     public void sendMsg(String msg) {
     8         before();
     9         message.sendMsg(msg);
    10         after();
    11     }
    12 
    13     void before() {
    14         System.out.println("prepare internet msg");
    15     }
    16 
    17     void after() {
    18         System.out.println("after internet  msg");
    19     }
    20 }

    上面只是一个静态代理增强对象的示例。当代码中有大量的 需要增强,甚至动态增强的代码时,这种代理类,会遍布项目中到处都是,并且当接口改变,代理类和实现类都要一并修改。所以有了动态代理。

    jdk动态代理:

    无需创建代理类,直接使用,会生成class文件,class文件也将被加载到内存中的Class对象,有了class对象,就有了类的所有信息,在调用方法的时候,动态代理相当于拦截了我们所有的调用,你可以在invoke中对目标对象和其方法进行增强。也应该不难想到,new instance 基本上就是通过拿到的class对象,来拿到其Contrustor 来构造对象。如果反编译生成的class文件,也可以看到在调用方法的时候,刚实现的invoke方法会被调用。 Class对象在手,天下我有~

     1 public class TestProxy {
     2 
     3     LANMessage msg=new LANMessage();
     4     @Test
     5     public void  fun(){
     6         HttpMessage message=(HttpMessage) Proxy.newProxyInstance(LANMessage.class.getClassLoader(), LANMessage.class.getInterfaces(), new InvocationHandler() {
     7             @Override
     8             public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
     9                 System.out.println("before");
    10                 Object res= method.invoke(msg,args);
    11                 System.out.println("after");
    12                 return res;
    13             }
    14         });
    15         message.sendMsg("hello");
    16     }
    17 }

    CGLib方式:

    该方式可代理任何类 不需要提供接口。其生成的class字节码文件,反编译后可以看到 它生成的是委托类的子类。

     1 public class TestProxy {
     2 
     3     LANMessage msg = new LANMessage();
     4 
     5     @Test
     6     public void fun() {
     7 
     8         CGLibProxy proxy=new CGLibProxy();
     9         HttpMessage msg=(HttpMessage) proxy.getProxy(LANMessage.class);
    10         msg.sendMsg("hi");
    11     }
    12 }
    13 
    14 class CGLibProxy implements MethodInterceptor {
    15 
    16     public Object getProxy(Class<?> clazz) {
    17         return Enhancer.create(clazz, this);
    18     }
    19 
    20     @Override
    21     public Object intercept(Object o, Method method, Object[] args, MethodProxy proxy) throws Throwable {
    22         System.out.println("before");
    23         Object res = proxy.invokeSuper(o, args);
    24         System.out.println("afert");
    25         return  res;
    26     }
    27 }
  • 相关阅读:
    Android 自定义ProgressDialog
    Android 设置TextView字体颜色
    Android 隐藏EditText的焦点
    Android TextView点击效果
    区间问题 codeforces 422c+hiho区间求差问
    hdu 5651 重复全排列+逆元
    hdu 1576
    C Looooops
    扩展欧几里得模板
    hdu 6025(女生赛)
  • 原文地址:https://www.cnblogs.com/tdws/p/4237670.html
Copyright © 2011-2022 走看看