在项目编写过程中,需要在必要的时候打印日志,而每个开发人员对日志打印的格式又有所不一样,这就导致项目中存在各种各样的日志格式。对于日志的提取会存在困难,那么统一日志打印格式就显得尤为必要。
什么是AOP?
AOP(Aspect Oriented Programming) 即面向切面编程,是OOP(Object Oriented Programming、面向对象编程)的一个延续,是OOP的一个进阶。在Java的Spring中,Aop显得格为重要。
AOP能干什么?
AOP能给我们带来很大的便利,利用AOP可以将业务进行隔离(比如说:对登录的统一校验),降低业务之间的耦合程度,也可以减少项目中的重复代码,大大的提高了项目的重用性和开发效率。其主要使用在日志统一管理、安全验证、各种接口请求统计、对异常的处理。
AOP的常用注解
@Aspect:声明该类为一个注解类;
@Pointcut:定义一个切点,后面跟随一个表达式,表达式可以定义为切某个注解,也可以切某个 package 下的方法;
@Before: 在切点之前,执行相关代码;
@After: 在切点之后,执行相关代码;
@AfterReturning: 在切点返回内容后,执行相关代码,一般用于对返回值做些加工处理的场景;
@AfterThrowing: 用来处理当执行的代码抛出异常后的逻辑处理;
@Around: 环绕,可以在切入点前后执行代码,并且可以自由的控制何时执行切点;
如何实现AOP?
下面就以实现日志打印为例来使用:
注意:需要使用 Lombok功能,建议先安装Lombok插件
package com.example.demo.aspect;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
@Aspect
@Component
@Slf4j
public class RequestAspect {
@Pointcut("execution(public * com.example.demo.controller.*.*(..))")
public void log(){
}
@Before("log()")
public void doBefore(JoinPoint joinPoint){
ServletRequestAttributes sra=(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request=sra.getRequest();
//操作如下
log.info ("controller {}.{} 方法开始执行... \n 参数信息如下 : {}", joinPoint.getSignature().getDeclaringTypeName(),
joinPoint.getSignature().getName(), Arrays.toString(joinPoint.getArgs()));
}
}
完整的pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
总结
通过以上简单的实践便可以实现使用AOP功能完成日志的统一打印,可以避免由于日志打印混乱而导致进行日志分析的时候不能更快的找到问题。