序言
最近在做一个spring boot的web应用,在解决日志处理的问题的时候需要用到AOP编程,作为spring入门选手的我来说还是第一次接触到这个概念。
概念
首先挂上概念,面向切面编程(AOP)是对面向对象编程(OOP)在另一程序结构上面的补充。 OOP 的核心单位是 class, 而AOP的核心单位则是 aspect(切面)。 切面使得对于像事务管理这种横切不同类型和对象的逻辑变得模块化。AOP主要的功能是:
- 日志记录
- 性能统计
- 安全控制
- 事务处理
- 异常处理等
主要的意图是:将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。
理解AOP,需要理解以下几种名词的概念:
- Aspect: 对系统中的横切关注点逻辑进行模块化封装的AOP概念实体
- jointPoint: 一个程序的执行点, 比如方法执行或者处理一个异常
- advice: aspect 中对切入点(join point)操作的封装, 相当于OOP中的method. 不同的advice类型包括 "around", "before" 和 "after" advice
- pointcut: 代表的是Jointpoint的表述方式, 将横切逻辑织入当前系统的过程中, 需要参照Pointcut规定的Joinpoint信息, 才可以知道应该往系统的哪些Joinpoint上织入横切逻辑.
- Target object: 被一个或多个aspect横切拦截操作的目标对象
实例
下面结合我项目中的实际问题来谈。
在web开发中,我想在日志中记录一些关键的信息,比如哪些url导致了异常,那些函数的调用导致了异常等等,这些信息对于程序的调试很关键。在我的这个项目中,我希望记录
- 请求的URL
- 访问者ip
- 调用方法classmethod
- 参数args
-
返回内容
为什么AOP适用?通俗点儿说,web控制器的请求是一个流状(flow)的过程,利用AOP,可以将这个flow上切一刀(定义一个切面),然后针对这个切面(aspect)的前和后来进行日志处理。接下来就是实际的操作:
首先我们需要新建一个aspect的package,来放置我们的切面,然后在这个package中定义一个LogAspect类,来进行日志处理。
接下来就要在LogAspect这个类中实现我的日志处理功能啦!
定义切面
@Pointcut("execution(* com.jasonliu.web.*.*(..))")
public void log() {}
这里的意思是,这个切面用来拦截jasonliu.web包下所有的web控制器的带有任意参数的所有方法。
切面前 before advise
@Before("log()")
public void doBefore(JoinPoint joinPoint) {
logger.info("--------dobefore--------");
}
切面后 after advice
@After("log()")
public void doAfter() {
logger.info("--------doAfter--------");
}
切面返回后 after returning advice
@AfterReturning(returning = "result",pointcut = "log()")
public void doAfterRuturn(Object result) {
logger.info("Result : {}", result);
}
我还需要记录方法返回的内容,这个就需要after returining来捕获。
方便大家理解程序执行的过程,我把切面的代码也贴出来
切面
public class IndexController {
@GetMapping("/")
public String index() {
System.out.println("----index-----");
return "index";
}
@GetMapping("/blog")
public String blog() {
return "blog";
}
}
运行后的日志结果
哈哈哈经过这些操作,我就能顺利记录我想要的日志内容啦!
小伙伴们,你学到了吗!rua!