技术标签: spring spring boot aop java 自定义注解
注解的使用真的很神奇,加一个注解就能实现想要的功能,很好奇,也想自己根据需要写一些自己实现的自定义注解。问题来了,自定义注解到底是什么?其实注解一点也不神奇,注解是一种能被添加到java源代码中的元数据,单独使用注解,就相当于在类、方法、参数和包上加上一个装饰,什么功能也没有,仅仅是一个标志,然后这个标志可以加上一些自己定义的参数。就像下面这样,创建一个@interface的注解,然后就可以使用这个注解了,加在我们需要装饰的方法上,但是什么功能也没有。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface ValidateToken {
String value() default"";
}
我们上面的创建的注解ValidateToken 上面还有几个注解(@Target、@Retention、@Inherited、@Documented),这四个注解就是元注解,元注解的作用就是负责注解其他注解。Java5.0定义了4个标准的元注解类型,它们被用来提供对其它 注解类型作标志操作(可以理解为最小的注解,基础注解)
Target类型 | 描述 |
---|---|
ElementType.TYPE | 应用于类、接口(包括注解类型)、枚举 |
ElementType.FIELD | 应用于属性(包括枚举中的常量) |
ElementType.METHOD | 应用于方法 |
ElementType.PARAMETER | 应用于方法的形参 |
ElementType.CONSTRUCTOR | 应用于构造函数 |
ElementType.LOCAL_VARIABLE | 应用于局部变量 |
ElementType.ANNOTATION_TYPE | 应用于注解类型 |
ElementType.PACKAGE | 应用于包 |
备注:例如@Target(ElementType.METHOD),标志的注解使用在方法上,但是我们在这个注解标志在类上,就会报错
生命周期类型 | 描述 |
---|---|
RetentionPolicy.SOURCE | 编译时被丢弃,不包含在类文件中 |
RetentionPolicy.CLASS | JVM加载时被丢弃,包含在类文件中,默认值 |
RetentionPolicy.RUNTIME | 由JVM 加载,包含在类文件中,在运行时可以被获取到 |
@Inherited阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。
AOP (Aspect Orient Programming),直译过来就是 面向切面编程。AOP 是一种编程思想,是面向对象编程(OOP)的一种补充。面向对象编程将程序抽象成各个层次的对象,而面向切面编程是将程序抽象成各个切面,是Spring的核心思想之一。
AOP 要达到的效果是,保证开发者不修改源代码的前提下,去为系统中的业务组件添加某种通用功能。AOP 的本质是由 AOP 框架修改业务组件的多个方法的源代码,按照 AOP 框架修改源代码的时机,可以将其分为两类:
我们知道,spring中的aop是通过动态代理实现的,那么他具体是如何实现的呢?spring通过一个切面类,在他的类上加入@Aspect注解,定义一个Pointcut方法,最后定义一系列的增强方法。这样就完成一个对象的切面操作。
那么思考一下,按照上述的基础,要实现我们的aop,大致有以下思路:
1.找到所有的切面类
2.解析出所有的advice并保存
3.创建一个动态代理类
4.调用被代理类的方法时,找到他的所有增强器,并增强当前的方法
bean表达式一般应用于类级别,实现粗粒度的切入点定义,案例分析:
within表达式应用于类级别,实现粗粒度的切入点表达式定义,案例分析:
execution表达式应用于方法级别,实现细粒度的切入点表达式定义,案例分析:
语法:execution(返回值类型 包名.类名.方法名(参数列表))。
@annotaion表达式应用于方法级别,实现细粒度的切入点表达式定义,案例分析
自定义注解使用范围:
上面总结的注解的定义,但是创建这样一个注解,仅仅是一个标志,装饰类、方法、属性的,并没有功能,要想实现功能,需要我们通过拦截器、AOP切面这些地方获取注解标志,然后实现我们的功能。一般我们可以通过注解来实现一些重复的逻辑,就像封装了的一个方法,可以用在一些权限校验、字段校验、字段属性注入、保存日志、缓存。
/**
* @Pointcut 注解通过切入点表达式定义切入点,例如
* bean表达式:bean(bean的名称)
*/
//@Pointcut("bean(sysUserServiceImpl)")
@Pointcut("@annotation(com.cy.pj.common.annotation.RequiredLog)")
public void doLogPointCut() {
//方法体不需要写任何内容
}
@Around("doLogPointCut()")
public Object around(ProceedingJoinPoint jp)throws Throwable{
long t1=System.currentTimeMillis();
log.info("start:{}",t1);//{}在这里表示占位符
try {
Object result=jp.proceed();//调用本类内部切入点对应其它通知或其它切面或目标方法。
long t2=System.currentTimeMillis();
log.info("end: {}",t2);
saveLog(jp,(t2-t1));//记录正常行为日志
return result;
}catch (Throwable e) {
log.error("error end: {}",e.getMessage());
//可以在此位置记录异常行为日志
//return null;
throw e;
}
}
private void saveLog(ProceedingJoinPoint jp,long time) throws NoSuchMethodException, SecurityException, JsonProcessingException {
//1.获取用户行为信息
//1.1获取目标方法对象
Method targetMethod=getTargetMethod(jp);
//1.2获取目标方法的方法名信息
String targetMethodName=
targetMethod.getDeclaringClass().getName()+"."+targetMethod.getName();
//1.3获取目标方法上的操作名
String operation = getOperation(targetMethod);
//1.4 目标方法参数(转换为字符串)
//String params=Arrays.toString(jp.getArgs());
String params=
//将参数对象转换为json格式字符串
new ObjectMapper().writeValueAsString(jp.getArgs());
//2.封装用户行为信息
SysLog log=new SysLog();
log.setIp(IPUtils.getIpAddr());
log.setUsername(ShiroUtils.getUsername());//后续做完登陆以后,为登陆用户名
log.setOperation(operation);
log.setMethod(targetMethodName);
log.setParams(params);
log.setTime(time);
log.setCreatedTime(new Date());
//3.保存用户行为信息
sysLogService.saveObject(log);
}
private Method getTargetMethod(ProceedingJoinPoint jp) throws NoSuchMethodException, SecurityException {
Class<?> targetCls=jp.getTarget().getClass();
MethodSignature ms=(MethodSignature)jp.getSignature();
//获取目标方法
Method targetMethod=//目标方法(类全名+方法名)
targetCls.getDeclaredMethod(ms.getName(),ms.getParameterTypes());
return targetMethod;
}
private String getOperation(Method targetMethod) {
String operation="operation";
RequiredLog requiredLog=
targetMethod.getAnnotation(RequiredLog.class);
if(requiredLog!=null) {
operation=requiredLog.value();
}
return operation;
}
文章浏览阅读7.4k次,点赞16次,收藏100次。基于XDMA 的PCIE读写DDR概述: 想实现基于FPGA的PCIe通信,查阅互联网各种转载…基本都是对PCIe的描述,所以想写一下基于XDMA的PCIe通信的实现(PCIe结构仅做简单的描述(笔记),了解详细结构移至互联网)。实现功能:PC通过PCIE读写DDR,同时用户通过逻辑代码可以读取被写入DDR内的数据(我是通过VIO实现DDR任意地址,任意数据大小的读取。)。实践实践!!!说明:参考文档:PCI Express Base Specification Revision 3.0P_xdma ddr
文章浏览阅读1.7k次。本文主要介绍在使用缓存过程中经常会遇到的几个问题:缓存击穿、缓存雪崩、缓存穿透,以及其解决方案。之后会对缓存穿透的解决方案之一布隆过滤器,进行详细讲解。_缓存穿透 布隆过滤器
文章浏览阅读1.4k次。1、代码:主要写入时表要为小写,否则报错Could not reflect: requested table(s) not available in Enginefrom sqlalchemy import create_engineconn_string='oracle+cx_oracle://admin:[email protected]:1521/ORCL?charset=utf8'..._pandas cx_oracle 写入
文章浏览阅读1.1k次,点赞2次,收藏2次。API 学习:https://blog.csdn.net/gaofeng6565/article/details/115696823项目准备:https://codepen.io/选择React,AntDesign 模式,添加依赖 react-dnd(@14.0.2),react-dnd-html5-backend(@14.0.0)ListDrag.jsimport React, { useState } from "react";import { Button } from "antd"._const defaultlist =
文章浏览阅读2.4w次,点赞21次,收藏162次。更新完显卡驱动后,视频可以自动导入了,继续码。2018.08.111 坐标系转换ADST(Automated Driving System Toolbox)中的坐标系ADST中的坐标系:世界坐标系(world),所有车辆及其传感器都建立其上的固定坐标系。 车辆(Vechicle):固定在车身上。有代表性地,车辆坐标系建立在车辆后轴中点处的地面上。 传感器(Sensor):明确具..._ego vehicle
文章浏览阅读370次。SAP S/4 HANA新变化-FI数据模型 http://mp.weixin.qq.com/s?__biz=MzAwMjgyMTA4MQ==&mid=2652153162&idx=1&sn=aee6fc43e0577479854e4842df919c90&ch..._hana anlc
文章浏览阅读1.1k次,点赞2次,收藏5次。Table of Contents0-1字典树例题1. CSU 1216:异或最大值:给定一些数,任意两个数的最大异或值例题2.HDU 4825Xor Sum:每次询问给出一个数,找出一个与它异或结果最大的数例题3.HDU 5536Chip Factory: 计算(s[i] + s[j]) ^ s[k] 的最大值例题4.POJ 3764The xor-longe..._字典树例题 poj
文章浏览阅读881次。自学习CVE-2017-11882漏洞后,便开始希望学习更多的漏洞,提高一下对漏洞的理解。在github上找到一个很好的项目,基本涵盖了所有漏洞(https://github.com/hacksysteam/HackSysExtremeVulnerableDriver)。下载下来后,执行过后得到驱动文件HEVD.sys,以及漏洞利用程序HackSysEVDExploit.exe,然后开启双..._通过fs寄存器解决栈溢出
文章浏览阅读364次。通达OA(Office Anywhere网络智能办公系统)是中国通达公司的一套协同办公自动化软件。通达OA /share/handle.php存在一个认证绕过漏洞,利用该漏洞可以实现任意用户登录。攻击者可以通过构造恶意攻击代码,成功登录系统管理员账户,继而在系统后台上传恶意文件控制网站服务器。_tongda oa 身份绕过
文章浏览阅读3.8w次,点赞33次,收藏80次。Java使用LocalDate或LocalDateTime获取某个月的第一天和最后一天日期_localdate获取当月最后一天
文章浏览阅读6.2k次,点赞3次,收藏40次。银河麒麟ARM64 飞腾FT2000 linuxdeployqt linux打包qt下载linuxdeployqt-aarch64.AppImageqt版本说明linuxdeployqt打包准备编译好的程序插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入下载linuxdeployqt-aa_linuxdeployqt aarch64
文章浏览阅读1.6k次,点赞2次,收藏6次。工作流 通过计算机对业务流程自动化执行管理他主要解决的是使在多个参与者之间按照某种“预定义规则”自动进行传递稳定 信息或任务的过程通俗来讲 业务上一个玩着的审批流程 比如请假,出差 外出采购等工作流引擎就是来解决流程问题的 提高我们的工作效率如果没有工作流引擎 我们就需要自己去写逻辑 就特别的复杂 扩展性还不强使用工作流引擎 业务改变,不需要修改代码如果是我们自己写的逻辑 有可能 业务改变,代码也需要改变那么为什么工作流引擎不用修改代码因为我们的工作流引擎都实现了一个规范这个规范要_集成activiti