做爲一名開發人員,註解的的使用是最多見的了,好比Spring框架裏的業務層註解@Service、@Transaction,控制層用的@Controller、@Autowired,SpringBoot框架的啓動類註解@SpringBootApplication等等。那麼如何自定義註解呢?java
註解(Annotation)是元數據的一種形式,從JDK5.0 引入,它能爲代碼提供一些相關數據,以便於在代碼編譯或運行時使用。spring
Java中的註解能夠修飾類、方法、變量、參數等。註解能夠經過反射手段獲取其內容,在編譯器生成類文件時,註解能夠被嵌入到字節碼中。固然JVM也能夠保留註解的內容,在運行時動態,總結起來主要是如下幾個層面:數組
public static void main(String[] args) {
Date date = new Date();
//JDK源碼中,Date類的getDay方法被@Deprecated註解標註,表明方法已過期
int day = date.getDay();
}
複製代碼
@Slf4j
@Component
@Aspect
public class MyAspect {
@Before(value = "execution(public * com.test.controller.*.*(..))")
public void before(JoinPoint joinPoint) {
log.info("CLASS_METHOD:[{}]" , joinPoint.getSignature().getName());
}
}
複製代碼
@Configuration
public class RabbitMqConfig {
@Value("${spring.rabbitmq.host}")
private String rabbitMqHost;
@Value("${spring.rabbitmq.port}")
private String rabbitMqPort;
}
複製代碼
首先咱們先看下一個註解示例,下面是javafx.beans包下的@DefaultProperty註解 :springboot
package javafx.beans;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/** * Specifies a property to which child elements will be added or set when an * explicit property is not given. * * @since JavaFX 2.0 */
@Inherited
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface DefaultProperty {
/** * The name of the default property. */
public String value();
}
複製代碼
咱們看到定義註解與定義一個class類類似,不過其中class關鍵字被替換爲了@interface,註解裏聲明瞭一個String類型的value屬性,注意這種聲明屬性方式!稍後會詳細說明。同時還能夠看到DefaultProperty註解被@Inherited、@Documented、@Retention(RetentionPolicy.RUNTIME)、@Target(ElementType.TYPE)這些註解所修飾,這就是咱們須要知道另一個概念——元註解(meta-annotations)。bash
元註解是咱們在定義註解時須要用到的一些特殊含義的註解,能夠說它們是對聲明註解時的註解。java語言爲咱們默認提供瞭如下元註解,在java.lang.annotation包下,咱們來看下:框架
@Retention(RetentionPolicy.XX) 註解的保留域,表示註解的保留範圍,可選項有ide
@Target( ElementType.XX) 指定該註解可使用的地方,如類聲明、方法聲明,變量聲明等等, 在定義註解時,若是沒有使用Target指定,默認均可以使用。若是使用了Target指定使用的位置,那麼該註解只能在所指定的位置使用工具
@Documented 表示在使用Javadoc工具生成文檔時,包含此註解信息spa
@Inherited 表示當前註解是可繼承的,父類中所使用的註解若是被@Inherited修飾,子類會繼承父類中對應的註解code
明白了註解的外在定義形式,那麼咱們就來看下註解內部的屬性的定義方式,Talk is cheap. Show me the code 多說無益,直接上代碼
@Documented
@Inherited
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
/** *一、屬性的定義和接口中方法聲明相似,訪問修飾符默認是public,可省略,注意屬性名後面跟了() */
String name();
/** * 二、能夠經過default爲屬性指定默認值,在註解使用時,能夠爲之賦值, 也能夠不賦值 * 固然若是不經過default爲屬性指定默認值,在註解使用必須使用該屬性而且爲之賦值 */
int age() default 1;
/** * 三、註解中的屬性value比較特殊,若是使用註解時僅爲該屬性賦值,"value="能夠省略掉, * 可是若是和其餘屬性同時賦值,「value=」則不能省略,這個特性和value的屬性類型無關 */
String value() default "";
/** * 4.註解中屬性的類型能夠是基本數據類型及其數組、類、枚舉、註解 */
boolean sex() default true;
}
複製代碼
在上面代碼中,咱們自定義了@MyAnnotation註解,而且指明@Target({ElementType.METHOD})代表此註解只能用在方法聲明上, @Retention(RetentionPolicy.RUNTIME)指定其保留到代碼運行時,因此咱們能夠經過反射獲取MyAnnotation的屬性值。下面咱們定義了一個Person類,並在其中定義了一個sayHello方法,在方法聲明上,咱們使用@MyAnnotation註解,咱們將使用反射調用sayHello方法,而且使用MyAnnotation註解中的屬性值
package com.test.annotation;
import com.test.enu.Color;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Person {
@MyAnnotation(name="韓梅梅",age = 30,sex = true,clothes = Color.YELLOW)
public void sayHello(String name){
System.out.println("Hello!" + name);
}
public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
Person person = new Person();
//獲取Person類的Class對象
Class<? extends Person> personClass = person.getClass();
//獲取類中聲明的方法列表
Method[] declaredMethods = personClass.getDeclaredMethods();
for (Method method : declaredMethods) {
//判斷當前方法是否含有MyAnnotation註解
if(method.isAnnotationPresent(MyAnnotation.class)){
//獲取MyAnnotation類型註解
MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);
//反射調用方法,並傳遞註解name屬性值爲參數
Object invoke = method.invoke(person,myAnnotation.name());
//打印註解中定義的各個類型的值
System.out.println(myAnnotation);
System.out.println(myAnnotation.name()+","+myAnnotation.sex()+","+myAnnotation.age());
}
}
}
}
複製代碼
此時的IDE控制檯輸出,說明咱們經過反射在運行時獲取到了@MyAnnotation註解的值
Hello!韓梅梅
韓梅梅,true,30
@com.test.annotation.MyAnnotation(value=, age=30, sex=true, name=韓梅梅, clothes=YELLOW)
複製代碼
JDK自帶了一些原先定義好的註解,咱們能夠直接使用
至於註解內部詳細內容,你們能夠點進去源碼查看。但願本篇文章對你有所幫助!