Java 註解 基礎

註解篇

如今的開發,愈來愈多的使用到註解簡化開發,好比spring_boot、spring_cloud中的一系列註解,這就讓我很是感興趣的事情java

接觸spring原始開發並很少,也知道前期spring開發會帶來一大堆xml的配置,由於在下仍是比較渣的coder面試

我也在面試過程當中常常被問spring的特性什麼什麼的,像我這樣從spring_boot往回走的人很少吧,不理解註解都很差意思說spring,mybatis也是spring

 

好處

①學習註解可以讀懂別人寫的代碼,特別是框架相關的代碼,在學習或工做中會去看別人的代碼,不少知識是和註解相關的引用體現,很差好研究一下就不能很順暢的看懂其代碼套路編程

②讓咱們註解編程更加簡潔,代碼更加清晰,趨向於programmer的進階,engineer的方向前進,能夠將不少邏輯才能實現的方法轉化成一個註解來替代,來一套讓本身飛起來的服務數組

③讓本身的逼格別具特點,讓別人也向你學習session

 

你們都會使用註解,但不必定都會自定義註解來解決問題,開始學習mybatis

 

概念

Java提供了一種原程序中的元素關聯任何信息和任何元數據的途徑和方法app

就像學校裏起步學Java時就教面向對面的概念,比較抽象,須要在後面的編程學習或工做中才能慢慢領悟的方式學習---知新而溫故框架

 

解析註解

★Java中的常見註解ide

① JDK常見註解: @Override@Deprecated 、@Suppvisewarnings等

建立一個接口和一個實現類

public interface Dog {
    String kind();
    Integer age();
    void work();
}
public class SingleDog implements Dog {
    @Override
    public String kind() {return null;}
    @Override
    public Integer age() {return null;}
    @Override
    public void work() {}
}

@Override出現,覆蓋父類的方法,能夠發現若是將接口的方法注掉,標@Override的實現方法就會出現問題

 

每隻Dog都有品種,年齡,但不是每隻Dog都能work,因此決定將此方法做廢,使用@Deprecated註解

public interface Dog {
    String kind();
    Integer age();
    @Deprecated
    void work();
}

此時實現的方法不會出現什麼問題,在調用的時候就會出現提示信息,以下:

public class DemoMain {
    public static void main(String[] args) {
        Dog dog=new SingleDog();
        dog.kind();
        dog.age();
        dog.work();
    }
}

有的編程工具還會出現警告,也有某些編程潔癖的公司是不容許出現警告和此類問題

 

在方法上加@Suppvisewarnings註解,就能夠去除警告和刪除線

public class DemoMain {
    @SuppressWarnings("deprecation")
    public static void main(String[] args) {
        Dog dog=new SingleDog();
        dog.kind();
        dog.age();
        dog.work();
    }
}

 

② 第三方註解

Spring常見註解: @Autowired 、@Service 、@Repository等

Mybatis常見註解: @InsertProvider 、@Select 、 @Options等

下面以@Autowired示例,對比引入先後的展現效果: 

》類的實現

public class DogManagerImpl implements DogMapper {
    private DogDao dogDao;

    public void setDogDao(DogDao dogDao) {
        this.dogDao = dogDao;
    }
    //...
}

配置文件

<bean id="DogManagerImpl" class ="com.cloud.eureka.demo.DogManager">
    <property name="dogDao" ref="dogDao" />
</bean>
<bean id="dogDao" class ="com.cloud.eureka.demo.DogManagerImpl">
    <property name="sessionFactory" ref="mySessionFactory" />
</bean>

 

》引入@Autowired

public class DogManagerImpl implements DogMapper {
    @Autowired
    private DogDao dogDao;
    //...
}

兩種引入對比,我這麼懶的人,確定用@Autowired

 

★註解的分類

①按運行機制分

  • 源碼註解: 只在源碼中存在,編譯成class文件時就不存在
  • 編譯時註解: 在源碼和class文件中都存在,例如@Override 、@Deprecated等,好比Override在編譯時告訴編譯器,這個子類方法是覆蓋父類的方法;若是實現,沒有覆蓋,那麼代碼上就會報錯
  • 運行時註解: 在運行時起做用,能夠影響運行邏輯,例如@Autowired

②按來源分

  • 來自JDK的註解
  • 來自第三方的註解 : 這個使用的最多
  • 自定義的註解

③元註解

  • 給註解的註解

 

★自定義註解

》自定義的語法要求 》註解的註解(元註解)

import java.lang.annotation.*;

