Spring Aop

Spring Aop

动态代理

实现方式

JDK动态代理、cglib动态代理

动态代理的作用

  • 在目标类源代码不改变的情况下,增加功能;
  • 减少代码的重复;
  • 专注于业务逻辑代码;
  • 解耦合,让你的业务功能和日志、事务与非业务功能分离。

Aop面向切面编程

基于动态代理的,可以使用JDK、cglib两种代理方式。

Aop就是动态代理的规范化,把动态代理的实现步骤、方式都定义好,让开发人员所用动态代理统一。

AOP(Aspect Orient Programming)面向切面编程。

  • Aspect:切面,利用动态代理给目标类增加的功能就是切面,如打印日志等;

    切面的特点:

    • 一般都是非业务方法,可以独立使用;

OOP:面向对象编程

如何理解面向切面编程?

  • 需要在分析项目时找出切面;
  • 合理地安排切面的执行时间,(在目标方法之前还是之后);
  • 合理地安排切面执行的位置,在哪个类、哪个方法增项功能。

术语:

  • Advice:通知,切面的工作被称为通知,通知定义了切面是什么以及何时使用

    Spring可以应用五种类型的通知:

    • 前置通知(Before):在目标方法被调用之前调用通知功能;
    • 后置通知(After):在目标方法完成之后调用通知,此时不会关心方法的输出是什么;
    • 返回通知(After-returning):在目标方法成功执行之后调用通知;
    • 异常通知(After-throwing):在目标方法抛出异常后调用通知;
    • 环绕通知(Around):通知包裹了被通知的方法,在通知的方法调用之前和调用之后执行自定义行为;
  • JoinPoint:连接点,是指在应用执行过程中能够插入切面的一个点,切面代码可以利用这些点插入到应用的正常流程之中,已添加新行为;

  • Pointcut:切点,如果说通知定义了切面的什么何时,则切点则定义了何处,即切面插入的一个或多个连接点;

  • Aspect:切面,是通知与切入点的结合,通知和切入点共同定义了切面的全部内容——它是什么,在何时和何处完成其功能;

  • Introduction:引入,

  • Weaving:织入,织入是把切面应用到目标对象并创建新的代理对象的过程,切面在指定的连接点(即切点)被织入到目标对象中。

一个切面的三个关键要素:

  • 切面的功能代码,切面是干什么的;
  • 切面的执行位置,使用Pointcut表示切面执行的位置;
  • 切面执行的时间,使用Advice表示时间——在目标方法之前还是之后。

AOP的实现:

AOP是一个规范,是动态代理的一个规范化、一个标准

aop的技术实现框架:

  • spring:spring在内部实现了aop规范,能做aop的工作,主要在事务处理时使用aop,但在项目开发过程中很少使用spring的aop,因为笨重

  • aspectJ:一个开源的专门做aop的框架,spring框架中集成了aspectJ框架,通过spring就可使用aspectJ的功能

    aspectJ框架实现aop的两种方式:

    • 使用xml的配置文件:用于配置全局事务;
    • 使用注解(项目中实现aop功能一般都是用注解),aspectJ有5个注解。

aspectJ框架的使用:

  1. 切面的执行时间,这个执行时间在规范中称Advice(通知,增强)

    在aspectJ中使用注解表示:

    • @Before
    • @AfterReturning
    • @Around
    • @AfterThrowing
    • @After

    也可使用xml配置文件中的标签。

  2. 表示切面执行的位置,使用切入点表达式execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?)

    解释:

    • modifiers-pattern:访问权限类型
    • ret-type-pattern:返回值类型
    • declaring-type-pattern:全类名
    • name-pattern(param-pattern):方法名(参数类型和参数个数)
    • throws-pattern:抛出异常类型
    • ?:表示可选部分

    总结:excution(访问权限 返回值类型 方法声明(参数) 抛出异常),加粗部分不可省略。

关于通配符:

符号 意义
* 0至多个任意字符
.. 用在方法参数中:表示任意多个参数;用在包名后:表示当前包及其子包路径
+ 用在类名后表示当前类即其子类;用在接口后表示当前接口及其实现类。
1
2
3
4
jdbc.driver = com.mysql.cj.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/stu?serverTimezone=GMT%2B8
jdbc.username = root
jdbc.password = xxxxx