成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

注解就這么簡(jiǎn)單

FrozenMap / 2865人閱讀

摘要:上面在將注解信息注入到方法中的時(shí)候,我們最后加上了的注解不然就會(huì)報(bào)錯(cuò)了那它是干什么用的呢只能用于修飾其他的,用于指定被修飾的被保留多長(zhǎng)時(shí)間。

前言

今天要講的是注解,對(duì)于本章節(jié),最好是有Servlet基礎(chǔ)的人查閱~因?yàn)閱渭兪荍ava基礎(chǔ)的話,可能用不上注解這個(gè)東西。但如果開(kāi)發(fā)過(guò)Servlet,就對(duì)@WebServlet不會(huì)陌生。

現(xiàn)在的開(kāi)發(fā)都推崇使用注解來(lái)進(jìn)行開(kāi)發(fā),這樣就可以免去寫(xiě)XML配置了,十分方便的一項(xiàng)技術(shù)~

學(xué)習(xí)注解可以更好地理解注解是怎么工作的,看見(jiàn)注解了就可以想到它的運(yùn)行原理了~。

如果有錯(cuò)的地方請(qǐng)大家多多包涵并歡迎在評(píng)論區(qū)指正~

一、什么是注解?

注解:Annotation....

注解其實(shí)就是代碼中的特殊標(biāo)記,這些標(biāo)記可以在編譯、類(lèi)加載、運(yùn)行時(shí)被讀取,并執(zhí)行相對(duì)應(yīng)的處理。

二、為什么我們需要用到注解?

傳統(tǒng)的方式,我們是通過(guò)配置文件(xml文件)來(lái)告訴類(lèi)是如何運(yùn)行的。

有了注解技術(shù)以后,我們就可以通過(guò)注解告訴類(lèi)如何運(yùn)行

例如:我們以前編寫(xiě)Servlet的時(shí)候,需要在web.xml文件配置具體的信息

我們使用了注解以后,可以直接在Servlet源代碼上,增加注解...Servlet就被配置到Tomcat上了。也就是說(shuō),注解可以給類(lèi)、方法上注入信息。

明顯地可以看出,這樣是非常直觀的,并且Servlet規(guī)范是推崇這種配置方式的。

三、基本Annotation

在java.lang包下存在著5個(gè)基本的Annotation,其中有3個(gè)Annotation我們是非常常見(jiàn)的了。

3.1@Overried

重寫(xiě)注解

如果我們使用IDE重寫(xiě)父類(lèi)的方法,我們就可以看見(jiàn)它了。那它有什么用呢??

@Overried是告訴編譯器要檢查該方法是實(shí)現(xiàn)父類(lèi)的...可以幫我們避免一些低級(jí)的錯(cuò)誤...

比如,我們?cè)趯?shí)現(xiàn)equals()方法的時(shí)候,把euqals()打錯(cuò)了,那么編譯器就會(huì)發(fā)現(xiàn)該方法并不是實(shí)現(xiàn)父類(lèi)的,與注解@Overried沖突,于是就會(huì)給予錯(cuò)誤。

3.2@Deprecated

過(guò)時(shí)注解

該注解也非常常見(jiàn),Java在設(shè)計(jì)的時(shí)候,可能覺(jué)得某些方法設(shè)計(jì)得不好,為了兼容以前的程序,是不能直接把它拋棄的,于是就設(shè)置它為過(guò)時(shí)。

Date對(duì)象中的toLocalString()就被設(shè)置成過(guò)時(shí)了

    @Deprecated
    public String toLocaleString() {
        DateFormat formatter = DateFormat.getDateTimeInstance();
        return formatter.format(this);
    }

當(dāng)我們?cè)诔绦蛑姓{(diào)用它的時(shí)候,在IDE上會(huì)出現(xiàn)一條橫杠,說(shuō)明該方法是過(guò)時(shí)的。

3.3@SuppressWarnings

抑制編譯器警告注解

該注解在我們寫(xiě)程序的時(shí)候并不是很常見(jiàn),我們可以用它來(lái)讓編譯器不給予我們警告

當(dāng)我們?cè)谑褂眉系臅r(shí)候,如果沒(méi)有指定泛型,那么會(huì)提示安全檢查的警告

