绑定完请刷新页面
取消
刷新

分享好友

×
取消 复制
你不知道的骚操作,Springboot AOP的使用详解
2019-10-24 11:07:38

文章来源:掘金

AOP是什么

要了解**AOP(Aspect Oriented Programming)面向方面编程,我们往往将其和另一个名词即OOP(Object Oriented Programming)面向对象编程**放一起来比较和理解。

在OOP的模式下,当多个不具有继承关系的对象需引用同一个公共行为时,就会产生大量重复冗余代码。好理解就是我们的日志模块或者安全监测等。要在函数的调用处打出日志,我们则需要引入日志对象来调用,然而这个日志对象并非业务类所需要的。

AOP所关注的方向是横向的,是OOP的有益补充。为了能让业务类更专注于具体的物业开发,而其他模块功能的增加不修改到目标函数,可通过配置切面来实现达到功能解耦。

AOP术语

连接点(join point):对应的是具体被拦截的对象,因为Spring只支持方法,所以被拦截的对象往往就是指特定的方法。

切点(point cut):有时候,我们的切面不单单应用于单个方法,也可以是多个类的不同方法,这时,可以通过正则表达式和指示器的规则去定义。

通知(advice):

前置通知(before advice)

后置通知(after advice)

环绕通知(around advice)

事后返回通知(afterReturning advice)

异常通知(afterThrowingadvice)

目标对象(target):即被代理对象。

引入(introduction):是指引入新的类和方法,增强现有Bean的功能。

织入(weaving):它是一个通过动态代理技术,为原有服务对象生成动态对象,然后将与切点定义匹配的连接点拦截,并按约定将各类通知织入约定流程的过程。

切面(aspect):是一个可以定义切点、各类通知和引入的内容。

了解了大致概念之后,我们直接动手看究竟怎么来执行一个切面。

AOP使用

业务类代码TestController。

定义简单切面

上面的例子就是对业务方法testFunc进行一个简单的切面定义实现。到这里,一个基本的切面类已经实现了。下面我们继续了解AOP的更多内容。

切面注解要点说明

使用@Aspect注解将一个java类定义为切面类,如例子中的MyAspect。

使用@Pointcut定义一个切入点,可以是一个规则表达式,也可以是一个注解等。

根据需要在切入点不同位置的切入内容

使用@Before在切入点开始处切入内容

使用@After在切入点结尾处切入内容

使用@AfterReturning在切入点return内容之后切入内容(可以用来对处理返回值做一些加工处理)

使用@Around在切入点前后切入内容,并自己控制何时执行切入点自身的内容

使用@AfterThrowing用来处理当切入内容部分抛出异常之后的处理逻辑

定义处理参数的切面

Spring AOP提供使用org.aspectj.lang.JoinPoint类型获取连接点数据,任何通知方法的个参数都可以是JoinPoint(环绕通知是ProceedingJoinPoint,JoinPoint子类)。

JoinPoint:提供访问当前被通知方法的目标对象、代理对象、方法参数等数据

ProceedingJoinPoint:只用于环绕通知,使用proceed()方法来执行目标方法

如参数类型是JoinPoint、ProceedingJoinPoint类型,可以从“argNames”属性省略掉该参数名(可选,写上也对),这些类型对象会自动传入的,但必须作为个参数。

@Aspect

@Component

public class MyAspect {

@Pointcut("execution(public * com.test.TestController.testFunc(..))")

public void pointCut() {}

@Before("pointCut()")

public void before(JoinPoint joinPoint) {

String method = joinPoint.getSignature().getName();

log.info("MyAspect before Method:{}::{}", joinPoint.getSignature().getDeclaringTypeName(), method);

ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

HttpServletRequest request = attributes.getRequest();

log.info("ClientIP:{}", request.getRemoteAddr());

}

@After("pointCut()")

public void after(JoinPoint joinPoint) {

String method = joinPoint.getSignature().getName();

log.info("MyAspect after Method:{}::{}", joinPoint.getSignature().getDeclaringTypeName(), method);

}

@AfterReturning("pointCut()")

public void afterReturning(JoinPoint joinPoint) {

String method = joinPoint.getSignature().getName();

log.info("MyAspect after returning Method:{}::{}", joinPoint.getSignature().getDeclaringTypeName(), method);

}

@AfterThrowing("pointCut()")

public void afterThrowing(JoinPoint joinPoint) {

log.info("MyAspect after throwing ...");

}

@Around("pointCut()")

public void around(ProceedingJoinPoint joinPoint) throws Throwable {

log.info("MyAspect around before ...");

joinPoint.proceed();

log.info("MyAspect around after ...");

}

}

定义具有执行优先级切面

通过注解@Order来配置执行优先级,order数字越小越优先执行。

@Aspect

@Component

@Order(-1)

public class MyAspect2 {

//和上面例子一样,省略

}

通过实现org.springframework.core.Ordered接口

@Component

@Aspect

public class MyAspect2 implements Ordered {

@Override

public int getOrder() {

//do something to gen order.

return 2;

}

}

AOP切点详解

PointCut的定义包括两个部分:Pointcut表示式(expression)和Pointcut签名(signature)。

//Pointcut表示式

@Pointcut("execution(public * com.test.TestController.testFunc(..))")

//Pointcut签名

public void pointCut() {}

execution表示式的格式:

execution(

modifier-pattern?

ret-type-pattern

declaring-type-pattern?

name-pattern(param-pattern)

throws-pattern?)

括号中各个pattern分别表示

修饰符匹配(modifier-pattern?)

返回值匹配(ret-type-pattern)

类路径匹配(declaring-type-pattern?)

方法名匹配(name-pattern)

参数匹配((param-pattern))

异常类型匹配(throws-pattern?),其中后面跟着“?”的是可选项。

现在来看看几个例子。

execution(* *(..)):表示匹配所有方法

execution(public * com.test.TestController.*(..)):表示匹配com.test.TestController类中所有的公有方法

execution(* com.test..*.*(..)):表示匹配com.test包中所有的方法

分享好友

分享这个小栈给你的朋友们,一起进步吧。

应用开发
创建时间:2020-06-17 15:31:04
应用软件开发是指使用程序语言C#、java、 c++、vb等语言编写,主要是用于商业、生活应用的软件的开发。
展开
订阅须知

• 所有用户可根据关注领域订阅专区或所有专区

• 付费订阅:虚拟交易,一经交易不退款;若特殊情况,可3日内客服咨询

• 专区发布评论属默认订阅所评论专区(除付费小栈外)

技术专家

查看更多
  • 栈栈
    专家
戳我,来吐槽~