目录

Life in Flow

知不知,尚矣;不知知,病矣。
不知不知,殆矣。

X

AOP 打印数据访问层摘要

APO核心概念

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

作者:Soulboy