随笔分类
对 Aop的些许思考:
Aop实际上就是提供了一些横切点,供我们去进行一些插拔式的动作
Aspect实际是就是一些横切点的组织形式,而 Joinpoint其实就是方法执行过程中定义良好的一个点
so,Aspect其实就是定义了一个模块去组织 Joinpoint
Pointcut其实就是断言,Pointcut会去匹配 Joinpoint,匹配成功,则进行对应 Advice的执行,即将特定动作的 Advice织入 Joinpoint中去
AopProxy的实现不是 public的,其实也是根据某种方式进行的封装,外部通过判断后,通过某种调用去创建出具体的一个 AopProxy实现
对 Proxy.newProxyInstance()的些许思考
在以往中,任意 new的代码,无论是直接去 new方式,还是通过反射的方式去获取,实际上相应的结构是已经存在的了,即对比类元信息是存在的,但是 Jdk的动态dialing有点不同,这里是全新生成一个新的对象,在实际调用前,我们甚至不知道其内部结构是怎样的;
实际上这里面会根据一些信息,来去动态生成代理类的字节码,当然需要一些相关的类元信息了,如对应的 proxyName、interfaces、accessFlags,然后使用 ProxyGenerator.generateProxyClass来去生成其字节码,然后调用 defineclass0()方法将字节码通过类加载器加载到内存中,生成对应的类,这块说白了其实就是联动字节码与 jvm而已
详情可去看以往 Aop解读文章
为什么 Java动态代理无法满足 Aop的需要?
虽然 Java是推荐我们是面向接口进行编程,但 Java本质上还是面向类编程的,这里的类就包括了接口、抽象类、以及具体的类上去
so,在日常开发中,总是不可避免会存在这么情况,开发人员不写接口,直接写类或者说是直接去使用类的情况,那么 JDK动态代理此时便不能起作用了,因此,我们需要字节码提升的手段,来满足 Aop需要
因此,我们需要一些 字节码提升的手段,即在运行时、非编译时去创建新的 Class
在 Spring里面存在两种字节码提升的框架,一个是 ASM,一个 Cglib
ASM过于底层,直接去操作字节码;而 Cglib相对简单一些,能够轻松实现 Aop的拦截
Cglib其实就是依靠于 Enhancer,子类的生成依靠 Cglib,父类则是有我们来进行指定,接口同样
Spring Aop和 AspectJ Aop存在哪些区别?
-
AspectJ是较为完整的 Aop实现 (其强大主要依靠于其本身编译器实现编译器的字节码提升),而 Spring Aop则是部分实现
-
Spring Aop比 AspectJ使用更简单
-
Spring Aop整合 Spring IoC容器与 AspectJ注解
基于 IoC,更加容易实现基于 bean的代理
但是 AspectJ并不是直接和 IoC打通的,因此这里基于 Spring Aop的方式来进行使用,这里确实是提高了复用性;可以说 Spring Aop并没有去提升自己的 Api下很好的整合了 Aspectj
这样做的好处是?
可以在不改变代码的基础上,让同一套代码可以在 Spring Aop和 AspectJ都可以进行使用,这块我感觉可以来类比 "日志门面"
-
Spring Aop仅支持代理模式的 Aop
-
Spring Aop仅支持方法级别的 Joinpoints,而 AspectJ可以做到对字段的拦截
怎么来理解 Advice、Pointcut、Advisor?
Advice是一个动作,在执行前需要来关联一个断言,即 Pointcut,而 Pointcut本身不能直接来进行使用,即使用 Advisor去适配了 Pointcut与 Advvice
这里设计,个人理解,因为 Advice是 Aop联盟的,so,Spring需要进行适配,对应的便是 Advice,可以说 Advice和 Advisor是一 一对应的关系,但 Advice需要关联一个判断,so,Advisor可以去持有 Pointcut
这块玩法特别多,这块的设计理念其实就是基于 "适配器模式",这块可以类比下 Netty中 ChannelHandlerContext对 ChannelHandler的适配,适配的同时增加了些许功能,如掩码的定位,便于快速查找到下一个匹配的 ctx去执行对应操作