如果我們?cè)陬?lèi)上添加了@SuppressWarnings這個(gè)注解,那么編譯器就不會(huì)給予我們警告了

3.4@SafeVarargs

Java 7“堆污染”警告

什么是堆污染呢??當(dāng)把一個(gè)不是泛型的集合賦值給一個(gè)帶泛型的集合的時(shí)候,這種情況就很容易發(fā)生堆污染....

這個(gè)注解也是用來(lái)抑制編譯器警告的注解...用的地方并不多,我也不詳細(xì)說(shuō)明了......有用到的時(shí)候再回來(lái)填坑吧。

3.5@FunctionalInterface

@FunctionalInterface用來(lái)指定該接口是函數(shù)式接口

用該注解顯示指定該接口是一個(gè)函數(shù)式接口。

四、自定義注解基礎(chǔ)

上面講解的是java.lang包下的5個(gè)注解,我們是可以自己來(lái)寫(xiě)注解,給方法或類(lèi)注入信息。

4.1標(biāo)記Annotation

沒(méi)有任何成員變量的注解稱(chēng)作為標(biāo)記注解,@Overried就是一個(gè)標(biāo)記注解

//有點(diǎn)像定義一個(gè)接口一樣,只不過(guò)它多了一個(gè)@
public @interface MyAnnotation {
    
}
4.2元數(shù)據(jù)Annotation

我們自定義的注解是可以帶成員變量的,定義帶成員變量的注解叫做元數(shù)據(jù)Annotation

在注解中定義成員變量,語(yǔ)法類(lèi)似于聲明方法一樣....

public @interface MyAnnotation {

    //定義了兩個(gè)成員變量
    String username();
    int age();
}

注意:在注解上定義的成員變量只能是String、數(shù)組、Class、枚舉類(lèi)、注解

有的人可能會(huì)奇怪,為什么注解上還要定義注解成員變量??聽(tīng)起來(lái)就很復(fù)雜了....

上邊已經(jīng)說(shuō)了,注解的作用就是給類(lèi)、方法注入信息。那么我們經(jīng)常使用XML文件,告訴程序怎么運(yùn)行。XML經(jīng)常會(huì)有嵌套的情況

<書(shū)>
    <作者>zhongfucheng
    <價(jià)錢(qián)>22222


那么,當(dāng)我們?cè)谑褂米⒔獾臅r(shí)候,也可能需要有嵌套的時(shí)候,所以就允許了注解上可以定義成員變量為注解。

4.3使用自定義注解

上面我們已經(jīng)定義了一個(gè)注解了,下面我們來(lái)使用它吧

4.3.1常規(guī)使用

下面我有一個(gè)add的方法,需要username和age參數(shù),我們通過(guò)注解來(lái)讓該方法擁有這兩個(gè)變量!

    //注解擁有什么屬性,在修飾的時(shí)候就要給出相對(duì)應(yīng)的值
    @MyAnnotation(username = "zhongfucheng", age = 20)
    public void add(String username, int age) {

    }
4.3.2默認(rèn)值

當(dāng)然啦,我們可以在注解聲明屬性的時(shí)候,給出默認(rèn)值。那么在修飾的時(shí)候,就可以不用具體指定了。

public @interface MyAnnotation {

    //定義了兩個(gè)成員變量
    String username() default "zicheng";
    int age() default 23;
}

在修飾的時(shí)候就不需要給出具體的值了

    @MyAnnotation()
    public void add(String username, int age) {

    }
4.3.3注解屬性為value

還有一種特殊的情況,如果注解上只有一個(gè)屬性,并且屬性的名稱(chēng)為value,那么在使用的時(shí)候,我們可以不寫(xiě)value,直接賦值給它就行

public @interface MyAnnotation2 {

    String value();
}

