动态代理模式
来源:互联网 发布:skype官方下载 mac 编辑:程序博客网 时间:2024/05/23 10:27
最近在看项目中关于aop的一些东西,正好想起之前没毕业的时候去唯品会面试,面试官问我知不知道aop底层实现原理,当时真是一脸懵逼啊。现在工作后对aop怎么使用稍微了解了一点,也知道底层原理其实是动态代理,具体怎么实现还不是很清楚所以这篇就聊一聊动态代理设计模式。在这里分享一下之前无意中看到的大神对aop的比喻,感觉很有道理。
aop切面编程就是在常规的执行java类中方法前或执行后加入自定义的方法。比如你本来每天都去打酱油,去,打酱油,回。现在我每天在你打酱油路上等着,你去打酱油的时候我打你一顿,回来的时候给你点糖果吃。你根本不知道为什么我会在路上拦住打你。所以在切面中插入你自定义的方法,这个方法的执行和本身要执行的类方法无关系,也就是不是这个类的方法来调用你写的方法的,你写的方法什么时候执行都是要通过在配置指定。我打完你,你该打酱油还是去打酱油,当然我如果是拦住你让你酱油打少点,你打酱油的时候还是会打那么多,但是在你打完酱油回来的时候我可以把你的酱油倒些出去,所以嵌入的自定义方法对要调用的类方法本身没有影响,但是可以操纵这个方法的返结果或者处理结果。
上面这段话我觉得还是很形象的,我现在接触到的aop的应用一般是日志以及异常处理,session之类的还不是很了解。
按照我现在的理解,我觉得动态代理只要有两个地方比较重要,一个是InvocationHandler接口,还有一个是Proxy类。
为什么要有代理模式?
在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。比如我们买二手房,往往只能通过中介,因为我们这时候不能直接接触到客户,但是中介可以。
代理模式代码如下:
首先建立buyHouse接口
public interface BuyHouse {public void buyHouse();}建立一个realSubject
public class RealSubject implements BuyHouse {@Overridepublic void buyHouse() {System.out.println("我要在外滩旁边买一套房");}}定义一个动态代理类,实现InvocationHandler接口
import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;public class DynamicProxy implements InvocationHandler {private Object object;public DynamicProxy(Object object){this.object = object;}@Overridepublic Object invoke(Object paramObject, Method paramMethod, Object[] paramArrayOfObject) throws Throwable {//实现真实对象前可以添加自己想实现的业务,实际可能是日志,权限验证等等System.out.println("你必须给我中介费先付5w");//实现真实对象方法paramMethod.invoke(object, paramArrayOfObject);//之后继续实现一些业务,可以通过回调System.out.println("中介费尾款给我");return null;}}最后看一下测试类
import java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy;public class TestDynamicProxy {public static void main(String[] args) {// TODO Auto-generated method stubBuyHouse buyHouse = new RealSubject();InvocationHandler handler = new DynamicProxy(buyHouse);BuyHouse proxyHouse = (BuyHouse) Proxy.newProxyInstance(handler.getClass().getClassLoader(), buyHouse.getClass().getInterfaces(), handler);proxyHouse.buyHouse();}}控制台输出结果为
你必须给我中介费先付5w
我要在外滩旁边买一套房
中介费尾款给我
到此建议动态代理结束,我们看下jdk1.8中InvocationHandler以及Proxy源码。首先是InvocationHandler
public abstract interface InvocationHandler{ public abstract Object invoke(Object paramObject, Method paramMethod, Object[] paramArrayOfObject) throws Throwable;}InvocationHandler接口中只有一个invoke方法,该方法三个参数分别指 真实对象,调用对象的method方法,最后一个不是很明白作用,待以后补充,或者知道的大神解答下
Proxy
Proxy类在jdk1.8中定义的属性如图,这里我们主要使用newProxyInstance这个方法(我也不知道为什么,我一看到Instance这个就想到反射),代码如下
public static Object newProxyInstance(ClassLoader paramClassLoader, Class<?>[] paramArrayOfClass, InvocationHandler paramInvocationHandler) throws IllegalArgumentException { Objects.requireNonNull(paramInvocationHandler); Class[] arrayOfClass = (Class[])paramArrayOfClass.clone(); SecurityManager localSecurityManager = System.getSecurityManager(); if (localSecurityManager != null) { checkProxyAccess(Reflection.getCallerClass(), paramClassLoader, arrayOfClass); } Class localClass = getProxyClass0(paramClassLoader, arrayOfClass); try { if (localSecurityManager != null) { checkNewProxyPermission(Reflection.getCallerClass(), localClass); } Constructor localConstructor = localClass.getConstructor(constructorParams); localObject = paramInvocationHandler; if (!Modifier.isPublic(localClass.getModifiers())) { AccessController.doPrivileged(new PrivilegedAction() { public Void run() { this.val$cons.setAccessible(true); return null; } }); } return localConstructor.newInstance(new Object[] { paramInvocationHandler }); } catch (IllegalAccessException|InstantiationException localIllegalAccessException) { throw new InternalError(localIllegalAccessException.toString(), localIllegalAccessException); } catch (InvocationTargetException localInvocationTargetException) { Object localObject = localInvocationTargetException.getCause(); if ((localObject instanceof RuntimeException)) { throw ((RuntimeException)localObject); } throw new InternalError(((Throwable)localObject).toString(), (Throwable)localObject); } catch (NoSuchMethodException localNoSuchMethodException) { throw new InternalError(localNoSuchMethodException.toString(), localNoSuchMethodException); } }这段代码我只能看个大体,基本就是利用反射获取构造函数对象并生成一个代理类,看一下他的三个参数:
ClassLoader paramClassLoader, Class<?>[] paramArrayOfClass, InvocationHandler paramInvocationHandler)paramClassLoader指类装载器,paramArrayOfClass 一般表示需要提供给代理对象的需要的接口,最后InvocationHandler不多做介绍了。
- 代理模式--动态代理
- 代理模式 & 动态代理
- 代理模式--动态代理
- 代理模式(动态代理)
- 代理模式-动态代理
- 代理模式-动态代理
- 代理模式动态代理
- 代理模式-动态代理
- 代理模式 -动态代理
- 代理模式---动态代理
- 代理模式-动态代理
- 代理模式之动态代理
- java代理模式--动态代理
- 代理模式之动态代理
- 代理模式之动态代理
- 代理模式之动态代理
- 代理模式和动态代理
- 代理模式与动态代理
- bzoj2190【线性筛】
- RxJava 驯服数据流之 hot & cold Observable
- android在hal下 如何获得对一个内核节点的访问权限
- angular2实现图片轮播
- Tomcat服务器顶层结构和启动过程
- 动态代理模式
- 圆角等离屏渲染问题
- 如何在Jenkins CI 里调试
- 大型网站架构体系的演变(上)
- Maven(4)maven依赖
- 手机设计过程
- 1613-3-傅溥衍 总结《2016年12月8日》【连续第六十九天总结】
- 仿百度壁纸客户端(三)——首页单向,双向事件冲突处理,壁纸列表的实现
- 3.Draftjs 学习笔记-Entities