Spring AOP 学习简记

最近在学习Spring上的AOP,通过官方文档和慕课网上的一个课程,对AOP有了一些了解。在这里做下记录。

什么是AOP

相信大家对于AOP这个词都不陌生:面向切面编程。在解释这个概念的时候就不得不说一下他的适用情况了。在实际项目中,有一部分是主要的业务逻辑,而还有一部分很重要的就是非功能性需求,比如权限判断,事务控制,异常处理等等。这些功能有个共同的特点就是他们会贯穿项目,我们可能在很多的地方都需要做一些为了系统安全的操作,而这些操作又不能将他们放到业务逻辑中去,那样就会使我们的业务逻辑实现变得复杂。这时候就需要AOP这一利器。它会在某一个层面上统一执行一些操作,而这些操作我们在实现业务逻辑的时候就完全不用去考虑了。

简言之,AOP就是从复杂的业务逻辑中将非功能性需求抽离出来的办法。

Spring是如何实现AOP的

Spring在为我们实现AOP的时候提供了很好的支持。https://docs.spring.io/spring/docs/4.3.18.BUILD-SNAPSHOT/spring-framework-reference/htmlsingle/#aop

Aspect类

首先我们需要建立一个Aspect类,用来定义切面和执行切面的操作。在这个切面类中,首选需要定义一个切点:@Pointcut,它会告诉我们在哪里执行的操作。然后就是定义advice函数,这些函数主要是告诉我们在的时候执行什么操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
@Aspect // 声明这个是一个切面
@Component // 声明这个是一个组件。由于切面中,并没有包含Component,所以如果想让spring扫描到,必须那入@Component注解
public class InstrumentOwnerCheckAspect {
...
@Pointcut("@annotation(com.mengyunzhi.measurement.annotation.InstrumentOwnerCheckAnnotation) && args(id,..)")
public void doAccessCheck(Long id) {}
@Before("doAccessCheck(id)")
public void before(Long id) throws ObjectNotFoundException, AccessDeniedException {
...
}
}

值得注意的是,在定义Aspect这个类的时候,我们需要使用@Component这个注解,以使它在项目启动的时候能够被Spring扫描到。

匹配注解

这个概念是对如何实现切的操作而说的。

这是说通过某一个注解就可以实现切的操作。

在这几个中,比较常用的是@annotation:在方法上使用注解。参数是告诉我们使用哪个注解,比如上面使用的就是AdminOnly注解。

有一个比较特殊的,是匹配方法:execution,它只能在某个方法的地方切。

1
2
// 在所有的public方法上切
@Pointcut("execution(public * *(..))")

他的用法在https://docs.spring.io/spring/docs/4.3.14.RELEASE/spring-framework-reference/html/aop.html#aop-pointcuts-examples上还要很多,这里就不一一介绍了。

匹配参数

匹配参数是同样也是在告诉我们在什么地方执行的操作,不同的是,它只能告诉我们切点的参数是什么样子。所以匹配参数都是在切方法的时候用的。

参数匹配主要有两种executionargs

这里推荐使用args

五大Advice

advice是告诉我们在执行切的时候应该做什么的,而五大advice是根据在切点不同位置执行操作而区分的。

示例代码解读

1
2
3
4
5
6
7
8
9
...
@Pointcut("@annotation(com.mengyunzhi.measurement.annotation.InstrumentOwnerCheckAnnotation) && args(id,..)")
public void doAccessCheck(Long id) {}
@Before("doAccessCheck(id)")
public void before(Long id) throws ObjectNotFoundException, AccessDeniedException {
...
}
...

切点:InstrumentOwnerCheckAnnotation注解。参数:第一个参数是id的方法。

@Before在切之前执行操作。

所以上面的意思就是,在所有使用@InstrumentOwnerCheckAnnotation注解,并且第一个参数是id的方法处切,然后在切之前执行before方法。

总结

Spring的AOP帮助我们能够更加专注于实现某一部分的业务逻辑,而忽视夹杂其间的非功能性需求,在最大的可能上降低了我们的项目的整体耦合性,从而更好的实现面向对象的思想。


友情链接:

https://docs.spring.io/spring/docs/4.3.14.RELEASE/spring-framework-reference/html/aop.html

https://www.imooc.com/learn/869

坚持原创技术分享,您的支持将鼓励我继续创作!