使用注解,可以不指定value,直接賦值

    @MyAnnotation2("zhongfucheng")
    public void find(String id) {
        
    }
4.4把自定義注解的基本信息注入到方法上

上面我們已經(jīng)使用到了注解,但是目前為止注解上的信息和方法上的信息是沒(méi)有任何關(guān)聯(lián)的。

我們使用Servlet注解的時(shí)候,僅僅調(diào)用注解,那么注解的就生效了。這是Web容器把內(nèi)部實(shí)現(xiàn)了。我們自己寫(xiě)的自定義注解是需要我們自己來(lái)處理的

那現(xiàn)在問(wèn)題來(lái)了,我們?cè)趺窗炎⒔馍系男畔⒆⑷氲椒椒ㄉ夏????我?strong>利用的是反射技術(shù)

步驟可分為三部:

反射出該類(lèi)的方法

通過(guò)方法得到注解上具體的信息

將注解上的信息注入到方法上

        //反射出該類(lèi)的方法
        Class aClass = Demo2.class;
        Method method = aClass.getMethod("add", String.class, int.class);

        //通過(guò)該方法得到注解上的具體信息
        MyAnnotation annotation = method.getAnnotation(MyAnnotation.class);
        String username = annotation.username();
        int age = annotation.age();

        //將注解上的信息注入到方法上
        Object o = aClass.newInstance();
        method.invoke(o, username, age);

當(dāng)我們執(zhí)行的時(shí)候,我們發(fā)現(xiàn)會(huì)出現(xiàn)異常...

此時(shí),我們需要在自定義注解上加入這樣一句代碼(下面就會(huì)講到,為什么要加入這句代碼)

    @Retention(RetentionPolicy.RUNTIME)

再次執(zhí)行的時(shí)候,我們就會(huì)發(fā)現(xiàn),可以通過(guò)注解來(lái)把信息注入到方法中了。

五、JDK的元Annotation

前面我們已經(jīng)介紹了java.lang包下的幾個(gè)基本Annotation了。在JDK中除了java.lang包下有Annotation,在java.lang.annotation下也有幾個(gè)常用的元Annotation。

在annotation包下的好幾個(gè)元Annotation都是用于修飾其他的Annotation定義。

5.1@Retention

上面在將注解信息注入到方法中的時(shí)候,我們最后加上了@Retention的注解....不然就會(huì)報(bào)錯(cuò)了..那它是干什么用的呢?

@Retention只能用于修飾其他的Annotation,用于指定被修飾的Annotation被保留多長(zhǎng)時(shí)間。

@Retention 包含了一個(gè)RetentionPolicy類(lèi)型的value變量,所以在使用它的時(shí)候,必須要為value成員變量賦值

value變量的值只有三個(gè):

public enum RetentionPolicy {
    /**
     * Annotations are to be discarded by the compiler.
     */
    SOURCE,

    /**
     * Annotations are to be recorded in the class file by the compiler
     * but need not be retained by the VM at run time.  This is the default
     * behavior.
     */
    CLASS,

    /**
     * Annotations are to be recorded in the class file by the compiler and
     * retained by the VM at run time, so they may be read reflectively.
     *
     * @see java.lang.reflect.AnnotatedElement
     */
    RUNTIME
}

java文件有三個(gè)時(shí)期:編譯,class,運(yùn)行。@Retention默認(rèn)是class

前面我們是使用反射來(lái)得到注解上的信息的,因?yàn)锧Retention默認(rèn)是class,而反射是在運(yùn)行時(shí)期來(lái)獲取信息的。因此就獲取不到Annotation的信息了。于是,就得在自定義注解上修改它的RetentionPolicy值

5.2@Target

@Target也是只能用于修飾另外的Annotation,它用于指定被修飾的Annotation用于修飾哪些程序單元

@Target是只有一個(gè)value成員變量的,該成員變量的值是以下的:

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

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

    /** Method declaration */
    METHOD,

    /** Parameter declaration */
    PARAMETER,

    /** Constructor declaration */
    CONSTRUCTOR,

    /** Local variable declaration */
    LOCAL_VARIABLE,

    /** Annotation type declaration */
    ANNOTATION_TYPE,

    /** Package declaration */
    PACKAGE
}

