AOP 打印数据访问层摘要
APO核心概念
Spring AOP 常用注解
- @EnableAspectJAutoProxy:开启AspectJ的支持。
- @Aspect:当前类是一个切面。(需要配合@Component)
- @Pointcut:
- @Before:Advice在Join Point之前执行。
- @After :不管成功或失败,只要结束就会执行。
- @AfterReturning :在成功return之后执行。
- @AfterThrowing :在失败return之后执行。
- @Around:环绕通知。前+后
- @Order:用于指定切面的执行顺序。数值越小,优先级越高。
如何打印SQL
HikariCP
自身没有输出SQL的能力,需要借助P6Spy。
<dependency>
<groupId>p6spy</groupId>
<artifactId>p6spy</artifactId>
<version>3.8.1</version>
</dependency>
Alibaba Druid
内置 SQL 输出
Druid中使用log4j2进行日志输出
示例
引入依赖
<?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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>geektime.spring</groupId>
<artifactId>springbucks</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springbucks</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.joda</groupId>
<artifactId>joda-money</artifactId>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>org.jadira.usertype</groupId>
<artifactId>usertype.core</artifactId>
<version>6.0.1.GA</version>
</dependency>
<dependency>
<groupId>p6spy</groupId>
<artifactId>p6spy</artifactId>
<version>3.8.1</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</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>
application.properties
spring.datasource.driver-class-name=com.p6spy.engine.spy.P6SpyDriver
spring.datasource.url=jdbc:p6spy:h2:mem:testdb
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.hibernate.ddl-auto=none
#spring.jpa.properties.hibernate.show_sql=true
#spring.jpa.properties.hibernate.format_sql=true
spy.properties
Reference
# 单行日志
logMessageFormat=com.p6spy.engine.spy.appender.SingleLineFormat
# 使用Slf4J记录sql
appender=com.p6spy.engine.spy.appender.Slf4JLogger
# 是否开启慢SQL记录
outagedetection=true
# 慢SQL记录标准,单位秒
outagedetectioninterval=2
PerformanceAspect
package geektime.spring.springbucks.aspect;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Aspect
@Component
@Slf4j
public class PerformanceAspect {
/**
* 定义通知
* @param pjp
* @return
* @throws Throwable
*/
// @Around("execution(* geektime.spring.springbucks.repository..*(..))")
@Around("repositoryOps()")
public Object logPerformance(ProceedingJoinPoint pjp) throws Throwable {
//执行方法前记录当前时间
long startTime = System.currentTimeMillis();
//打印目标方法的名字
String name = "-";
//执行失败就会变成 "N" ,默认是成功 "Y"
String result = "Y";
try {
//获取目标方法的名字
name = pjp.getSignature().toShortString();
//执行目标方法
return pjp.proceed();
} catch (Throwable t) {
result = "N";
throw t;
} finally {
//在方法执行之后 记录当前时间
long endTime = System.currentTimeMillis();
//记录方法的耗时
log.info("{};{};{}ms", name, result, endTime - startTime);
}
}
/**
* 定义 切入点
* 拦截 geektime.spring.springbucks.repository 包下面所有类的所有方法
* 这里是拦截 repository 层
* 如果想要拦截 service 层 可以如法炮制。
*/
@Pointcut("execution(* geektime.spring.springbucks.repository..*(..))")
private void repositoryOps() {
}
}
控制台输出
2020-01-15 18:27:01.555 INFO 6504 --- [ main] g.s.s.aspect.PerformanceAspect : CrudRepository.save(..);Y;11ms