Spring AOP简析

前言

通常我们在进行开发的时候,主要编写的都是业务代码,而一些与业务没有强相关的外围事务,如日志记录、事务处理等,会在代码中大量重复出现,造成代码冗余、霰弹式修改等问题,需要实现这些功能的热插拔、在使用的时候通过简便地方式引入处理。由此,引入了AOP实现业务代码与外围功能分离。

通过AOP,可以将业务外的周边共用逻辑,比如日志、事务、权限等封装起来,然后在业务需要使用时,将这些功能和业务功能“编织”在一起。

AOP描述

基础知识
AOP

Aspect Oriented Programming,即面向切面编程。AOP要实现的是在业务代码基础上,进行一定的包装,将切面的逻辑在方法返回前、方法返回后、方法抛异常等地方进行增强处理。在原来类的基础上,实现一个代理类,把切面的逻辑加在代理类中,实际上运行的是代理类的实例。

实现方式

AOP实现方式有两种,一种是静态编译,一种是动态代理;Java语言的实现方案有AspectJ或Spring AOP。

AspectJ

AspectJ是一种编译期的用注解形式实现的AOP,是一个代码生成工具。需要用AspectJ语法来定义代码生成规则、由AspectJ的编译工具编译生成class文件。

AspectJ能干很多Spring AOP不能干的事情,是AOP编程的完全解决方案。

因为AspectJ在代码加载运行前就完成了织入,因此它生成的类是没有额外运行时开销的。

Spring AOP

Spring AOP基于动态代理实现,在默认情况下,如果被代理类使用接口、则用JDK提供的动态代理实现,如果没有接口,使用Cglib实现。

Spring AOP依赖于IOC容器管理,只能作用于Spring容器中的bean对象,只能作用于bean对象的方法。

web开发时,有些时候需要的是一个Filter或者一个Intercepter,不一定是AOP

相关术语
Aspect

Aspect即切面,是实现功能增强的类,里面包含一些Pointcut和Advice。在AOP中,切面一般使用 @Aspect 注解来使用,在XML 中,可以使用 aop:aspect 来定义一个切面。 (注:在Spring中,仅使用@Aspect注解是无法将一个Java对象转换成bean的,还要使用类似@Component之类的注解标明)

Advice

Advice即增强,定义切面起作用的时机,比如是在方法执行前、执行后起作用。Spring AOP中有五种不同的增强方式:around(环绕通知),before(前置通知),after(后置通知), exception(异常通知),return(返回通知)

Advice对应的注解有:@Before、@After、@AfterReturn、@AfterThrow、@Around

JoinPoint

JoinPoint即连接点,表示切面执行的地点,比如一个对象的一个方法。

Pointcut

Pointcut即切入点,表示一组连接点,对应的注解为@Pointcut。这些连接点或是通过逻辑关系组合起来,或是通过通配、正则表达式等方式集中起来,它定义了相应的 Advice 将要发生的地方 。由切入点表达式匹配的连接点的概念是AOP的核心,Spring默认使用AspectJ切入点表达式语言。

Weaving

Weaving即织入,是指把增强应用到目标对象来创建新的代理对象的过程,它(例如 AspectJ 编译器)可以在编译时期,加载时期或者运行时期完成。

Target

Target即目标对象,是织入切面的对象(被代理的对象)

Aop proxy

Aop Proxy即AOP代理类,由AOP框架创建的对象,在Spring框架中,AOP代理对象有两种:JDK动态代理和CGLIB代理

织入的时期
  • 编译期: 切面在目标类编译时被织入,这种方式需要特殊的编译器。AspectJ 的织入编译器就是以这种方式织入切面的。
  • 类加载期: 切面在目标类加载到 JVM 时被织入,这种方式需要特殊的类加载器( ClassLoader ),它可以在目标类引入应用之前增强目标类的字节码。
  • 运行期: 切面在应用运行的某个时期被织入。一般情况下,在织入切面时,AOP容器会为目标对象动态创建一个代理对象,Spring AOP 采用的就是这种织入方式。
