java自定義註解學習(三)_註解解析及應用
阿新 • • 發佈:2018-12-16
上篇文章已經介紹了註解的基本構成資訊。這篇文章,主要介紹註解的解析。畢竟你只聲明瞭註解,是沒有用的。需要進行解析。主要就是利用反射機制在執行時進行檢視和利用這些資訊
常用方法彙總
在Class、Field、Method、Constructor中都有如下方法:
//獲取所有的註解 public Annotation[] getAnnotations() //獲取所有本元素上直接宣告的註解,忽略inherited來的 public Annotation[] getDeclaredAnnotations() //獲取指定型別的註解,沒有返回null public <A extends Annotation> A getAnnotation(Class<A> annotationClass) //判斷是否有指定型別的註解 public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
Annotation 是一個藉口,它表示註解,原始碼為:
public interface Annotation {
boolean equals(Object obj);
int hashCode();
String toString();
//返回真正的註解型別
Class<? extends Annotation> annotationType();
}
實際上,所有的註解型別、內部實現時,都是擴充套件的Annotation
對於Method和Contructor,他們都有方法引數
public Annotation[][] getParameterAnnotations()
應用註解
日常工作中,每個公司都會自定義註解進行記錄日誌的,我們就做一個簡單的記錄日誌操作的註解,結合aop和springboot
1.建立springboot專案
這裡不再贅述,主要需要引入aop
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2.定義自定義註解
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 "";
}
3.定義aspect及解析註解
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
@Component
public 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());
}
}
4. 在請求方法上加上自定義註解
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;
@RestController
public class HelloController {
@RequestMapping(value = "/hello")
@KevinLog("kevin test !")
public String hello() {
return "hello kevin";
}
}
5.啟動測試
訪問:http://localhost:8080/hello
頁面出現: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=7
2018-10-22 10:38:22.456 INFO 3916 --- [nio-8080-exec-2] com.kevin.anno.aspect.LogAscpect : url=http://localhost:8080/hello
2018-10-22 10:38:22.456 INFO 3916 --- [nio-8080-exec-2] com.kevin.anno.aspect.LogAscpect : method = GET
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
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
2018-10-22 10:38:22.457 INFO 3916 --- [nio-8080-exec-2] com.kevin.anno.aspect.LogAscpect : args = {}
總結
其實, 大家可以自己寫這玩玩,比較這個demo還用到了aop,工作中很少接觸到aop。以至於面試的時候,問你aop的時候,自己都沒有實際的應用過。
好了。玩的開心!