Spring学习笔记之AOP

123 阅读5分钟

第一步,首先说问题,表明这个技术诞生的原因

§  OOP面向对象编程存在的问题

AOP指面向切面编程,可以看作OOP面向对象编程的一种补充完善。OOP引入了封装、继承、多态等概念建立具有层级关系的对象模型,适合定义纵向关系。但不适合定义横向关系,例如日志功能。日志功能往往散布于核心业务逻辑代码中的各个地方,导致大量代码重复,不利于各个模块的复用(这一点对于go项目里面体现的很明显,散布于各处的log代码,dao层里面有,service层里面有,controller层里面也有)。

§  AOP针对这个问题而出现

AOP技术恰恰相反,它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性

§  www.cnblogs.com/xrq730/p/49…

o   第二步,解释技术中的基本概念,以及简单使用方式

§  AOP中引入了一些相关概念

·       Advice:增强,就是一段执行某个功能的代码

·       连结点:任何方法执行时的那一刻,都可以是连结点

·       切点:是一种描述信息,规定了哪些 join point 可以执行哪些 advice

·       目标对象:织入 advice 的目标对象. 目标对象也被称为 advised object.

·       代理对象:一个类被 AOP 织入 advice, 就会产生一个结果类, 它是融合了原类和增强逻辑的代理类

·       织入:将 aspect 和其他对象连接起来, 并创建 adviced object 的过程

o   动态代理织入, 在运行期为目标类添加增强(Advice)生成子类的方式??

o   Spring 采用动态代理织入, 而AspectJ采用编译器织入和类装载期织入

·       Advice类型:

o   before advice, 在 join point 前被执行的 advice.

o   after return advice, 在一个 join point 正常返回后执行的 advice

o   after throwing advice, 当一个 join point 抛出异常后执行的 advice

o   after(final) advice, 无论一个 join point 是正常退出还是发生了异常, 都会被执行的 advice

o   around advice, 在 join point 前和 joint point 退出后都执行的 advice. 这个是最常用的 advice

§  AOP使用例子,在现在用SpringBoot框架的情况下,都是用注解

·       @ Aspect, @ PointCut, @ Before, @ After, @ AfterReturning, @ AfterThrowing, @ Around

o   第三步,介绍技术的原理

§  AOP低层使用代理模式实现,代理模式以及Java中的代理模式

·       简单理解:就是在原始对象的基础上前后增加一些功能,形成一个增强版的代理类对象

image.png

·       在java中,根据代理创建的时间,可以分为静态代理和动态代理

o   静态代理:代理类已经写好了,在程序运行前代理类的 .class 文件就已经存在了

§  静态代理的问题:一个代理只能服务于一个特定的业务实现类

o   动态代理(最重要的,AOP默认使用JDK动态代理):动态代理可以帮助我们仅仅在需要的时候再创建代理类,减少资源浪费,此外由于动态代理是一个模板的形式,也可以减少程序的代码量

§  java中实现动态代理的步骤、实现方式(这个地方不好粘代码,看idea里面的吧)

§  segmentfault.com/a/119000004…

o   Cglib代理,它的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强。使用cglib实现动态代理,完全不受代理类必须实现接口的限制。

image.png

image.png

§  developer.huawei.com/consumer/cn…

www.cnblogs.com/tuyang1129/…

基本概念

  • Joinpoint
    • Spring AOP只支持方法执行类型的JoinPoint
  • Pointcut
    • AOP中的顶级接口之一(org.springframework.aop.Pointcut),用来匹配哪些Joinpoint可以织入
    • 规定了两个方法
    • ClassFilter getClassFilter():对JointPoint所处对象进行Class级别的类型匹配
    • MethodMatcher getMethodMatcher():对JointPoint进行方法级别的匹配
  • Advice
    • 代表织入JointPoint的横切逻辑,如果将Aspect比作Class,那么Advice即使Method
    • 根据执行实际分为三种Advice:MethodBeforeAdvice,AfterReturningAdvice,ThrowsAdvice,即Advice的三个子接口
  • Interceptor
    • AOP Alliance对Around Advice的叫法,拦截器中封装了Advice,与Advice对应,也有三种拦截器分别封装对应的Advice,即,MethodBeforeAdviceInterceptor,AfterReturningAdviceInterceptor,ThrowsAdviceInterceptor三个实现类
    • 实现类中包含了Advice对象和invoke()方法,不同的Advice增强位置invoke略有区别
    • MethodBeforeAdviceInterceptor源码和UML图:
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {
        private MethodBeforeAdvice advice;
        /**

         * Create a new MethodBeforeAdviceInterceptor for the given advice.

         * @param advice the MethodBeforeAdvice to wrap

         */
        public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
                 Assert.notNull(advice, "Advice must not be null");
                 this.advice = advice;
        }

        @Override
        public Object invoke(MethodInvocation mi) throws Throwable {
                 this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
                 return mi.proceed();
        }
}

image.png

  • Introduction
    • 一种特殊的Advice,和根据JointPoint执行时机不同而区别的Advice不同,而是根据可以完成的功能而区分
  • Aspect
    • PointCut和Advice的封装(即封装了哪些地方进行拦截,以及拦截后执行什么操作),在AOP Alliance中被称为Advisor
  • 织入和织入器
    • ProxyFactory
  • Target
    • 构造器输入一个Object,类中包含一个Object属性,即输入bean对其进行简单的封装,基本没有啥功能
    • 和构造器模式中的Target不一样