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 }
原文地址:https://www.cnblogs.com/tdws/p/4237670.html