如果@Target指定的是ElementType.ANNOTATION_TYPE,那么該被修飾的Annotation只能修飾Annotaion

5.3@Documented

@Documented用于指定被該Annotation修飾的Annotation類(lèi)將被javadoc工具提取成文檔。

該元Annotation用得挺少的....

5.4@Inherited

@Inherited也是用來(lái)修飾其他的Annotation的,被修飾過(guò)的Annotation將具有繼承性。。。

例子:

@xxx是我自定義的注解,我現(xiàn)在使用@xxx注解在Base類(lèi)上使用....

使用@Inherited修飾@xxx注解

當(dāng)有類(lèi)繼承了Base類(lèi)的時(shí)候,該實(shí)現(xiàn)類(lèi)自動(dòng)擁有@xxx注解

六、注入對(duì)象到方法或成員變量上 6.1把對(duì)象注入到方法上

前面我們已經(jīng)可以使用注解將基本的信息注入到方法上了,現(xiàn)在我們要使用的是將對(duì)象注入到方法上.....

上邊已經(jīng)說(shuō)過(guò)了,注解上只能定義String、枚舉類(lèi)、Double之類(lèi)的成員變量,那怎么把對(duì)象注入到方法上呢?

6.1.2模擬場(chǎng)景:

Person類(lèi),定義username和age屬性,擁有uername和age的getter和setter方法

public class Person {
    
    private String username;
    private int age;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

PersonDao類(lèi),PersonDao類(lèi)定義了Person對(duì)象,擁有person的setter和getter方法

public class PersonDao {
    
    private Person person;

    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }
}

現(xiàn)在我要做的就是:使用注解將Person對(duì)象注入到setPerson()方法中,從而設(shè)置了PersonDao類(lèi)的person屬性

public class PersonDao {

    private Person person;

    public Person getPerson() {
        return person;
    }


    //將username為zhongfucheng,age為20的Person對(duì)象注入到setPerson方法中
    @InjectPerson(username = "zhongfucheng",age = 20)
    public void setPerson(Person person) {
        
        this.person = person;
    }
}

步驟:

①: 自定義一個(gè)注解,屬性是和JavaBean類(lèi)一致的

//注入工具是通過(guò)反射來(lái)得到注解的信息的,于是保留域必須使用RunTime
@Retention(RetentionPolicy.RUNTIME)
public @interface InjectPerson {

    String username();
    int age();
}

②:編寫(xiě)注入工具

        //1.使用內(nèi)省【后邊需要得到屬性的寫(xiě)方法】,得到想要注入的屬性
        PropertyDescriptor descriptor = new PropertyDescriptor("person", PersonDao.class);

        //2.得到要想注入屬性的具體對(duì)象
        Person person = (Person) descriptor.getPropertyType().newInstance();

        //3.得到該屬性的寫(xiě)方法【setPerson()】
        Method method = descriptor.getWriteMethod();

        //4.得到寫(xiě)方法的注解
        Annotation annotation = method.getAnnotation(InjectPerson.class);

        //5.得到注解上的信息【注解的成員變量就是用方法來(lái)定義的】
        Method[] methods = annotation.getClass().getMethods();

        //6.將注解上的信息填充到person對(duì)象上

        for (Method m : methods) {

            //得到注解上屬性的名字【age或name】
            String name = m.getName();

            //看看Person對(duì)象有沒(méi)有與之對(duì)應(yīng)的方法【setAge(),setName()】
            try {

                //6.1這里假設(shè):有與之對(duì)應(yīng)的寫(xiě)方法,得到寫(xiě)方法
                PropertyDescriptor descriptor1 = new PropertyDescriptor(name, Person.class);
                Method method1 = descriptor1.getWriteMethod();//setAge(), setName()

                //得到注解中的值
                Object o = m.invoke(annotation, null);

                //調(diào)用Person對(duì)象的setter方法,將注解上的值設(shè)置進(jìn)去
                method1.invoke(person, o);

            } catch (Exception e) {

                //6.2 Person對(duì)象沒(méi)有與之對(duì)應(yīng)的方法,會(huì)跳到catch來(lái)。我們要讓它繼續(xù)遍歷注解就好了
                continue;
            }
        }
        
        //當(dāng)程序遍歷完之后,person對(duì)象已經(jīng)填充完數(shù)據(jù)了

        //7.將person對(duì)象賦給PersonDao【通過(guò)寫(xiě)方法】
        PersonDao personDao = new PersonDao();
        method.invoke(personDao, person);

        System.out.println(personDao.getPerson().getUsername());
        System.out.println(personDao.getPerson().getAge());

