代理(一)静态代理,动态代理
2018-12-24 09:10:07来源:博客园 阅读 ()
昨天面试碰到了面试官问spring的时候,问完ioc,然后下个问题我以为是aop,后来才听清是动态代理,感觉回答的不是太好,也是好久不接触
1.静态代理
代理模式也就委托模式。
三个角色:
1. Subject抽象主题角色:接口
2. RealSubject具体主题角色:接口的实现类,业务逻辑的具体执行者
3. Proxy代理主题角色:也叫做委托类,代理类。它负责对真实角色的应用,负责真实角色前后前后做预处理和善后处理。
在这里面Subject是一个借口,里面有一个Request()方法,RealSubject类实现了Subject这个接口,并且实现了request()方法,而在Proxy也实现了Subject接口,proxy里面还有一个变量Subject,可以通过构造函数将RealSubject注入,在实现request方法时,其实是调用的是Realsubject里面的request方法,在调用request()方法前后可以调用一些其他的方法。
下面是具体的代码
Subject.java
public interface Subject { //定义一个方法 public void request(); }
RealSubject.java
public class RealSubject implements Subject { @Override public void request() { //业务逻辑处理 } }
Proxy.java
public class Proxy implements Subject { private Subject subject = null; public Proxy(Subject subject){ this.subject = subject; } @Override public void request() { before(); subject.request(); after(); } public void before(){ //do something } public void after(){ //do something } }
代理模式的使用场景
为什么要使用代理呢?想想现实世界吧,打官司为什么要找个律师?因为你不想参与中间过程的是是非非,只要完成自己的答辩就行了,其他的比如事前调查、事后调查都由律师搞定,这就是为了减轻你的负担。代理模式的使用场景非常多,可以看见Spring aop,这是非常典型的动态代理
二:动态代理
动态代理是在实现阶段不用关心代理谁,而在运行阶段才指定代理哪一个对象。相对来说,自己写代理类的方式就叫静态代理
划重点,在运行阶段指定哪一个对象
具体代码,逻辑待会再说
抽象主题
public interface Subject { /** * //业务操作 * @param str */ void doSomething(String str); /** * 吃 * */ void eat(String str); }
真实主题
public class RealSubject implements Subject { @Override public void doSomething(String str) { System.out.println("do something!---->" + str); } @Override public void eat(String str) { System.out.println("今天晚上吃"+str); } }
动态代理的handler类
public class MyInvocationHandler implements InvocationHandler { /** * 被代理的对象 */ private Object target; public MyInvocationHandler(Object target){ this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //log Before System.out.println("log before:"+"method: "+method.getName()+ "return :"+method.getReturnType().getSimpleName()); Object result = method.invoke(target,args); System.out.println("log after: "+new Date(System.currentTimeMillis())); return result; } }
动态代理类
public class DynamicProxy<T> { public static <T> T newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler handler){ //返回目标,并返回结果 return (T) Proxy.newProxyInstance(loader,interfaces,handler); } }
动态代理的场景类
public class Client { public static void main(String[] args) throws IOException { //定义一个代理类 Subject subject = new RealSubject(); //定义一个Handler InvocationHandler handler = new MyInvocationHandler(subject); //定义主题的代理 Subject proxy = DynamicProxy.newProxyInstance(subject.getClass().getClassLoader(),subject.getClass().getInterfaces(),handler); //代理的行为 System.out.println(proxy.getClass().getCanonicalName()); proxy.doSomething("finish"); proxy.eat("香锅里辣家的麻辣香锅"); //此处可以将 byte[] proxyClass = ProxyGenerator.generateProxyClass(proxy.getClass() .getSimpleName(), proxy.getClass().getInterfaces()); //将字节码文件保存到D盘,文件名为$Proxy0.class FileOutputStream outputStream = new FileOutputStream(new File( "d:\\$Proxy0.class")); outputStream.write(proxyClass); outputStream.flush(); outputStream.close(); } }
分析过程:
Subject proxy = DynamicProxy.newProxyInstance(subject.getClass().getClassLoader(),subject.getClass().getInterfaces(),handler);
在我们使用proxy.doSomthing(args);
proxy.eat(args);*
***我们可以想象出,DynamicProxy.newProxyInstance(args)这个方法返回了一个proxy对象***
我们可以看到是调用了这个方法
newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
@CallerSensitive public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException { Objects.requireNonNull(h); final Class<?>[] intfs = interfaces.clone(); final SecurityManager sm = System.getSecurityManager(); if (sm != null) { checkProxyAccess(Reflection.getCallerClass(), loader, intfs); } /* * Look up or generate the designated proxy class. */ Class<?> cl = getProxyClass0(loader, intfs); /* * Invoke its constructor with the designated invocation handler. */ try { if (sm != null) { checkNewProxyPermission(Reflection.getCallerClass(), cl); } final Constructor<?> cons = cl.getConstructor(constructorParams); final InvocationHandler ih = h; if (!Modifier.isPublic(cl.getModifiers())) { AccessController.doPrivileged(new PrivilegedAction<Void>() { public Void run() { cons.setAccessible(true); return null; } }); } return cons.newInstance(new Object[]{h}); } catch (IllegalAccessException|InstantiationException e) { throw new InternalError(e.toString(), e); } catch (InvocationTargetException e) { Throwable t = e.getCause(); if (t instanceof RuntimeException) { throw (RuntimeException) t; } else { throw new InternalError(t.toString(), t); } } catch (NoSuchMethodException e) { throw new InternalError(e.toString(), e); } }最后这个方法会在运行中生成一个
类,名字叫:com.sun.proxy.$Proxy0
而我们并没有找到这个类,可以通过
ProxyGenerator.generateProxyClass
将这个运行中生成的类打印出来,,我们来看看,这个类是什么样子的
$Proxy0.class,反编译
public final class $Proxy0 extends Proxy implements Subject { private static Method m1; private static Method m2; private static Method m3; private static Method m4; private static Method m0; public $Proxy0(InvocationHandler var1) throws { super(var1); } public final boolean equals(Object var1) throws { try { return (Boolean)super.h.invoke(this, m1, new Object[]{var1}); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } } public final String toString() throws { try { return (String)super.h.invoke(this, m2, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } public final void doSomething(String var1) throws { try { super.h.invoke(this, m3, new Object[]{var1}); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } } public final void eat(String var1) throws { try { super.h.invoke(this, m4, new Object[]{var1}); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } } public final int hashCode() throws { try { return (Integer)super.h.invoke(this, m0, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } static { try { m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object")); m2 = Class.forName("java.lang.Object").getMethod("toString"); m3 = Class.forName("com.husky.dynamicproxy.Subject").getMethod("doSomething", Class.forName("java.lang.String")); m4 = Class.forName("com.husky.dynamicproxy.Subject").getMethod("eat", Class.forName("java.lang.String")); m0 = Class.forName("java.lang.Object").getMethod("hashCode"); } catch (NoSuchMethodException var2) { throw new NoSuchMethodError(var2.getMessage()); } catch (ClassNotFoundException var3) { throw new NoClassDefFoundError(var3.getMessage()); } } }
首先$Proxy0这个类extends Proxy implements Subject
有一个静态代码块,会反射生成Method类,也就是给 $Proxy这个类的变量赋值
举例我在调用proxy.doSomething()这个方法时
我们其实是调用
public final void doSomething(String var1) throws { try { super.h.invoke(this, m3, new Object[]{var1}); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } }
调用的是super.h.invoke(this, m3, new Object[]{var1});
这个h也就是实现InvocationHandler接口的MyInvocationHandler类。将这个$Proxy0,m3, new Object[]{var1}这些变量传过去
具体代码:https://github.com/pompeii666/proxy
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
下一篇:购买国外服务器地址
- 代理项 Surrogate 2020-06-11
- Spring Boot 2.3.0 新特性Redis 拓扑动态感应 2020-06-11
- SpringBoot通过web页面动态控制定时任务的启动、停止、创建 2020-06-09
- Spring Cloud Gateway 扩展支持动态限流 2020-06-08
- CGLIB动态代理机制,各个方面都有写到 2020-06-04
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash