Springboot中Aspect實現切面(以記錄日志為例)


前言
今天我們來說說spring中的切面Aspect,這是Spring的一大優勢。面向切面編程往往讓我們的開發更加低耦合,也大大減少了代碼量,同時呢讓我們更專注於業務模塊的開發,把那些與業務無關的東西提取出去,便於后期的維護和迭代。

好了,廢話少說!我們直接步入正題

以系統日志為例
首先,我們先做一些准備工作。

1、新建一個Springboot工程
2、添加必要的依賴
AOP 必須

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
gson主要是我用於數據的處理,不是必須的

<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.1</version>
</dependency>
個人喜好
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
3、日志實體類和service
package com.space.aspect.bo;

import lombok.Data;

/**
* 系統日志bo
* @author zhuzhe
* @date 2018/6/4 9:36
* @email 1529949535@qq.com
*/
@Data
public class SysLogBO {

private String className;

private String methodName;

private String params;

private Long exeuTime;

private String remark;

private String createDate;
}
package com.space.aspect.service;

import com.space.aspect.bo.SysLogBO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
* @author zhuzhe
* @date 2018/6/4 9:41
* @email 1529949535@qq.com
*/
@Slf4j
@Service
public class SysLogService {

public boolean save(SysLogBO sysLogBO){
// 這里就不做具體實現了
log.info(sysLogBO.getParams());
return true;
}
}
4、定義日志注解
這里呢,我們記錄日志使用注解的形式。所以,先定義一個注解

package com.space.aspect.anno;

import java.lang.annotation.*;

/**
* 定義系統日志注解
* @author zhuzhe
* @date 2018/6/4 9:24
* @email 1529949535@qq.com
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SysLog {
String value() default "";
}
5、聲明切面,完成日志記錄
以上4點我們的准備工作已經完成。接下來就是重點了

這里需要你對AOP有一定的了解。起碼知道切點表達式、環繞通知、前置通知、后置通知等。。。

package com.space.aspect.aspect;

import com.google.gson.Gson;
import com.space.aspect.anno.SysLog;
import com.space.aspect.bo.SysLogBO;
import com.space.aspect.service.SysLogService;
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.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
* 系統日志切面
* @author zhuzhe
* @date 2018/6/4 9:27
* @email 1529949535@qq.com
*/
@Aspect // 使用@Aspect注解聲明一個切面
@Component
public class SysLogAspect {

@Autowired
private SysLogService sysLogService;

/**
* 這里我們使用注解的形式
* 當然,我們也可以通過切點表達式直接指定需要攔截的package,需要攔截的class 以及 method
* 切點表達式: execution(...)
*/
@Pointcut("@annotation(com.space.aspect.anno.SysLog)")
public void logPointCut() {}

/**
* 環繞通知 @Around , 當然也可以使用 @Before (前置通知) @After (后置通知)
* @param point
* @return
* @throws Throwable
*/
@Around("logPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
long beginTime = System.currentTimeMillis();
Object result = point.proceed();
long time = System.currentTimeMillis() - beginTime;
try {
saveLog(point, time);
} catch (Exception e) {
}
return result;
}

/**
* 保存日志
* @param joinPoint
* @param time
*/
private void saveLog(ProceedingJoinPoint joinPoint, long time) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
SysLogBO sysLogBO = new SysLogBO();
sysLogBO.setExeuTime(time);
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
sysLogBO.setCreateDate(dateFormat.format(new Date()));
SysLog sysLog = method.getAnnotation(SysLog.class);
if(sysLog != null){
//注解上的描述
sysLogBO.setRemark(sysLog.value());
}
//請求的 類名、方法名
String className = joinPoint.getTarget().getClass().getName();
String methodName = signature.getName();
sysLogBO.setClassName(className);
sysLogBO.setMethodName(methodName);
//請求的參數
Object[] args = joinPoint.getArgs();
try{
List<String> list = new ArrayList<String>();
for (Object o : args) {
list.add(new Gson().toJson(o));
}
sysLogBO.setParams(list.toString());
}catch (Exception e){ }
sysLogService.save(sysLogBO);
}
}
6、測試
接下來,我們就來測試一下吧

package com.space.aspect.controller;

import com.space.aspect.anno.SysLog;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
* @author zhuzhe
* @date 2018/6/4 9:47
* @email 1529949535@qq.com
*/
@RestController
public class TestController {

@SysLog("測試")
@GetMapping("/test")
public String test(@RequestParam("name") String name){
return name;
}
}
啟動項目,訪問我們的test方法。

我們在service里打一個斷點

 

 

可以看到,我們所需要的值都成功拿到了。

這樣,我們就成功實現了使用Aspect實現切面記錄日志。
---------------------
作者:朱_哲
來源:CSDN
原文:https://blog.csdn.net/zhuzhezhuzhe1/article/details/80565067
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM