java注释和注解_深入理解JAVA注解(Annotation)以及自定义注解
Java 注解(Annotation)又稱 Java 標(biāo)注,是 JDK5.0 引入的一種注釋機制。Java 語言中的類、方法、變量、參數(shù)和包等都可以被標(biāo)注。注解可以看作是一種特殊的標(biāo)記,在程序在編譯或者運行時可以檢測到這些標(biāo)記而進行一些特殊的處理。本文對 Annotation 進行了整理帶你一步一步解開Java注解的神秘面紗并實現(xiàn)自己的自定義注解。
元注解
元注解的作用就是負(fù)責(zé)注解其他注解。Java5.0定義了4個標(biāo)準(zhǔn)的meta-annotation類型,它們被用來提供對其它 annotation類型作說明。他們位于java.lang.annotation包中。
元注解下
@Target
@Retention
@Documented
@Inherited
@Target:
源碼如下
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
/**
* Returns an array of the kinds of elements an annotation type
* can be applied to.
* @return an array of the kinds of elements an annotation type
* can be applied to
*/
ElementType[] value();
}
它表明該注解可以應(yīng)用的java元素類型
ElementType.TYPE:應(yīng)用于類、接口(包括注解類型)、枚舉
ElementType.FIELD:應(yīng)用于屬性(包括枚舉中的常量)
ElementType.METHOD:應(yīng)用于方法
ElementType.PARAMETER:應(yīng)用于方法的形參
ElementType.CONSTRUCTOR:應(yīng)用于構(gòu)造函數(shù)
ElementType.LOCAL_VARIABLE:應(yīng)用于局部變量
ElementType.ANNOTATION_TYPE:應(yīng)用于注解類型
ElementType.PACKAGE:應(yīng)用于包
ElementType.TYPE_PARAMETER:1.8版本新增,應(yīng)用于類型變量)
ElementType.TYPE_USE:1.8版本新增,應(yīng)用于任何使用類型的語句中(例如聲明語句、泛型和強制轉(zhuǎn)換語句中的類型)
@Retention:源碼如下
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
/**
* Returns the retention policy.
* @return the retention policy
*/
RetentionPolicy value();
}
它需要在什么級別保存該注釋信息,用于描述注解的生命周期
RetentionPolicy.SOURCE:在源文件中有效(即源文件保留),編譯時被丟棄,不包含在類文件中
RetentionPolicy.CLASS:在class文件中有效(即class保留),JVM加載時被丟棄,包含在類文件中,默認(rèn)值
RetentionPolicy.RUNTIME:在運行時有效(即運行時保留),由JVM 加載,包含在類文件中,在運行時可以被獲取到
@Documented:
源碼如下
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}
它表明該注解標(biāo)記的元素可以被Javadoc或類似的工具文檔化,@Documented是一個標(biāo)記注解,沒有成員。
@Inherited源碼如下
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}
表明使用了@Inherited注解的注解,所標(biāo)記的類的子類也會擁有這個注解是不是有點難以理解,我們舉個例子
自定義注解
自定義注解 @InheritedTest
package com.example.demo.annotation;
import java.lang.annotation.*;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited public @interface InheritedTest {
}
新建父類 Parent
package com.example.demo.test;
import com.example.demo.annotation.InheritedTest;
@InheritedTest
public class Parent {
public void testMethod(){
System.out.println("Parent " + Parent.class.isAnnotationPresent(InheritedTest.class));
}
}
新建子類 Child
package com.example.demo.test;
import com.example.demo.annotation.InheritedTest;
public class Child extends Parent {
public static void main(String[] args) {
Child child = new Child();
child.testMethod();
System.out.println("Child " + Child.class.isAnnotationPresent(InheritedTest.class));
}
}
isAnnotationPresent()方法表示指定注釋類型的注釋是否存在于此元素上,是則返回true,否則返回false。
我們運行子類可以看到如下結(jié)果
在子類中我們并沒有使用 @InheritedTest 注解,結(jié)果一樣返回了true,下面我們把InheritedTest中的@Inherited注釋掉,然后再運行子類結(jié)果如下
可以看到,現(xiàn)在返回了false。
簡單示例
package com.example.demo.annotation;
import java.lang.annotation.*;
@Target(ElementType.FIELD)
@Documented()
@Retention(RetentionPolicy.RUNTIME)
public @interface Color {
String value() default "";
}
以上我們就自定義了一個注解@Color,該注解應(yīng)用于屬性之上,在運行時有效,并且可以生成api文檔。使用方法
package com.example.demo.test;
import com.example.demo.annotation.Color;
public class Cat {
@Color("黃色")
private String color;
public String getColor(){
return this.color;
}
public void setColor(String color){
this.color = color;
}
public static void main(String args[]){
Cat cat = new Cat();
System.out.println(cat.getColor());
}
}
這里我們定義了一個Cat類,里面有一個屬性color,我們使用@Color(“黃色”)給他賦值為黃色,然后執(zhí)行這個類打印出結(jié)果如下
什么?怎么為null呢,是不是感覺被忽悠了?因為我們只是定義了這個注解,但是卻沒寫怎么處理被這個注解標(biāo)記了字段,這個時候打印出來的當(dāng)然為null了。
現(xiàn)在我們來修改一下Cat類
public static void main(String args[]) throws NoSuchFieldException {
Cat cat = new Cat();
Color color = Cat.class.getDeclaredField("color").getAnnotation(Color.class);
if (color != null) {
String value = color.value();
cat.setColor(value);
}
System.out.println(cat.getColor());
}
打印結(jié)果如下
以上我們簡單的處理了下注解,并把處理邏輯放在了main方法中,其實這是不合理的。我們通過用下面的例子,使用Spring AOP面向切面編程思想來自定義日志注解。
自定義注解
自定義日志注解@SysLog
package com.example.demo.annotation;
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Documented()
@Retention(RetentionPolicy.RUNTIME)
public @interface SysLog {
String value() default "";
}
定義切面
package com.example.demo.aspect;
import com.example.demo.annotation.SysLog;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
@Aspect
@Component
@Slf4j
public class SysLogAspect {
@Pointcut("@annotation(com.example.demo.annotation.SysLog)")
private void logPointCut() {
}
@Before("logPointCut()")
private void before(JoinPoint joinPoint){
String className = joinPoint.getTarget().getClass().getName();
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String methodName = signature.getName();
Method method = signature.getMethod();
SysLog sysLog = method.getAnnotation(SysLog.class);
String value = sysLog.value();
log.info(className);
log.info(methodName);
log.info(value);
log.info("這里我們就可以自己處理了");
}
@After("logPointCut()")
private void after(){
log.info("執(zhí)行之后");
}
}
測試注解
package com.example.demo.test;
import com.example.demo.annotation.SysLog;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController @RequestMapping("/log")
public class LogTest {
@SysLog("測試日志打印")
@RequestMapping("/test")
public String testLog(){
return "這里是測試自定義注解日志打印";
}
}
用postman訪問localhost:8080/log/test結(jié)果如下
控制臺日志打印如下
以上我們就完成了自定日志注解的實現(xiàn),以上例子只是示例,實際開發(fā)中還可以又更多功能實現(xiàn)。好了,本文介紹就到這里了,如有錯誤請?zhí)岢鲋刚?/p>
總結(jié)
以上是生活随笔為你收集整理的java注释和注解_深入理解JAVA注解(Annotation)以及自定义注解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java通过Netty,实现Websoc
- 下一篇: 从零开始学_JavaScript_系列(