③:總結(jié)一下步驟

其實(shí)我們是這樣把對(duì)象注入到方法中的:

得到想要類(lèi)中注入的屬性

得到該屬性的對(duì)象

得到屬性對(duì)應(yīng)的寫(xiě)方法

通過(guò)寫(xiě)方法得到注解

獲取注解詳細(xì)的信息

將注解的信息注入到對(duì)象上

調(diào)用屬性寫(xiě)方法,將已填充數(shù)據(jù)的對(duì)象注入到方法中

6.2把對(duì)象注入到成員變量

上面已經(jīng)說(shuō)了如何將對(duì)象注入到方法上了,那么注入到成員變量上也是非常簡(jiǎn)單的。

步驟:

①:在成員變量上使用注解

public class PersonDao {

    @InjectPerson(username = "zhongfucheng",age = 20) private Person person;

    public Person getPerson() {
        return person;
    }
    
    public void setPerson(Person person) {

        this.person = person;
    }
}

②:編寫(xiě)注入工具

        //1.得到想要注入的屬性
        Field field = PersonDao.class.getDeclaredField("person");

        //2.得到屬性的具體對(duì)象
        Person person = (Person) field.getType().newInstance();

        //3.得到屬性上的注解
        Annotation annotation = field.getAnnotation(InjectPerson.class);

        //4.得到注解的屬性【注解上的屬性使用方法來(lái)表示的】
        Method[] methods = annotation.getClass().getMethods();

        //5.將注入的屬性填充到person對(duì)象上
        for (Method method : methods) {

            //5.1得到注解屬性的名字
            String name = method.getName();

            //查看一下Person對(duì)象上有沒(méi)有與之對(duì)應(yīng)的寫(xiě)方法
            try {

                //如果有
                PropertyDescriptor descriptor = new PropertyDescriptor(name, Person.class);

                //得到Person對(duì)象上的寫(xiě)方法
                Method method1 = descriptor.getWriteMethod();

                //得到注解上的值
                Object o = method.invoke(annotation, null);

                //填充person對(duì)象
                method1.invoke(person, o);
            } catch (IntrospectionException e) {

                //如果沒(méi)有想對(duì)應(yīng)的屬性,繼續(xù)循環(huán)
                continue;
            }
        }

        //循環(huán)完之后,person就已經(jīng)填充好數(shù)據(jù)了


        //6.把person對(duì)象設(shè)置到PersonDao中
        PersonDao personDao = new PersonDao();
        field.setAccessible(true);
        field.set(personDao, person);

        System.out.println(personDao.getPerson().getUsername());
七、總結(jié)

①:注入對(duì)象的步驟:得到想要注入的對(duì)象屬性,通過(guò)屬性得到注解的信息,通過(guò)屬性的寫(xiě)方法將注解的信息注入到對(duì)象上,最后將對(duì)象賦給類(lèi)。

②:注解其實(shí)就是兩個(gè)作用:

讓編譯器檢查代碼

將數(shù)據(jù)注入到方法、成員變量、類(lèi)上

③:在JDK中注解分為了

基本Annotation

在lang包下,用于常用于標(biāo)記該方法,抑制編譯器警告等

元Annotaion

在annotaion包下,常用于修飾其他的Annotation定義

