关于注解的定义,使用等就不说了,在这里直接上干货,自定义注解相关的东西。
元注解的作用就是注解其他注解,一般我们使用自定义注解时,就需要用元注解来标注我们自己的注解,一共有四个元注解
元注解:
java.lang.annotation提供了四种元注解,专门注解其他的注解(在自定义注解的时候,需要使用到元注解):
@Documented –注解是否将包含在JavaDoc中 @Retention –什么时候使用该注解 @Target –注解用于什么地方 @Inherited – 是否允许子类继承该注解1.)@Retention– 定义该注解的生命周期
● RetentionPolicy.SOURCE : 在编译阶段丢弃。这些注解在编译结束之后就不再有任何意义,所以它们不会写入字节码。@Override, @SuppressWarnings都属于这类注解。 ● RetentionPolicy.CLASS : 在类加载的时候丢弃。在字节码文件的处理中有用。注解默认使用这种方式 ● RetentionPolicy.RUNTIME : 始终不会丢弃,运行期也保留该注解,因此可以使用反射机制读取该注解的信息。我们自定义的注解通常使用这种方式。2.)Target – 表示该注解用于什么地方。默认值为任何元素,表示该注解用于什么地方。可用的ElementType参数包括
● ElementType.CONSTRUCTOR:用于描述构造器 ● ElementType.FIELD:成员变量、对象、属性(包括enum实例) ● ElementType.LOCAL_VARIABLE:用于描述局部变量 ● ElementType.METHOD:用于描述方法 ● ElementType.PACKAGE:用于描述包 ● ElementType.PARAMETER:用于描述参数 ● ElementType.TYPE:用于描述类、接口(包括注解类型) 或enum声明3.)@Documented–一个简单的Annotations标记注解,表示是否将注解信息添加在java文档中。
4.)@Inherited – 定义该注释和子类的关系
@Inherited 元注解是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。自定义注解格式:
public @interface 注解名 {定义体}
1. Annotation型定义为@interface, 所有的Annotation会自动继承java.lang.Annotation这一接口,并且不能再去继承别的类或是接口.
2. 参数成员只能用public或默认(default)这两个访问权修饰 3. 参数成员只能用基本类型byte,short,char,int,long,float,double,boolean八种基本数据类型和String、Enum、Class、annotations等数据类型,以及这一些类型的数组. 4. 要获取类方法和字段的注解信息,必须通过Java的反射技术来获取 Annotation对象,因为你除此之外没有别的获取注解对象的方法 5. 注解也可以没有定义成员,因业务需要,为了放置表单数据重复提交,比如转账,误操作点了两下,这时候给出一个操作频繁的提示,那么我们可以写一个注解,在需要防止重复提交的地方添加上注解就ok了。代码如下:
自定义一个注解
1 @Target(ElementType.METHOD)2 @Retention(RetentionPolicy.RUNTIME)3 @Documented4 public @interface AvoidRepeatableCommit {5 6 long timeout() default 5;7 }
切面:
1 @Aspect 2 @Component 3 public class VoidRepeatCommitAspectJ { 4 5 Logger logger = LoggerFactory.getLogger(this.getClass()); 6 @Autowired 7 @Qualifier("redisTemplate2") 8 private RedisTemplatetemplate; 9 10 @Pointcut("@annotation(com.topband.beings.aop.AvoidRepeatableCommit)")11 public void cutPoint(){}12 @Around("cutPoint()")13 public Object around(ProceedingJoinPoint point) throws Throwable{14 logger.info("around point : {}",point);15 HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();16 String ip = ServletUtils.getIpAddr();17 String token = request.getHeader(SystemConstants.TOKEN_HEADER);18 logger.info("ip:{};token:{}",ip,token);19 //获取注解20 MethodSignature signature = (MethodSignature) point.getSignature();21 Method method = signature.getMethod();22 //目标类、方法23 String className = method.getDeclaringClass().getName();24 String methodName = method.getName();25 AvoidRepeatableCommit avoidRepeatableCommit = method.getAnnotation(AvoidRepeatableCommit.class);26 long timeout = avoidRepeatableCommit.timeout();27 if (timeout < 0){28 timeout = 5;29 }30 String key =SystemConstants.TOKEN_CACHE_PREFIX + token + "-" + className + "-" + methodName;31 logger.info("key:{}; template:{}",key,template);32 Object obj = template.opsForValue().get(key);33 logger.info("obj:{}",obj);34 String str = null;35 if(obj==null){36 ;37 }else{38 str = (String) template.opsForValue().get(key);39 logger.info("str:{}",str);40 }41 // String str = redisUtil.get(key);42 //查询redis 中是否存在此key 无则添加,有则抛出异常43 if (StringUtil.isEmpty(str)){44 String value = token + "-" + className + "-" + methodName;45 template.opsForValue().set(key, value, 5,TimeUnit.SECONDS);46 return point.proceed();47 }else {48 ResponseObj response = new ResponseObj();49 response.setStatus(Defined.STATUS_ERROR);50 response.setMessage("操作过于频繁");51 return response;52 }53 }54 }
然后在需要防止重复提交的地方,加上注解就可以了。