AOP 打印数据访问层摘要
APO 核心概念
Spring AOP 常用注解
- @EnableAspectJAutoProxy:开启 AspectJ 的支持。
- @Aspect:当前类是一个切面。(需要配合 @Component)
- @Pointcut:
- @Before:Advice 在 Join Point 之前执行。
- @After :不管成功或失败,只要结束就会执行。
- @AfterReturning :在成功 return 之后执行。
- @AfterThrowing :在失败 return 之后执行。
- @Around:环绕通知。前 + 后
- @Order:用于指定切面的执行顺序。数值越小,优先级越高。
如何打印 SQL
HikariCP
自身没有输出 SQL 的能力,需要借助 P6Spy。
1 <dependency>
2 <groupId>p6spy</groupId>
3 <artifactId>p6spy</artifactId>
4 <version>3.8.1</version>
5 </dependency>
Alibaba Druid
内置 SQL 输出
Druid 中使用 log4j2 进行日志输出
示例
引入依赖
1<?xml version="1.0" encoding="UTF-8"?>
2<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4 <modelVersion>4.0.0</modelVersion>
5 <parent>
6 <groupId>org.springframework.boot</groupId>
7 <artifactId>spring-boot-starter-parent</artifactId>
8 <version>2.1.2.RELEASE</version>
9 <relativePath/> <!-- lookup parent from repository -->
10 </parent>
11 <groupId>geektime.spring</groupId>
12 <artifactId>springbucks</artifactId>
13 <version>0.0.1-SNAPSHOT</version>
14 <name>springbucks</name>
15 <description>Demo project for Spring Boot</description>
16
17 <properties>
18 <java.version>1.8</java.version>
19 </properties>
20
21 <dependencies>
22 <dependency>
23 <groupId>org.springframework.boot</groupId>
24 <artifactId>spring-boot-starter-data-jpa</artifactId>
25 </dependency>
26
27 <dependency>
28 <groupId>org.joda</groupId>
29 <artifactId>joda-money</artifactId>
30 <version>1.0.1</version>
31 </dependency>
32 <dependency>
33 <groupId>org.jadira.usertype</groupId>
34 <artifactId>usertype.core</artifactId>
35 <version>6.0.1.GA</version>
36 </dependency>
37
38 <dependency>
39 <groupId>p6spy</groupId>
40 <artifactId>p6spy</artifactId>
41 <version>3.8.1</version>
42 </dependency>
43
44 <dependency>
45 <groupId>com.h2database</groupId>
46 <artifactId>h2</artifactId>
47 <scope>runtime</scope>
48 </dependency>
49 <dependency>
50 <groupId>org.projectlombok</groupId>
51 <artifactId>lombok</artifactId>
52 <optional>true</optional>
53 </dependency>
54 <dependency>
55 <groupId>org.springframework.boot</groupId>
56 <artifactId>spring-boot-starter-test</artifactId>
57 <scope>test</scope>
58 </dependency>
59 </dependencies>
60
61 <build>
62 <plugins>
63 <plugin>
64 <groupId>org.springframework.boot</groupId>
65 <artifactId>spring-boot-maven-plugin</artifactId>
66 </plugin>
67 </plugins>
68 </build>
69</project>
application.properties
1spring.datasource.driver-class-name=com.p6spy.engine.spy.P6SpyDriver
2spring.datasource.url=jdbc:p6spy:h2:mem:testdb
3spring.datasource.username=sa
4spring.datasource.password=
5
6spring.jpa.hibernate.ddl-auto=none
7#spring.jpa.properties.hibernate.show_sql=true
8#spring.jpa.properties.hibernate.format_sql=true
spy.properties
Reference
1# 单行日志
2logMessageFormat=com.p6spy.engine.spy.appender.SingleLineFormat
3# 使用Slf4J记录sql
4appender=com.p6spy.engine.spy.appender.Slf4JLogger
5# 是否开启慢SQL记录
6outagedetection=true
7# 慢SQL记录标准,单位秒
8outagedetectioninterval=2
PerformanceAspect
1package geektime.spring.springbucks.aspect;
2
3import lombok.extern.slf4j.Slf4j;
4import org.aspectj.lang.ProceedingJoinPoint;
5import org.aspectj.lang.annotation.Around;
6import org.aspectj.lang.annotation.Aspect;
7import org.aspectj.lang.annotation.Pointcut;
8import org.springframework.stereotype.Component;
9
10@Aspect
11@Component
12@Slf4j
13public class PerformanceAspect {
14 /**
15 * 定义通知
16 * @param pjp
17 * @return
18 * @throws Throwable
19 */
20// @Around("execution(* geektime.spring.springbucks.repository..*(..))")
21 @Around("repositoryOps()")
22 public Object logPerformance(ProceedingJoinPoint pjp) throws Throwable {
23 //执行方法前记录当前时间
24 long startTime = System.currentTimeMillis();
25 //打印目标方法的名字
26 String name = "-";
27 //执行失败就会变成 "N" ,默认是成功 "Y"
28 String result = "Y";
29 try {
30 //获取目标方法的名字
31 name = pjp.getSignature().toShortString();
32 //执行目标方法
33 return pjp.proceed();
34 } catch (Throwable t) {
35 result = "N";
36 throw t;
37 } finally {
38 //在方法执行之后 记录当前时间
39 long endTime = System.currentTimeMillis();
40 //记录方法的耗时
41 log.info("{};{};{}ms", name, result, endTime - startTime);
42 }
43 }
44
45 /**
46 * 定义 切入点
47 * 拦截 geektime.spring.springbucks.repository 包下面所有类的所有方法
48 * 这里是拦截 repository 层
49 * 如果想要拦截 service 层 可以如法炮制。
50 */
51 @Pointcut("execution(* geektime.spring.springbucks.repository..*(..))")
52 private void repositoryOps() {
53 }
54}
控制台输出
12020-01-15 18:27:01.555 INFO 6504 --- [ main] g.s.s.aspect.PerformanceAspect : CrudRepository.save(..);Y;11ms