Spring AOP的使用

这里只讲Spring AOP是如何使用的,不涉及原理分析。

@AspectJ注解

Spring中使用@AspectJ风格的注解来定义AOP,主要用到这几个注解:@Aspect、@Pointcut和增强相关的几个注解。而@Pointcut和增强相关的注解,都使用切点表达式(切点标识符designator)定义切面使用的时机(何时何地)。AspectJ5 的切点表达式由标志符(designator)和操作参数组成. 如 "execution( greetTo(…))" 的切点表达式, execution 就是 标志符, 而圆括号里的 greetTo(…) 就是操作参数。标识符中,重要的有:execution、within、@annotation

execution 匹配方法执行的连接点(一般是限定到类的方法), 对于给定的作用域、返回值类型、完全限定类名以及参数匹配的方法将会应用切点函数指定的通知

//scope :方法作用域,如public,private,protect
//returnt-type:方法返回值类型
//fully-qualified-class-name:方法所在类的完全限定名称
//parameters 方法参数
execution(<scope> <return-type> <fully-qualified-class-name>.*(parameters))

within 匹配指定类型内的方法执行(一般是限定到类)

@annotation 根据所应用的注解进行方法过滤

常见的切点表达式:
  • 匹配方法签名

    // 匹配指定包中的所有的方法
    execution(* com.xys.service.*(…))

    // 匹配当前包中的指定类的所有方法
    execution(* UserService.*(…))

    // 匹配指定包中的所有 public 方法
    execution(public * com.xys.service.*(…))

    // 匹配指定包中的所有 public 方法, 并且返回值是 int 类型的方法
    execution(public int com.xys.service.*(…))

    // 匹配指定包中的所有 public 方法, 并且第一个参数是 String, 返回值是 int 类型的方法
    execution(public int com.xys.service.*(String name, …))

  • 匹配类型签名

    // 匹配指定包中的所有的方法, 但不包括子包
    within(com.xys.service.*)

    // 匹配指定包中的所有的方法, 包括子包
    within(com.xys.service…*)

    // 匹配当前包中的指定类中的方法
    within(UserService)

    // 匹配一个接口的所有实现类中的实现的方法
    within(UserDao+)

参考文章https://www.cnblogs.com/duanxz/p/5217689.html

使用方式

在Spring中,早期是用xml配置的方式来定义,后面可以通过xml配置+注解、或者完全通过注解的方式来使用。

纯xml配置方式

参考文章https://www.cnblogs.com/ysocean/p/7476379.html

xml配置+注解

在xml配置文件中添加如下语句,使能@AspectJ注解,再用注解定义切面。

<!-- 使能AOP注解 -->
<aop:aspectj-autoproxy/>

<!-- 让IOC容器能够扫描到bean对象 -->
<context:component-scan base-package="com.huang.aop.basic"/>
注解

在SpringBoot中,通过注解的方式定义一个配置类,从而使能@AspectJ注解

@Configuration
@EnableAspectJAutoProxy
public class AppConfig {
}
Spring AOP的原理

待补充

参考资料:

https://www.cnblogs.com/cxuanBlog/p/13060510.html 相对概述的一篇文章

https://segmentfault.com/a/1190000007469968 比较详细

https://javadoop.com/post/spring-aop-source 基于xml配置详细讲解源码

https://www.cnblogs.com/duanxz/p/5217689.html 详解标识符语法

https://mp.weixin.qq.com/s?__biz=MzI4Njg5MDA5NA==&mid=2247483954&idx=1&sn=b34e385ed716edf6f58998ec329f9867&chksm=ebd74333dca0ca257a77c02ab458300ef982adff3cf37eb6d8d2f985f11df5cc07ef17f659d4#rd 从java代理讲解AOP,实例比较好

https://blog.csdn.net/javazejian/article/details/56267036 详解AOP,论述清晰,有实例

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值