什么是AOP

AOP是面向切面编程。AOP是OOP的延续,而这里的切面则代表动态的将代码加入到指定的方法或位置上,一句话总结:在不改变原有代码的条件下,对该有功能进行扩展;

AOP的作用

可以将日志记录、性能统计、安全控制、事务处理、异常处理等代码从业务逻辑代码中分离出来,放到一个非业务逻辑的方法中,进而改变这些行为的同时不影响业务逻辑代码;实现了减少重复代码以及模块间低耦合的目的,以此来达到专心处理业务逻辑代码,不用管日志记录、事务控制及权限控制等。

什么是注解

从JDK5开始,Java增加对元数据的支持,也就是注解,注解与注释是有一定区别的,可以把注解理解为代码里的特殊标记,这些标记可以在编译,类加载,运行时被读取,并执行相应的处理。通过注解开发人员可以在不改变原有代码和逻辑的情况下在源代码中嵌入补充信息。

本文的目的

自定义注解OptLog,完成日志的记录
自定义注解AccessLimit,完成接口的限流操作
这里只演示日志操作,具体代码查看Gitee仓库

详细步骤

添加依赖

 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><!--浏览器解析工具--><dependency><groupId>eu.bitwalker</groupId><artifactId>UserAgentUtils</artifactId><version>1.20</version></dependency><!--fastJson--><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>2.0.7</version></dependency><!--Redis--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>

自定义注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface OptLog {/*** @return 操作类型*/String optType() default "";
}

定义切面

@Component
@Aspect
public class OptLogAspect {/*** 定义切点*/@Pointcut("@annotation(com.liu.springexam.annotation.OptLog)")public void optLogPointCut() {}/*** 切点后置通知* @param joinPoint 切点* @param result 返回结果*/@AfterReturning(value="optLogPointCut()",returning="result")public void saveOptLog(JoinPoint joinPoint,Object result) {// 获取RequestAttributesRequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();// 从获取RequestAttributes中获取HttpServletRequest的信息HttpServletRequest request = (HttpServletRequest) Objects.requireNonNull(requestAttributes).resolveReference(RequestAttributes.REFERENCE_REQUEST);MethodSignature signature = (MethodSignature) joinPoint.getSignature();Method method = signature.getMethod();//获取自定义注解OptLog optLog = method.getAnnotation(OptLog.class);//获取方法名String methodName = method.getName();// 请求IPString ipAddress = IpUtils.getIpAddress(request);UserAgent userAgent = IpUtils.getUserAgent(request);// 获取操作系统String os = userAgent.getOperatingSystem().getName();// 获取浏览器String browser = userAgent.getBrowser().getName();String ipSource = IpUtils.getIpSource(ipAddress);System.out.println("ipSource = " + ipSource);System.out.println("操作系统:"+os);System.out.println("浏览器:"+browser);System.out.println("请求IP:"+ipAddress);System.out.println("方法名:"+methodName);System.out.println("result = " + result);}
}

IpUtils


import com.alibaba.fastjson.JSON;
import eu.bitwalker.useragentutils.UserAgent;import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.List;
import java.util.Map;/*** ip工具类**/
@SuppressWarnings("all")
public class IpUtils {/*** 获取用户ip地址** @param request 请求* @return ip地址*/public static String getIpAddress(HttpServletRequest request) {String ipAddress = null;try {ipAddress = request.getHeader("x-forwarded-for");if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {ipAddress = request.getHeader("Proxy-Client-IP");}if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {ipAddress = request.getHeader("WL-Proxy-Client-IP");}if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {ipAddress = request.getRemoteAddr();if ("127.0.0.1".equals(ipAddress)) {// 根据网卡取本机配置的IPInetAddress inet = null;try {inet = InetAddress.getLocalHost();} catch (UnknownHostException e) {e.printStackTrace();}ipAddress = inet.getHostAddress();}}// 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割if (ipAddress != null && ipAddress.length() > 15) {// = 15if (ipAddress.indexOf(",") > 0) {ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));}}} catch (Exception e) {ipAddress = "";}return ipAddress;}/*** 解析ip地址** @param ipAddress ip地址* @return 解析后的ip地址*/public static String getIpSource(String ipAddress) {try {URL url = new URL("http://opendata.baidu.com/api.php?query=" + ipAddress + "&co=&resource_id=6006&oe=utf8");BufferedReader reader = new BufferedReader(new InputStreamReader(url.openConnection().getInputStream(), "utf-8"));String line = null;StringBuffer result = new StringBuffer();while ((line = reader.readLine()) != null) {result.append(line);}reader.close();Map map = JSON.parseObject(result.toString(), Map.class);List<Map<String, String>> data = (List) map.get("data");return data.get(0).get("location");} catch (Exception e) {return "";}}/*** 获取访问设备** @param request 请求* @return {@link UserAgent} 访问设备*/public static UserAgent getUserAgent(HttpServletRequest request){return UserAgent.parseUserAgentString(request.getHeader("User-Agent"));}}

在Controller层对应的方法上添加注解

@OptLog(optType = "查询专业")@GetMapping("/list")public RespInfo list() {List<Majors> majorsList = majorsService.findAll();RespInfo result = new RespInfo();result.setCode(200);result.setData(majorsList);result.setMsg("查询成功");return result;}

自定义注解实现AOP相关推荐

