上篇文章已经介绍了注解的基本构成信息。这篇文章,主要介绍注解的解析。毕竟你只声明了注解,是没有用的。需要进行解析。主要就是利用反射机制在运行时进行查看和利用这些信息

在Class、Field、Method、Constructor中都有如下方法:

  1. //获取所有的注解
  2. public Annotation[] getAnnotations()
  3. //获取所有本元素上直接声明的注解,忽略inherited来的
  4. public Annotation[] getDeclaredAnnotations()
  5. //获取指定类型的注解,没有返回null
  6. public <A extends Annotation> A getAnnotation(Class<A> annotationClass)
  7. //判断是否有指定类型的注解
  8. public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)

Annotation 是一个借口,它表示注解,源码为:

  1. public interface Annotation {
  2. boolean equals(Object obj);
  3. int hashCode();
  4. String toString();
  5. //返回真正的注解类型
  6. Class<? extends Annotation> annotationType();
  7. }

实际上,所有的注解类型、内部实现时,都是扩展的Annotation

对于Method和Contructor,他们都有方法参数

  1. public Annotation[][] getParameterAnnotations()

日常工作中,每个公司都会自定义注解进行记录日志的,我们就做一个简单的记录日志操作的注解,结合aop和springboot

这里不再赘述,主要需要引入aop

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-aop</artifactId>
  4. </dependency>
  1. package com.kevin.anno.annotation;
  2. import java.lang.annotation.ElementType;
  3. import java.lang.annotation.Retention;
  4. import java.lang.annotation.RetentionPolicy;
  5. import java.lang.annotation.Target;
  6. @Target(ElementType.METHOD)
  7. @Retention(RetentionPolicy.RUNTIME)
  8. public @interface KevinLog {
  9. String value() default "";
  10. }
  1. package com.kevin.anno.aspect;
  2. import com.kevin.anno.annotation.KevinLog;
  3. import org.aspectj.lang.ProceedingJoinPoint;
  4. import org.aspectj.lang.annotation.Around;
  5. import org.aspectj.lang.annotation.Aspect;
  6. import org.aspectj.lang.annotation.Pointcut;
  7. import org.aspectj.lang.reflect.MethodSignature;
  8. import org.slf4j.Logger;
  9. import org.slf4j.LoggerFactory;
  10. import org.springframework.stereotype.Component;
  11. import org.springframework.web.context.request.RequestContextHolder;
  12. import org.springframework.web.context.request.ServletRequestAttributes;
  13. import javax.servlet.http.HttpServletRequest;
  14. import java.lang.reflect.Method;
  15. @Aspect
  16. @Component
  17. public class LogAscpect {
  18. private final static Logger logger = LoggerFactory.getLogger(LogAscpect.class);
  19. @Pointcut("@annotation(com.kevin.anno.annotation.KevinLog)")
  20. public void log() {
  21. }
  22. @Around("log()")
  23. public Object aroundAdvice(ProceedingJoinPoint point) throws Throwable {
  24. Object object = null;
  25. long start = System.currentTimeMillis();
  26. Method method = ((MethodSignature) MethodSignature.class.cast(point.getSignature())).getMethod();
  27. KevinLog kevinLog = method.getAnnotation(KevinLog.class);
  28. String operationName = kevinLog.value();
  29. object = point.proceed(point.getArgs());
  30. long end = System.currentTimeMillis();
  31. Long excuteTime = end - start;
  32. print(operationName, excuteTime, point);
  33. return object;
  34. }
  35. private void print(String operationName, Long excuteTime, ProceedingJoinPoint point) {
  36. ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
  37. HttpServletRequest request = attributes.getRequest();
  38. //operationName
  39. logger.info("operationName={}", operationName);
  40. //time
  41. logger.info("time={}", excuteTime);
  42. // url
  43. logger.info("url={}", request.getRequestURL());
  44. //method
  45. logger.info("method = {}", request.getMethod());
  46. //ip
  47. logger.info("ip = {}", request.getRemoteAddr());
  48. //类方法
  49. logger.info("class_method={}", point.getSignature().getDeclaringTypeName() + "." + point.getSignature().getName());
  50. //参数
  51. logger.info("args = {}", point.getArgs());
  52. }
  53. }
  1. package com.kevin.anno.controller;
  2. import com.kevin.anno.annotation.KevinLog;
  3. import org.springframework.web.bind.annotation.RequestMapping;
  4. import org.springframework.web.bind.annotation.RestController;
  5. @RestController
  6. public class HelloController {
  7. @RequestMapping(value = "/hello")
  8. @KevinLog("kevin test !")
  9. public String hello() {
  10. return "hello kevin";
  11. }
  12. }

访问:http://localhost:8080/hello

页面出现:hello kevin

控制台打印信息如下:

  1. 2018-10-22 10:38:22.456 INFO 3916 --- [nio-8080-exec-2] com.kevin.anno : operationName=kevin test !
  2. 2018-10-22 10:38:22.456 INFO 3916 --- [nio-8080-exec-2] com.kevin.anno.aspect.LogAscpect : time=7
  3. 2018-10-22 10:38:22.456 INFO 3916 --- [nio-8080-exec-2] com.kevin.anno.aspect.LogAscpect : url=http://localhost:8080/hello
  4. 2018-10-22 10:38:22.456 INFO 3916 --- [nio-8080-exec-2] com.kevin.anno.aspect.LogAscpect : method = GET
  5. 2018-10-22 10:38:22.457 INFO 3916 --- [nio-8080-exec-2] com.kevin.anno.aspect.LogAscpect : ip = 0:0:0:0:0:0:0:1
  6. 2018-10-22 10:38:22.457 INFO 3916 --- [nio-8080-exec-2] com.kevin.anno.aspect.LogAscpect : class_method=com.kevin.anno.controller.HelloController.hello
  7. 2018-10-22 10:38:22.457 INFO 3916 --- [nio-8080-exec-2] com.kevin.anno.aspect.LogAscpect : args = {}

其实, 大家可以自己写这玩玩,比较这个demo还用到了aop,工作中很少接触到aop。以至于面试的时候,问你aop的时候,自己都没有实际的应用过。

好了。玩的开心!

版权声明:本文为zhenghengbin原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/zhenghengbin/p/9828954.html