//@Target、@Retention、@Inherited、@Documented 爲元註解
@Target({ElementType.METHOD,ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
//以public @interface關鍵字定義註解
public @interface MyAnnotation {
    //成員的類型有規範,包括基本類型、String、Class、Annotation、Enumeration
    //成員大部分使用基本類型、Enumeration以及String,其餘的比較少見
    //成員不能夠List、Map、對象等類型
    //沒有成員的註解稱爲標識註解

    //成員以無參數、無異常方式聲明
    String hello();

    //若是註解只有一個成員,則成員的名字必須爲value,此處的必須是一個規範
    //若是MyAnnotation只有一個成員,那麼使用的方式@MyAnnotation("val")
    //正常使用方式@MyAnnotation(value="val")
    String value();

    //能夠爲成員指定一個默認值default
    int age() default 21;
}

 

@Target 定義一個註解的做用域,其有一個成員ElementType[] value();是一個枚舉數組

ElementType常量提供簡答的分類,經常使用於@Target元註釋用於指定編寫註釋的合法位置,給定類型

/** Class, interface (including annotation type), or enum declaration */
TYPE,

/** Field declaration (includes enum constants) */
FIELD,

/** Method declaration */
METHOD,

/** Formal parameter declaration */
PARAMETER,

/** Constructor declaration */
CONSTRUCTOR,

/** Local variable declaration */
LOCAL_VARIABLE,

/** Annotation type declaration */
ANNOTATION_TYPE,

/** Package declaration */
PACKAGE,

/** Type parameter declaration */
TYPE_PARAMETER,

/** Use of a type */
TYPE_USE

@Retention(RetentionPolicy.RUNTIME)註解定義運行機制,聲明生命週期類型 SOURCE, CLASS, RUNTIME

@Inherrited註解容許子類繼承

@Documented生成javadoc時會包含註解信息,標識註解

 

》使用自定義註解

@MyAnnotation(hello = "tom",value = "val",age = 18)
public String demo(){
   return "demo";
}

 

★解析註解

概念: 經過反射獲取類、函數或成員上的運行時註解信息,從而實現動態控制程序運行的邏輯

下面定義一個註解,經過反射解析註解

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface MyAnnotation {
    String value();
}
public interface Dog {
    String kind();
    
    String name();
    
    void work();
}
@MyAnnotation("這是實現類")
public class DogImpl implements Dog {
    @Override
    @MyAnnotation("這是kind方法")
    public String kind() {return null;}

    @Override
    public String name() {
        return null;
    }

    @Override
    public void work() {}
}
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

public class ParseAnnotation {
    public static void main(String[] args) throws ClassNotFoundException {
        //1.類加載器
        Class c = Class.forName("com.cloud.eureka.demo.DogImpl");

        //2.找到類上的註解
        boolean b = c.isAnnotationPresent(MyAnnotation.class);

        if (b) {
            //3.獲取註解示例
            MyAnnotation annotation = (MyAnnotation) c.getAnnotation(MyAnnotation.class);
            System.out.println("3。" + annotation.value());
        }

        System.out.println("-------------------------------");

        //4.找到方法上的註解
        Method[] methods = c.getMethods();
        for (Method method : methods) {
            boolean mb = method.isAnnotationPresent(MyAnnotation.class);
            if (mb) {
                //5.獲取註解示例
                MyAnnotation annotation = (MyAnnotation) method.getAnnotation(MyAnnotation.class);
                System.out.println("5。" + annotation.value());
            }
        }

        System.out.println("-------------------------------");

        //6.獲取方法的註解
        for (Method method : methods) {
            Annotation[] annotations = method.getAnnotations();
            for (Annotation annotation : annotations) {
                if (annotation instanceof MyAnnotation) {
                    MyAnnotation myAnnotation = (MyAnnotation) annotation;
                    System.out.println("6。" + myAnnotation.value());
                }
            }
        }
    }
}

控制檯輸出:

 

將MyAnnotation註解的元註解@Retention改爲@Retention(RetentionPolicy.SOURCE),就會反射不到,由於這個做用域只在源碼級別存在,編譯運行就不存在了; 元註解@Retention改爲@Retention(RetentionPolicy.CLASS),運行結構控制檯依然是空的,執行的main是運行時的環境,只能是運行時註解@Retention(RetentionPolicy.RUNTIME)

 

提示: @Inherited元註解在接口實現時是無效的,是類與類的繼承纔會有效果,而且只會繼承類上的註解信息,不會繼承方法上的註解

------------------------------------------------------------------

相關文章
相關標籤/搜索