  1. 自定义注解加AOP怎么玩?

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 作者 | 乱敲代码 来源 | 公众号「乱敲代码」 前言 ...

  2. 通过自定义注解与aop统一存储操作记录

    模块开发完成后,接到通知需要添加操作记录功能,看着那一堆接口,如果一个方法一个方法的加,那真是太麻烦了.为了偷懒,就百度了一下,发现可以通过自定义注解和aop的形式来统一添加操作记录,只需要在每个方法 ...

  3. 一个简单的例子,学习自定义注解和AOP

    转载自   一个简单的例子,学习自定义注解和AOP 记得今年年初刚开始面试的时候,被问的最多的就是你知道Spring的两大核心嘛?那你说说什么是AOP,什么是IOC?我相信你可能也被问了很多次了. 1 ...

  4. java aop注解日志记录_springMVC自定义注解,用AOP来实现日志记录的方法

    需求背景 最近的一个项目,在项目基本完工的阶段,客户提出要将所有业务操作的日志记录到数据库中,并且要提取一些业务的关键信息(比如交易单号)体现在日志中. 为了保证工期,在查阅了资料以后,决定用AOP+ ...

  5. java方法设置切点_如何通过自定义注解实现AOP切点定义

    面向切面编程(Aspect Oriented Programming, AOP)是面向对象编程(Object Oriented Programming,OOP)的强大补充,通过横切面注入的方式引入其他 ...

  6. 通过自定义注解,AOP,反射,Group分组编写适用于各层级通用性手动调用validate方法

    通过自定义注解,AOP,反射,group分组编写适用于[*Controller,*RemoteImpl,*ServiceImpl]通用性手动调用validate方法 拓展方式:该通用方法可扩展性,通用 ...

  7. SpringBoot自定义注解和aop

    自定义注解类编写的一些规则: 1定义一个注解Annotation 定义为@interface,所有的Annotation会自动继承java.lang.Annotation这一接口,并且不能再去继承别的 ...

  8. 自定义注解和AOP的结合

    下面的代码我想实现的功能是凡是加了@CacheLock 的注解都要进行上锁 package run.halo.app.cache.lock;import org.springframework.cor ...

  9. ssm+redis 如何更简洁的利用自定义注解+AOP实现redis缓存

    基于 ssm + maven + redis 使用自定义注解 利用aop基于AspectJ方式 实现redis缓存 如何能更简洁的利用aop实现redis缓存,话不多说,上demo 需求: 数据查询时 ...

最新文章

  1. java httpclient 为邮箱添加来信转发规则
  2. php ajax实现查询功能,ajax实现分页查询功能
  3. OpenGL 学习笔记(3)绘制几何物体
  4. 每天一个Linux命令之date
  5. java uuid静态方法_Java UUID timestamp()方法与示例
  6. javascript用户登录_SAP HANA XS的JavaScript安全事项
  7. excel制作一个信息录入系统_制作Excel仓库入库单,一键完成数据录入、计算及保存操作...
  8. Qt 中获取三种坐标类型
  9. 配置vivado用vscode编辑文本
  10. firebug和firepath插件下载安装
  11. mysql 省份名排序,mysql省份表,含行政区划代码、省份名和省份全拼
  12. Raywenderlich: 用 VFX 制作蝴蝶飞起的效果
  13. Dell vostro 3667重装系统
  14. 文科生能学计算机专业难吗,文科生能读计算机科学专业吗?
  15. 阿里云天池大赛赛题解析——深度学习篇
  16. AT2401C功放PA完美替代RFX2401C
  17. 国债期货matlab,Matlab和国债期货的那些事儿~(四)——关键利率法在利率风险管理中的运用...
  18. 前端面试题整理—ES6篇
  19. 使用RMAN实现异机备份恢复(WIN平台)
  20. 河南单招计算机专业专科学校排名2015,河南省单招大专学校排名榜 哪个学校好...

热门文章

  1. 知乎热榜:如何渡过小白期,不再当菜鸟程序员?
  2. svn: E155004: Working copy 'E:\XX' locked 解决方法
  3. ObjectARX如何锁定一个图层
  4. 苹果手机sim卡无效怎么办_苹果手机扬声器没声音怎么办
  5. 微信小程序自定义组件——插槽
  6. java自动换行方法_自动换行的实现方法zz
  7. 股价SP预测——线性回归
  8. 微信王者服务器怎么删掉,《王者荣耀》如何删除微信列表里的人 2021删除游戏好友方法...
  9. 装饰器-带参数的装饰器动态传值
  10. EndNote X9 教程入门到进阶 win mac