作用:控制对对象的访问,保护对象,增强对象功能
动态代理与静态代理
简单理解:静态代理是硬编码,动态代理不是
JDK动态代理写法及原理分析:
写法:
1,需要代理的类 要实现一个定义接口,类功能通过接口定义
2,代理逻辑handler类,需要实现jdk动态代理接口InvocationHandler,作为代理handler类, 并实现invoke方法
3,提供代理类获取方法 通过jdk代理工具Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(),this)方法获取,入参为Object可以直接将需要代理的实力传入
4,invoke方法实现逻辑,直接根据入参Method调用调用代理类方法,method.invoke(this.target,args),可以拓展前置后置,接收方法返回值。
5,返回的代理类一定是接口的实现类,所以可以直接强转,然后就行调用。
原理:
一,代理类的生成:通过ClassLoader类加载器去磁盘读取类文件,在内存中生成一个extend了jdk的Proxy并且实现需要代理类定义的接口的代理类,将生成的代理类编译成.class文件并加载进jvm,返回代理对象。
二,代理类存在引用属性InvocationHandler h, newProxyInstance方法将当前handler赋值给代理类的h。
三,代理类结构:实现了接口的所有方法,方法的获取方式通过类的反射直接赋值。
四,每个方法实现是h调用invoke方法,方法入参为当前代理类,方法,以及参数。
五,外部程序运行,代理类调用实现了接口的方法,代理类内部的h调用invoke方法,invoke方法逻辑是直接执行需要被代理类的指定方法,达到了动态代理的效果。
Cglib动态代理写法及原理分析:
1,定义一个类 实现java反射包的MethodInterceptor接口,并且实现intercept方法.
2, intercept方法中根据MethodProxy调用父类方法
3,提供一个获取代理类的方法,入参为Class,内部直击根据Enhancer生成一个继承子类,作为代理类返回。
4,代理类重写了父类的方法,方法内部判断是否存在实现了MethodInterceptor的实现类,存在便拦截,调用intercept方法(Cglib代理类满足这一条件),根据MethodProxy调用父类方法,达到代理类的效果。此处违背了里式替换原则,不过方法内部不论是调用incepter还是直接super方法 都是调用父类方法。此处违背里式替换原则,最终调用的还是父类方法,逻辑不变,是为了aop前置后置,此处为个人观点
比较:
JDK动态代理基于实现,需要被代理类实现一个抽象接口,Cglib直接继承需要代理类,对需要代理类没有要求,但是Cglib会忽略父类中的final方法,需要注意。
Cglib动态代理性能更高,因为内部没有使用反射
使用场景:SpringAop中的切面编程内部实现就是通过代理,当Bean有实现接口时,就会使用jdk动态代理,没有实现结构,通过Cglib做动态代理
原文:https://www.cnblogs.com/xianyi/p/14670594.html