如果文章有錯(cuò)的地方歡迎指正,大家互相交流。習(xí)慣在微信看技術(shù)文章,想要獲取更多的Java資源的同學(xué),可以關(guān)注微信公眾號(hào):Java3y

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/68912.html

相關(guān)文章

  • SpringBoot自動(dòng)配置原理

    摘要:開(kāi)啟自動(dòng)配置功能后文詳解這個(gè)注解,學(xué)過(guò)的同學(xué)應(yīng)該對(duì)它不會(huì)陌生,就是掃描注解,默認(rèn)是掃描當(dāng)前類(lèi)下的。簡(jiǎn)單來(lái)說(shuō),這個(gè)注解可以幫助我們自動(dòng)載入應(yīng)用程序所需要的所有默認(rèn)配置。簡(jiǎn)單理解這二者掃描的對(duì)象是不一樣的。 前言 只有光頭才能變強(qiáng)。 文本已收錄至我的GitHub倉(cāng)庫(kù),歡迎Star:https://github.com/ZhongFuCheng3y/3y 回顧前面Spring的文章(以學(xué)習(xí)...

    Rainie 評(píng)論0 收藏0
  • Spring AOP這么簡(jiǎn)單

    摘要:是一種特殊的增強(qiáng)切面切面由切點(diǎn)和增強(qiáng)通知組成,它既包括了橫切邏輯的定義也包括了連接點(diǎn)的定義。實(shí)際上,一個(gè)的實(shí)現(xiàn)被拆分到多個(gè)類(lèi)中在中聲明切面我們知道注解很方便,但是,要想使用注解的方式使用就必須要有源碼因?yàn)槲覀円? 前言 只有光頭才能變強(qiáng) 上一篇已經(jīng)講解了Spring IOC知識(shí)點(diǎn)一網(wǎng)打盡!,這篇主要是講解Spring的AOP模塊~ 之前我已經(jīng)寫(xiě)過(guò)一篇關(guān)于AOP的文章了,那篇把比較重要的知...

    Jacendfeng 評(píng)論0 收藏0
  • SpringBoot原理深入篇

    摘要:?jiǎn)?dòng)原理和執(zhí)行原理分析一的啟動(dòng)原理我們打開(kāi),注意看下面兩個(gè)依賴(lài)我們第一步是繼承了父項(xiàng)目,然后在添加啟動(dòng)器的依賴(lài),項(xiàng)目就會(huì)自動(dòng)給我們導(dǎo)入關(guān)于項(xiàng)目所需要的配置和。 上一篇我們看到,我們很輕松的完成了項(xiàng)目的構(gòu)建,那么SpringBoot是如何做到的呢,在使用的使用又有哪些通用配置和注意事項(xiàng)呢? 其實(shí)SpringBoot給我們做了大量的自動(dòng)配置功能,我們只需要引入對(duì)應(yīng)的啟動(dòng)器就可以直接使用,作...

    gotham 評(píng)論0 收藏0
  • 從深處去掌握數(shù)據(jù)校驗(yàn)@Valid的作用(級(jí)聯(lián)校驗(yàn))

    摘要:如果說(shuō)要使用數(shù)據(jù)校驗(yàn),我十分相信小伙伴們都能夠使用,但估計(jì)大都是有個(gè)前提的環(huán)境。具體使用可參考小家讓支持對(duì)平鋪參數(shù)執(zhí)行數(shù)據(jù)校驗(yàn)?zāi)J(rèn)使用只能對(duì)進(jìn)行校驗(yàn)級(jí)聯(lián)校驗(yàn)什么叫級(jí)聯(lián)校驗(yàn),其實(shí)就是帶校驗(yàn)的成員里存在級(jí)聯(lián)對(duì)象時(shí),也要對(duì)它完成校驗(yàn)。 每篇一句 NBA里有兩大笑話:一是科比沒(méi)天賦,二是詹姆斯沒(méi)技術(shù) 相關(guān)閱讀 【小家Java】深入了解數(shù)據(jù)校驗(yàn):Java Bean Validation 2.0(...

    BlackFlagBin 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<