本文共 4849 字,大约阅读时间需要 16 分钟。
上篇文章已经介绍了注解的基本构成信息。这篇文章,主要介绍注解的解析。毕竟你只声明了注解,是没有用的。需要进行解析。主要就是利用反射机制在运行时进行查看和利用这些信息
在Class、Field、Method、Constructor中都有如下方法:
//获取所有的注解public Annotation[] getAnnotations()//获取所有本元素上直接声明的注解,忽略inherited来的public Annotation[] getDeclaredAnnotations()//获取指定类型的注解,没有返回nullpublic A getAnnotation(Class annotationClass)//判断是否有指定类型的注解public boolean isAnnotationPresent(Class annotationClass)
Annotation 是一个借口,它表示注解,源码为:
public interface Annotation { boolean equals(Object obj); int hashCode(); String toString(); //返回真正的注解类型 Class annotationType();}
实际上,所有的注解类型、内部实现时,都是扩展的Annotation
对于Method和Contructor,他们都有方法参数
public Annotation[][] getParameterAnnotations()
日常工作中,每个公司都会自定义注解进行记录日志的,我们就做一个简单的记录日志操作的注解,结合aop和springboot
这里不再赘述,主要需要引入aop
org.springframework.boot spring-boot-starter-aop
package com.kevin.anno.annotation;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface KevinLog { String value() default "";}
package com.kevin.anno.aspect;import com.kevin.anno.annotation.KevinLog;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.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Component;import org.springframework.web.context.request.RequestContextHolder;import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.http.HttpServletRequest;import java.lang.reflect.Method;@Aspect@Componentpublic class LogAscpect { private final static Logger logger = LoggerFactory.getLogger(LogAscpect.class); @Pointcut("@annotation(com.kevin.anno.annotation.KevinLog)") public void log() { } @Around("log()") public Object aroundAdvice(ProceedingJoinPoint point) throws Throwable { Object object = null; long start = System.currentTimeMillis(); Method method = ((MethodSignature) MethodSignature.class.cast(point.getSignature())).getMethod(); KevinLog kevinLog = method.getAnnotation(KevinLog.class); String operationName = kevinLog.value(); object = point.proceed(point.getArgs()); long end = System.currentTimeMillis(); Long excuteTime = end - start; print(operationName, excuteTime, point); return object; } private void print(String operationName, Long excuteTime, ProceedingJoinPoint point) { ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); //operationName logger.info("operationName={}", operationName); //time logger.info("time={}", excuteTime); // url logger.info("url={}", request.getRequestURL()); //method logger.info("method = {}", request.getMethod()); //ip logger.info("ip = {}", request.getRemoteAddr()); //类方法 logger.info("class_method={}", point.getSignature().getDeclaringTypeName() + "." + point.getSignature().getName()); //参数 logger.info("args = {}", point.getArgs()); }}
package com.kevin.anno.controller;import com.kevin.anno.annotation.KevinLog;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class HelloController { @RequestMapping(value = "/hello") @KevinLog("kevin test !") public String hello() { return "hello kevin"; }}
访问:
页面出现:hello kevin
控制台打印信息如下:
2018-10-22 10:38:22.456 INFO 3916 --- [nio-8080-exec-2] com.kevin.anno : operationName=kevin test !2018-10-22 10:38:22.456 INFO 3916 --- [nio-8080-exec-2] com.kevin.anno.aspect.LogAscpect : time=72018-10-22 10:38:22.456 INFO 3916 --- [nio-8080-exec-2] com.kevin.anno.aspect.LogAscpect : url=http://localhost:8080/hello2018-10-22 10:38:22.456 INFO 3916 --- [nio-8080-exec-2] com.kevin.anno.aspect.LogAscpect : method = GET2018-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:12018-10-22 10:38:22.457 INFO 3916 --- [nio-8080-exec-2] com.kevin.anno.aspect.LogAscpect : class_method=com.kevin.anno.controller.HelloController.hello2018-10-22 10:38:22.457 INFO 3916 --- [nio-8080-exec-2] com.kevin.anno.aspect.LogAscpect : args = {}
其实, 大家可以自己写这玩玩,比较这个demo还用到了aop,工作中很少接触到aop。以至于面试的时候,问你aop的时候,自己都没有实际的应用过。
好了。玩的开心!
转载地址:http://ijiex.baihongyu.com/