Spring 核心技术之一 AOP

什么是AOP

      AOP:(Aspect Oriented Programming),面向切面编程,是一个概念,并没有设定具体语言的实现

AOP的作用

      AOP哪些与业务无关,却为业务模块共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合行,并有利于未来的可操作行和可维护性。

AOP与OOP的区别

  • OOP引入封装,继承和多态等概念,建立一种对象层次结构,是针对业务处理过程的实体及其属性和行为进行抽象封装,以获得更加清晰高效的逻辑单元划分;OOP定义的是竖向的关系,即从上到下;
  • AOP是OOP(面向对象编程)的延续,是为分散的对象引入公共行为,是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。这两种设计思想在目标上有着本质的差异;AOP定义的是横向的关系,即从左到右

如何实现

实现AOP的技术,主要分为两大类:

  • 一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;
  • 二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。

相关概念

这里写图片描述

  • Cross Cutting Concern:

            是一种独立服务,它会遍布在系统的处理流程之中

  • Aspect

            对横切性关注点的模块化

  • Advice

            对横切行关注点的具体实现

  • Pointcut

            它定义类Advice应用到哪些JpinPoint上,对Spring来说是方法调用

  • JoinPoint

            Advice在应用程序上执行的点或时机,Spring只支持方法的JpinPoint

  • Weave

            将Advice应用到Target Object上的过程叫织入,Spring支持的是动态织入

  • Target Object

            Advice被应用的对象

  • Proxy

            Spring AOP默认使用JDK动态代理,它的代理是运行时创建,也可使用CGLIB代理

  • Introduction

            动态得为类添加方法


应用

      权限、错误处理、检查安全性、记录日志等

实现

过程:

  • 引入spring相关依赖包
  • 将横切行关注点模块化,即写为一个类
  • 指定Aspect,定义Advice和Pointcut

有两种实现方式:注解方式和配置文件方式

1.注解方式

      在配置文件中,启用Aspect对Annotation的支持

<aop:aspectj-autoproxy />

      Aspect模块:

//声明Aspect
@Aspect
public class SecurityHandler  {

    //该方法不是实际调用的,只是为了提供注解Pointcut,因为注解在类上,Pointcut的名称为addMethod()
    //此方法没有返回值和参数,该方法就是个标识,不进行调用
    //第一个*:返回值
    //第二个*:所有的add方法
    //..:方法参数
    @Pointcut("execution(* add*(..))")
    private void addAddMethod(){};

    //定义advice
    @Before("addAddMethod()")
    private void checkSecurity(){
        System.out.println("_______checkSecurity___________");
    }
}

      这样就实现了在所有的以add开头的方法执行前都会先执行,在此定义的checkSecurity()方法,即:

@Before("addAddMethod()")
private void checkSecurity(){
    System.out.println("_______checkSecurity___________");
}

      可以在Advice方法中加入JoinPoint参数,来获取客户端调用的方法名和方法的参数

2.配置文件方式:

    <bean id="securityHandler" class="com.bjpowernode.spring.SecurityHandler"></bean>

    <aop:config>
        <aop:aspect id="securityAspect" ref="securityHandler">
            <!-- 所有以add开头的方法 -->
            <!-- <aop:pointcut id ="addMethod" expression="execution(* add*(..))"/> -->
            <!-- 该包下的所有方法 -->
            <!-- <aop:pointcut id ="addMethod" expression="execution(* com.bjpowernode.spring.*.*(..))"/> -->
            <!-- 该包下所有类的add开后或del开头的方法 -->
            <aop:pointcut id ="addMethod" expression="execution(* com.bjpowernode.spring.*.add*(..)) || execution(* com.bjpowernode.spring.*.del*(..))"/>
            <aop:before method="checkSecurity" pointcut-ref="addMethod"/>
        </aop:aspect>
    </aop:config>

总结spring对AOP的支持:

  1. 如果目标对象实现了接口,在默认情况下会采用JDK动态代理实现AOP,也可强制使用CGLIB生成代理实现AOP
  2. 如果目标对象没有实现接口,就必须引入CGLIB,spring会在JKD的动态代理和CGLIB代理之间切换

JDK动态代理和CGLIB代理的区别:

  1. JDK动态代理实现了接口的类进行代理
  2. CGLIB代理可实现对类的代理,主要对指定的类生成一个子类

如何强制使用CGLIB代理:

  1. 加入CGLIB库
  2. 在配置文件中声明强制使用CGLIB代理(默认是使用的JDK代理)
<aop:aspectj-autoproxy proxy-target-class="true" />

总结

      AOP就是给多个不相关的同等级(所以是横切性)的类提供共同的服务,而这些服务与具体的类的业务逻辑是不相关的,这样减少了代码的书写,降低程序耦合

猜你喜欢

转载自blog.csdn.net/wrs120/article/details/79598958