AOP的基本概念

(1)Aspect(切面):通常是一个类,里面可以定义切入点和通知

(2)JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用

(3)Advice(通知):AOP在特定的切入点上执行的增强处理,有before,after,afterReturning,afterThrowing,around

(4)Pointcut(切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式

(5)AOP代理:

AOP框架创建的对象,代理就是目标对象的加强。

Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类

实现代理的两种代理方式:

静态代理(个人理解)

针对具体的类编写代理类。

针对一个接口编写一个代理类。

动态代理

而动态代理也可以分为2种,

一种是JDK Proxy,另外一种是cglib代理。

Spring对于有接口的类使用JDK Proxy,对于无接口和抽象类用Cglib代理,虽然Cglib可以进行代理,但是Cglib代理是有例外,

就是代理类中不能出现final修饰的类或者类中有final修饰的方法。

aop作用

AOP(Aspect-Oriented Programming:面向切面编程)能够将那些与业务无关,

却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,

便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。

Spring AOP就是基于动态代理的,

如果要代理的对象,实现了某个接口,那么Spring AOP会使用JDK Proxy,去创建代理对象,

而对于没有实现接口的对象,就无法使用 JDK Proxy 去进行代理了,

这时候Spring AOP会使用Cglib ,这时候Spring AOP会使用 Cglib 生成一个被代理对象的子类来作为代理

如下图所示:

aop切面原理 java aop的切面和切点_连接点

当然你也可以使用 AspectJ ,Spring AOP 已经集成了AspectJ ,

AspectJ 应该算的上是 Java 生态系统中最完整的 AOP 框架了。

使用 AOP 之后我们可以把一些通用功能抽象出来,在需要用到的地方直接使用即可,

这样大大简化了代码量。我们需要增加新功能时也方便,这样也提高了系统扩展性。

日志功能、事务管理等等场景都用到了 AOP 。

Spring AOP原理

被我们横切出来的逻辑代码融合到业务逻辑中,来完成和之前(没抽取前)一样的功能

没有学Spring AOP之前,我们就可以使用代理来完成。

代理能干嘛?代理可以帮我们增强对象的行为!使用动态代理实质上就是调用时拦截对象方法,对方法进行改造、增强!

 

其实Spring AOP的底层原理就是动态代理!

Spring AOP使用纯Java实现,它不需要专门的编译过程,也不需要特殊的类装载器,它在运行期通过代理方式向目标类织入增强代码。

在Spring中可以无缝地将Spring AOP、IoC和AspectJ整合在一起。

 

在Java中动态代理有两种方式:

JDK动态代理

CGLib动态代理

aop切面原理 java aop的切面和切点_连接点_02

JDK动态代理是需要实现某个接口了,而我们类未必全部会有接口,于是CGLib代理就有了

CGLib代理其生成的动态代理对象是目标类的子类

 

Spring AOP默认是使用JDK动态代理,如果代理的类没有接口则会使用CGLib代理。

 

那么JDK代理和CGLib代理我们该用哪个呢??在《精通Spring4.x 企业应用开发实战》给出了建议:

如果是单例的我们最好使用CGLib代理,如果是多例的我们最好使用JDK代理

原因:

  • JDK在创建代理对象时的性能要高于CGLib代理,而生成代理对象的运行性能却比CGLib的低。
  • 如果是单例的代理,推荐使用CGLib

看到这里我们就应该知道什么是Spring AOP(面向切面编程)了:

将相同逻辑的重复代码横向抽取出来,使用动态代理技术将这些重复代码织入到目标对象方法中,实现和原来一样的功能。

这样一来,我们就在写业务时只关心业务代码,而不用关心与业务无关的代码

AOP的术语

嗯,AOP搞了好几个术语出来~~两本书都有讲解这些术语,我会尽量让大家看得明白的:

连接点(Join point):

能够被拦截的地方:Spring AOP是基于动态代理的,所以是方法拦截的。每个成员方法都可以称之为连接点~

 

切点(Poincut):

具体定位的连接点:上面也说了,每个方法都可以称之为连接点,我们具体定位到某一个方法就成为切点。

增强/通知(Advice):

表示添加到切点的一段逻辑代码,并定位连接点的方位信息。

简单来说就定义了是干什么的,具体是在哪干

Spring AOP提供了5种Advice类型给我们:前置、后置、返回、异常、环绕给我们使用!

织入(Weaving):

将增强/通知添加到目标类的具体连接点上的过程。

引入/引介(Introduction):

引入/引介允许我们向现有的类添加新方法或属性。是一种特殊的增强!

切面(Aspect):

切面由切点和增强/通知组成,它既包括了横切逻辑的定义、也包括了连接点的定义。

在《Spring 实战 (第4版)》给出的总结是这样子的:

通知/增强包含了需要用于多个应用对象的横切行为;连接点是程序执行过程中能够应用通知的所有点;

切点定义了通知/增强被应用的具体位置。其中关键的是切点定义了哪些连接点会得到通知/增强。

Spring AOP 和 AspectJ AOP 有什么区别

Spring AOP 属于运行时增强,而 AspectJ 是编译时增强。

Spring AOP 基于代理(Proxying),而 AspectJ 基于字节码操作(Bytecode Manipulation)。

Spring AOP 已经集成了 AspectJ ,AspectJ 应该算的上是 Java 生态系统中最完整的 AOP 框架了。

AspectJ 相比于 Spring AOP 功能更加强大,但是 Spring AOP 相对来说更简单,

如果我们的切面比较少,那么两者性能差异不大。

但是,当切面太多的话,最好选择 AspectJ ,它比Spring AOP 快很多。

Spring对AOP的支持

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

  • 基于代理的经典SpringAOP   需要实现接口,手动创建代理
  • 纯POJO切面 使用XML配置,aop命名空间
  • @AspectJ注解驱动的切面 使用注解的方式,这是最简洁和最方便的!