前言
今天我们来说说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实现切面记录日志。

源码:https://github.com/zhuzhegithub/springboot-aop-aspect

转载请务必保留此出处(原作者):https://blog.csdn.net/zhuzhezhuzhe1

最新文章

  1. 关于Memcached一致性hash的探究
  2. 控件 UI: VisualState, VisualStateManager, 控件的默认 UI
  3. 【BZOJ-4173】数学 欧拉函数 + 关于余数的变换
  4. 定位frame 中的对象
  5. 测试方法---&quot;SFDIPOT&quot;
  6. hdoj 1257 最少拦截系统
  7. jQuery预加载插件
  8. oracle的基本信息查询
  9. JS的substr与substring的区别
  10. MinGW 运行C++程序的方法
  11. 团队作业9——展示博客(Bata版本)
  12. C# Dispose模式详细分析
  13. git在项目中的实际运用
  14. Android进阶推荐书籍
  15. Java学习笔记之——集合
  16. 一次Windows 安装问题
  17. java8 集合对象间的处理
  18. 计算机从加电到系统(Linux)启动完成
  19. windows下建立netcore控制台程序,然后传送到centos7下的docker容器里运行
  20. opengl wglsharelists

热门文章

  1. Application Initialization UI for IIS 7.5
  2. ubuntu系统安装mysql登陆提示 解决Mysql ERROR 1045 (28000): Access denied for user &#39;root&#39;@&#39;localhost&#39;问题
  3. net core体系-API-1Ocelot-(1)概要
  4. redis 配置文件配置
  5. Codeforces 1092E Minimal Diameter Forest
  6. 修改注册表.exe的文件目录
  7. 存储过程导入excel
  8. Python交互图表可视化Bokeh:5 柱状图| 堆叠图| 直方图
  9. 查找常用字符(给定仅有小写字母组成的字符串数组 A,返回列表中的每个字符串中都显示的全部字符(包括重复字符)组成的列表。例如,如果一个字符在每个字符串中出现 3 次,但不是 4 次,则需要在最终答案中包含该字符 3 次。)
  10. Addition Chains POJ - 2248 (bfs / dfs / 迭代加深)