技术栈

四、Spring AOP

2019-07-03  本文已影响0人  烟雨乱平生

AOP的常用术语:

AOP框架

并不是所有的AOP框架都是一样的,它们在连接点模型上可能有强弱之分。有些允许对字段修饰符级别应用通知,而另一些只支持与方法调用相关的连接点。它们织入切面的方式和时机也有所不同。但是无论如何,创建切点来定义切面织入的连接点是AOP框架的基本功能。

三足鼎立的AOP框架:

Spring AOP

Spring提供了4种各具特色的AOP支持:

前三种都是Spring基于代理AOP的变体,因此,Spring对AOP的支持局限于方法拦截。如果AOP需求超过了简单方法拦截的范畴,那么应该考虑在AspectJ里面实现,利用Spring的DI把Spring Bean注入到AspectJ切面中。

使用切点选择连接点

切点是用于准确定位应该在什么地方应用切面的通知。切点个通知是切面的最基本元素。

在Spring AOP中,需要使用AspectJ的切点表达式语言来定义切点。关于Spring AOP的AspectJ切点,最重要的一点是Spring仅支持AspectJ切点指示器的一个子集。

AspectJ指示器 描述
arg() 限制连接点匹配参数为指定类型的执行方法
@args() 限制连接匹配参数由指定注解标注的执行方法
execution() 用于匹配是连接点的执行方法
this() 限制连接点匹配AOP代理的Bean应用类型为指定类型的类
target() 限制连接点匹配目标对象为指定类型的类
@target() 限制连接点匹配特定的执行对象,这些对象对应的类要具备指定类型的注解
within() 限制连接点匹配指定的类型
@within() 限制连接点匹配指定注解所标注的类型
@annotation 限制匹配带有指定注解连接点

注意只有execution指示器是唯一的执行匹配,而其他的指示器都是用于限制匹配的。这说明execution指示器是我们在编写切点定义时最主要使用的指示器。在此基础上,我们使用其他指示器来限制所匹配的切点。

编写切点
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?)

这里问号表示当前项可以有也可以没有,其中各项的语义如下:

  • modifiers-pattern:方法的可见性,如public,protected;

  • ret-type-pattern:方法的返回值类型,如int,void等;

  • declaring-type-pattern:方法所在类的全路径名,如com.spring.Aspect;

  • name-pattern:方法名类型,如buisinessService();

  • param-pattern:方法的参数类型,如java.lang.String;

  • throws-pattern:方法抛出的异常类型,如java.lang.Exception;

由于Spring切面粒度最小是达到方法级别,而execution表达式可以用于明确指定方法返回类型,类名,方法名和参数名等与方法相关的部件,并且在Spring中,大部分需要使用AOP的业务场景也只需要达到方法级别即可,因而execution表达式的使用是最为广泛的。

/*匹配使用public修饰,返回值为任意类型,并且是*com.spring.BusinessObject类中名称为businessService的方法,方法可以有多个参数,但是第一个参数必须是java.lang.String类型的方法*/
execution(public * com.spring.service.BusinessObject.businessService(java.lang.String,..))

/*返回值为任意类型,在com.spring.service.BusinessObject类中,并且参数个数为零的方法*/
execution(* com.spring.service.BusinessObject.*())

/*返回值为任意类型,在com.spring.service包中,以Business为前缀的类,并且是类中参数个数为零方法:*/
execution(* com.spring.service.Business*.*())

/*匹配返回值为任意类型,并且是com.spring.service包及其子包下的任意类的名称为businessService的方法,而且该方法不能有任何参数*/
execution(* com.spring.service..*.businessService())

通配符

  • *通配符:该通配符主要用于匹配单个单词,或者是以某个词为前缀或后缀的单词。

  • ..通配符:该通配符表示0个或多个项,主要用于declaring-type-pattern和param-pattern中,如果用于declaring-type-pattern中,则表示匹配当前包及其子包,如果用于param-pattern中,则表示匹配0个或多个参数。

within(declaring-type-pattern)

within表达式的粒度为类,其参数为全路径的类名(可使用通配符),表示匹配当前表达式的所有类都将被当前方法环绕。

/*匹配com.spring.service.BusinessObject中的所有方法*/
within(com.spring.service.BusinessObject)

/*匹配com.spring.service包下的所有类,不包括子包中的类*/
within(com.spring.service.*)

/*匹配com.spring.service包及子包下的所有类*/
within(com.spring.service..*)
args(param-pattern)

args表达式的作用是匹配指定参数类型和指定参数数量的方法,无论其类路径或者是方法名是什么。这里需要注意的是,args指定的参数必须是全路径的。

/*匹配所有只有一个参数,并且参数类型是java.lang.String类型的方法*/
args(java.lang.String)

/*匹配第一个参数为java.lang.String,最后一个参数为java.lang.Integer,并且中间可以有任意个数和类型参数的方法*/
args(java.lang.String,..,java.lang.Integer)
@within(annotation-type)

前面我们讲解了within的语义表示匹配指定类型的类实例,这里的@within表示匹配带有指定注解的类

/*匹配使用com.spring.annotation.BusinessAspect注解标注的类*/
@within(com.spring.annotation.BusinessAspect)
@annotation(annotation-type)

表示匹配使用@annotation指定注解标注的方法将会被环绕

/*匹配使用com.spring.annotation.BusinessAspect注解标注的方法*/
@annotation(com.spring.annotation.BusinessAspect)
@args(annotation-type)

@within和@annotation分别表示匹配使用指定注解标注的类和标注的方法将会被匹配,@args则表示使用指定注解标注的类作为某个方法的参数时该方法将会被匹配。

/*匹配使用了com.spring.annotation.FruitAspect注解标注的类作为参数的方法*/
@args(com.spring.annotation.FruitAspect)

上一篇 下一篇

猜你喜欢

热点阅读