java自定義註解學習(三)_註解解析及應用
上篇文章已經介紹了註解的基本構成資訊。這篇文章,主要介紹註解的解析。畢竟你只宣告瞭註解,是沒有用的。需要進行解析。主要就是利用反射機制在執行時進行檢視和利用這些資訊
常用方法彙總
在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的時候,自己都沒有實際的應用過。
好了。玩的開心!
相關文章
- JAVA-註解(2)-自定義註解及反射註解Java反射
- Java中的註解-自定義註解Java
- 自定義JAVA註解Java
- 自定義註解以及註解在反射中的應用反射
- Java 自定義註解及使用場景Java
- java中如何自定義註解Java
- Java中的註解及自定義註解你用的怎麼樣,能不能像我這樣應用自如?Java
- Java 自定義註解在登入驗證的應用Java
- 自定義註解
- Java註解-後設資料、註解分類、內建註解和自定義註解Java
- 自定義ConditionalOnXX註解
- Java學習_註解Java
- app直播原始碼,java自定義註解APP原始碼Java
- Java開發學習(十三)----基於註解開發定義第三方bean及註解開發總結JavaBean
- Java註解全面解析Java
- Java 註解完全解析Java
- Java 註解全面解析Java
- Spring Boot 自定義註解失效Spring Boot
- SpringBoot自定義校驗註解Spring Boot
- 自定義校驗註解ConstraintValidatorAI
- springBoot自定義註解的使用Spring Boot
- java 註解學習補充Java
- SpringMVC 解析(三) Controller 註解SpringMVCController
- 自定義註解+反射 實現給註解新增功能的效果反射
- Java註解解析-基礎+執行時註解(RUNTIME)Java
- SpringBoot分組校驗及自定義校驗註解Spring Boot
- Java註解解析-搭建自己的註解處理器(CLASS註解使用篇)Java
- java註解初步學習和使用Java
- JUnit5學習之五:標籤(Tag)和自定義註解
- SpringBoot自定義註解、AOP列印日誌Spring Boot
- 每日註解學習(九)@PostConstruct和@PreConstruct註解Struct
- @Param註解學習
- java如何讓程式碼變得優雅——自定義註解Java
- Java註解與反射學習筆記Java反射筆記
- @lombok註解背後的原理是什麼,讓我們走近自定義Java註解處理器LombokJava
- JSR303自定義校驗註解,自定義註解校驗字串是否是JSON字串,可擴充套件字串JSON套件
- 這一次搞懂Spring自定義標籤以及註解解析原理Spring
- Java 註解及其在 Android 中的應用JavaAndroid