• Spring AOP


    面向切面编程(AOP)通过提供另外一种思考程序结构的途经来弥补面向对象编程(OOP)的不足。在OOP中模块化的关键单元是类(classes),而在AOP中模块化的单元则是切面。切面能对关注点进行模块化,例如横切多个类型和对象的事务管理。(在AOP术语中通常称作横切(crosscutting)关注点。)

    AOP的基本概念

    切面(Aspect)

    一个关注点的模块化,是通知和切点的结合。通知和切点共同定义了切面的全部内容——它是什么,在何时和何处完成其功能。

    连接点(Joinpoint)

    连接点是在应用执行过程中能够插入切面的一个点。这个点可以是调用方法时、抛出异常时、甚至修改一个字段时。切面代码可以利用这些点插入到应用的正常流程之中,并添加新的行为。因为Spring基于代理实现AOP,所以只支持方法连接点。

    通知(Advice)

    在切面的某个特定的连接点上执行的动作。Spring切面可以应用6种类型的通知:

    1 前置通知(Before):在目标方法被调用之前调用通知功能;

    2 后置通知(After):在目标方法完成之后调用通知,此时不会关心方法的输出是什么;

    3 返回通知(After-returning):在目标方法成功执行之后调用通知;

    4 异常通知(After-throwing):在目标方法抛出异常后调用通知;

    5 环绕通知(Around):通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为。

    6 引入通知(Introduction):用来给一个类型声明额外的方法或属性。Spring允许引入新的接口(以及一个对应的实现)到任何被代理的对象。可以在无需修改现有的类的情况下,让它们具有新的行为和状态。

    切入点(Pointcut)

    切入点是匹配连接点的表达式。通知和一个切入点表达式关联,并在满足这个切入点的连接点上运行。一个切面并不需要通知应用的所有连接点。切点有助于缩小切面所通知的连接点的范围。

    目标对象(Target Object)

    被一个或者多个切面所通知的对象。也被称做被通知(advised)对象。 既然Spring AOP是通过运行时代理实现的,这个对象永远是一个被代理(proxied)对象。

    AOP代理(AOP Proxy)

    AOP框架创建的对象,用来实现切面(例如通知方法执行等等)。在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。

    织入(Weaving)

    织入是把切面应用到目标对象并创建新的代理对象的过程。切面在指定的连接点被织入到目标对象中。在目标对象的生命周期里有多个点可以进行织入:

    编译期:切面在目标类编译时被织入。这种方式需要特殊的编译器。AspectJ的织入编译器就是以这种方式织入切面的。

    类加载期:切面在目标类加载到JVM时被织入。这种方式需要特殊的类加载器(ClassLoader),它可以在目标类被引入应用之前增强该目标类的字节码。AspectJ 5的加载时织入(load-timeweaving,LTW)就支持以这种方式织入切面。

    运行期:切面在应用运行的某个时刻被织入。一般情况下,在织入切面时,AOP容器会为目标对象动态地创建一个代理对象。Spring AOP就是以这种方式织入切面的。

    示例代码:

    /**
     * 检查入参合法性
     * 
     * @author 喻聪
     * @date   2018-01-26
     * 
     */
    @Aspect
    public class ValidParamAspect { // Controller层切点 @Pointcut("execution (* com.yucong.controller..*.*(..))") public void aspect() { } @Before("aspect()") public void doBefore(JoinPoint jp) throws Throwable { Object[] args = jp.getArgs(); if(args != null && args.length > 1 ) { //取出第2个参数 Object obj = jp.getArgs()[1]; if(obj instanceof BindingResult) { BindingResult bindingResult = (BindingResult)obj; // 校验返回错误集合中的第一个错误信息 if (bindingResult.hasErrors()) { List<ObjectError> errors = bindingResult.getAllErrors(); throw new ParameterIllegalException(errors.get(0).getDefaultMessage()); } } } } }

    Spring提供了4种类型的AOP支持:

    基于代理的经典Spring AOP

    基于XML配置,曾经它的确非常棒。但是现在Spring提供了更简洁和干净的面向切面编程方式。引入了简单的声明式AOP和基于注解的AOP之后,Spring经典的AOP看起来就显得非常笨重和过于复杂。

    纯POJO切面

    借助Spring的aop命名空间,我们可以将纯POJO转换为切面。实际上,这些POJO只是提供了满足切点条件时所要调用的方法。遗憾的是,这种技术需要XML配置,但这的确是声明式地将对象转换为切面的简便方式。

    @AspectJ注解驱动的切面

    Spring借鉴了AspectJ的切面,以提供注解驱动的AOP。本质上,它依然是Spring基于代理的AOP,但是编程模型几乎与编写成熟的AspectJ注解切面完全一致。这种AOP风格的好处在于能够不使用XML来完成功能。

    需要导入aspectjweaver.jar,4.3.8依赖1.8.9

    注入式AspectJ切面

    如果AOP的**切点要求超出了方法**(如构造器或属性拦截),那么需要考虑使用AspectJ来实现切面。

    前三种都是Spring AOP实现的变体,Spring AOP构建在动态代理基础之上,因此,Spring对AOP的支持局限于方法拦截。

  • 相关阅读:
    全屏透明遮罩层
    理解Javascript__理解undefined和null
    JS 对象属性相关--检查属性、枚举属性等
    js 空正则匹配任意一个位置
    a 标签 download 和 target 不配合
    Array.prototype.filter(Boolean)
    页面操作表单不会调用表单 value 属性的 set 函数
    Babel6.x的安装
    html 事件处理程序中的代码在执行时,有权访问全局作用域中的任何代码。
    js 常用 DOM 元素宽高
  • 原文地址:https://www.cnblogs.com/yucongblog/p/11162901.html
Copyright © 2020-2023  润新知