亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專(zhuān)欄INFORMATION COLUMN

Java 注解實(shí)戰(zhàn)

Jochen / 1918人閱讀

摘要:注解是的一個(gè)新特性。很重要,生產(chǎn)中我們開(kāi)發(fā)常用此值表示注解是否可被子元素繼承。類(lèi)注解方法注解通過(guò)反射獲取方法對(duì)象此部分內(nèi)容可參考通過(guò)反射獲取注解信息注解處理器實(shí)戰(zhàn)接下來(lái)我通過(guò)在公司中的一個(gè)實(shí)戰(zhàn)改編來(lái)演示一下注解處理器的真實(shí)使用場(chǎng)景。

前言:Java 注解,對(duì)于很多人都不陌生了,但是在公司的實(shí)際開(kāi)發(fā)中,可能讓我們自己去定義注解并應(yīng)用到生產(chǎn)環(huán)境中的機(jī)會(huì)比較少,所以會(huì)導(dǎo)致一部分人對(duì)注解的理解比較淺,在看到一些框架或者別人的代碼中有注解的代碼就會(huì)頭大,不知道這代表的是什么意思。其實(shí)究其原因,最主要的還是我們對(duì)注解的這個(gè)概念沒(méi)搞清楚,所以本文通篇會(huì)串插著這些重要的概念,從幾個(gè)主題入手,從淺到深的帶領(lǐng)大家進(jìn)入注解的世界,讓大家在今后的代碼旅程中輕松應(yīng)對(duì)注解。

注解是 Java 5 的一個(gè)新特性。先給大家梳理一個(gè)在生產(chǎn)環(huán)境中注解的常用使用流程。第一步: 定義一個(gè)注解;第二步: 在類(lèi)上面或方法上面等地方使用注解;第三步: 通過(guò)注解處理器獲取注解信息并做相應(yīng)的處理(這個(gè)處理也就是注解真正起作用的地方了)。本篇文章的整個(gè)脈絡(luò)大致也是按照這三步來(lái)寫(xiě)的。

JDK 內(nèi)置注解

先來(lái)看幾個(gè) Java 內(nèi)置的注解,讓大家熱熱身。

@Override 演示

class Parent {
    public void run() {
    }
}

class Son extends Parent {
    /**
     * 這個(gè)注解是為了檢查此方法是否真的是重寫(xiě)父類(lèi)的方法
     * 這時(shí)候就不用我們用肉眼去觀察到底是不是重寫(xiě)了
     */
    @Override
    public void run() {
    }
}

@Deprecated 演示

class Parent {

    /**
     * 此注解代表過(guò)時(shí)了,但是如果可以調(diào)用到,當(dāng)然也可以正常使用
     * 但是,此方法有可能在以后的版本升級(jí)中會(huì)被慢慢的淘汰
     * 可以放在類(lèi),變量,方法上面都起作用
     */
    @Deprecated
    public void run() {
    }
}

public class JDKAnnotationDemo {
    public static void main(String[] args) {
        Parent parent = new Parent();
        parent.run(); // 在編譯器中此方法會(huì)顯示過(guò)時(shí)標(biāo)志
    }
}

@SuppressWarnings 演示

class Parent {

    // 因?yàn)槎x的 name 沒(méi)有使用,那么編譯器就會(huì)有警告,這時(shí)候使用此注解可以屏蔽掉警告
    // 即任意不想看到的編譯時(shí)期的警告都可以用此注解屏蔽掉,但是不推薦,有警告的代碼最好還是處理一下
    @SuppressWarnings("all")
    private String name;
}

@FunctionalInterface 演示

/**
 * 此注解是 Java8 提出的函數(shù)式接口,接口中只允許有一個(gè)抽象方法
 * 加上這個(gè)注解之后,類(lèi)中多一個(gè)抽象方法或者少一個(gè)抽象方法都會(huì)報(bào)錯(cuò)
 */
@FunctionalInterface
interface Func {
    void run();
}
定義一個(gè)注解 完整注解

這里先提供一個(gè)比較完整的注解,即此注解內(nèi)容基本包含了我們?cè)谏a(chǎn)環(huán)境中常用的信息了,然后根據(jù)這個(gè)注解來(lái)介紹枚舉的重要概念。首先看到下面這個(gè)完整注解包含三部分內(nèi)容,第一部分就是 @interface 來(lái)定義注解,所有注解隱式繼承 java.lang.annotation.Annotation;第二部分就是這個(gè)注解的內(nèi)部信息;第三部分就是這個(gè)注解的頭部,即元注解。

@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER, ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.RUNTIME)
@Inherited // 此注解應(yīng)用的相對(duì)較少,本文不多做介紹,可自行研究
@Documented // 此注解應(yīng)用的相對(duì)較少,本文不多做介紹,可自行研究
public @interface ApiAuthAnnotation {
    int age();

    String name() default "lyf";

    AnnotationDemo annotattion() default @AnnotationDemo;

    Season Sason() default Season.SPRING;

    int[] nums() default {1, 2, 3};

    Class clazz() default String.class;
}
注解內(nèi)部信息

所謂注解內(nèi)部信息,也就是這個(gè)注解里面都寫(xiě)什么,通過(guò)如上的完整注解可以很直觀的看到都寫(xiě)了什么,其實(shí)就是一種比較特殊的方法了,帶有返回值類(lèi)型,沒(méi)有具體實(shí)現(xiàn),后面可以選填默認(rèn)值。大概也就這么點(diǎn)內(nèi)容了。其支持的數(shù)據(jù)類(lèi)型有:

基本數(shù)據(jù)類(lèi)型

java.lang.String

注解

枚舉

一維數(shù)組

java.lang.Class

元注解

元注解是指用于注解類(lèi)型上的注解。通俗來(lái)講,元注解的作用就是,規(guī)范我們定義的注解,給這個(gè)注解一些規(guī)則。比如說(shuō): 我在注解頭部沒(méi)有寫(xiě)元注解,那么我們自定義的這個(gè)注解在使用的時(shí)候放在類(lèi)上面,方法上面,或者放在成員變量上面,沒(méi)有規(guī)則,想放哪里就放哪里;但是當(dāng)我們?cè)谧⒔忸^部寫(xiě)了元注解,并把元注解的 Target 設(shè)置為 ElementType.METHOD,那么我們自定義的這個(gè)注解在使用的時(shí)候就只能放在方法上面,放在類(lèi)上面或者成員變量上面就會(huì)報(bào)錯(cuò)。

元注解的注解類(lèi)型主要有如下幾種:

@Target: 表示定義的注解的作用域,其值包括:

CONSTRUCTOR: 構(gòu)造方法聲明;

FIELD: 屬性/字段聲明;

LOCAL_VARIABLE: 局部變量聲明;

METHOD: 方法聲明;

PACKAGE: 包聲明;

PARAMETER: 參數(shù)聲明;

TYPE: 類(lèi)接口聲明;

ANNOTATION_TYPE: 注解類(lèi)型聲明;

TYPE_PARAMETER: 類(lèi)型參數(shù)聲明(jdk1.8 提供);

TYPE_USE: 類(lèi)型使用(jdk1.8 提供)

@Retention: 自定義注解的生命周期,其值包括:

SOURCE: 只在源碼顯示,編譯時(shí)丟棄;(比如 jdk 自帶的 @SuppressWarnings 和 @Override)

CLASS: 編譯時(shí)記錄到.class中,運(yùn)行時(shí)忽略;

RUNTIME: 運(yùn)行時(shí)存在,可通過(guò)反射來(lái)讀取。(很重要,生產(chǎn)中我們開(kāi)發(fā)常用此值)

@Inherited: 表示注解是否可被子元素繼承。

@Documented: 表示 javadoc 是否為實(shí)例產(chǎn)生文檔

注意事項(xiàng)

注解不能繼承另一個(gè)注解

方法不能有參數(shù)

方法不能拋出異常

不能定義 Object 或 Annotation 接口中的方法(因?yàn)樽⒔舛茧[式繼承 Annotation 接口)

注解不能是泛型

使用 default 指定屬性的默認(rèn)值

不能使用 null 作為屬性的默認(rèn)值

使用注解

這個(gè)當(dāng)然就相當(dāng)簡(jiǎn)單了,哪個(gè)地方需要使用我們自定義的注解,那我們?cè)谄涞胤教砑由献⒔饩?ok 了。如下代碼: 如果要作用到類(lèi),那就在類(lèi)頭上加上注解;如果要作用到方法,那就在方法上加上注解。

@ApiAuthAnnotation(age = 16, name = "lyf")
@RestController
public class ApiController {

    @ApiAuthAnnotation(age = 20, name = "lisi")
    @RequestMapping(value = "/topic1", method = RequestMethod.GET)
    public void getByTopic1() {
        System.out.println("年齡大于 18 歲的可以訪(fǎng)問(wèn)此 API");
    }

    @ApiAuthAnnotation(age = 16, name = "zhangsan")
    @RequestMapping(value = "/topic2", method = RequestMethod.GET)
    public void getByTopic2() {
        System.out.println("年齡小于 18 歲的不可以訪(fǎng)問(wèn)此 API");
    }

}

從如上代碼來(lái)看,使用注解的時(shí)候則是相當(dāng)?shù)暮?jiǎn)單了,我們這里是在類(lèi)上和方法上都加上了自定義的注解了,至于這些注解加上以后怎么起作用,那就跟注解處理器有關(guān)了。
【注: 在使用注解的時(shí)候其實(shí)還有很多小的語(yǔ)法技巧,很多時(shí)候可以簡(jiǎn)寫(xiě)一些代碼,不過(guò)有沒(méi)有必要簡(jiǎn)寫(xiě)代碼,這個(gè)自己去衡量,這個(gè)不是重點(diǎn),就是語(yǔ)法,可以自行去研究下。就比如當(dāng)注解只要一個(gè)元素,且其名字是 value 時(shí),賦值的時(shí)候可以簡(jiǎn)寫(xiě)】

注解處理器

注解處理器才是使用注解整個(gè)流程中最重要的一步了。所有在代碼中出現(xiàn)的注解,它到底起了什么作用,都是在注解處理器中定義好的。
概念:注解本身并不會(huì)對(duì)程序的編譯方式產(chǎn)生影響,而是注解處理器起的作用;注解處理器能夠通過(guò)在運(yùn)行時(shí)使用反射獲取在程序代碼中的使用的注解信息,從而實(shí)現(xiàn)一些額外功能。前提是我們自定義的注解使用的是 RetentionPolicy.RUNTIME 修飾的。這也是我們?cè)陂_(kāi)發(fā)中使用頻率很高的一種方式。

我們先來(lái)了解下如何通過(guò)在運(yùn)行時(shí)使用反射獲取在程序中的使用的注解信息。如下類(lèi)注解和方法注解。

類(lèi)注解
Class aClass = ApiController.class;
Annotation[] annotations = aClass.getAnnotations();

for(Annotation annotation : annotations) {
    if(annotation instanceof ApiAuthAnnotation) {
        ApiAuthAnnotation apiAuthAnnotation = (ApiAuthAnnotation) annotation;
        System.out.println("name: " + apiAuthAnnotation.name());
        System.out.println("age: " + apiAuthAnnotation.age());
    }
}
方法注解
Method method = ... //通過(guò)反射獲取方法對(duì)象
Annotation[] annotations = method.getDeclaredAnnotations();

for(Annotation annotation : annotations) {
    if(annotation instanceof ApiAuthAnnotation) {
        ApiAuthAnnotation apiAuthAnnotation = (ApiAuthAnnotation) annotation;
        System.out.println("name: " + apiAuthAnnotation.name());
        System.out.println("age: " + apiAuthAnnotation.age());
    }
}   

此部分內(nèi)容可參考: 通過(guò)反射獲取注解信息

注解處理器實(shí)戰(zhàn)

接下來(lái)我通過(guò)在公司中的一個(gè)實(shí)戰(zhàn)改編來(lái)演示一下注解處理器的真實(shí)使用場(chǎng)景。
需求: 網(wǎng)站后臺(tái)接口只能是年齡大于 18 歲的才能訪(fǎng)問(wèn),否則不能訪(fǎng)問(wèn)
前置準(zhǔn)備: 定義注解(這里使用上文的完整注解),使用注解(這里使用上文中使用注解的例子)
接下來(lái)要做的事情: 寫(xiě)一個(gè)切面,攔截瀏覽器訪(fǎng)問(wèn)帶注解的接口,取出注解信息,判斷年齡來(lái)確定是否可以繼續(xù)訪(fǎng)問(wèn)。

在 dispatcher-servlet.xml 文件中定義 aop 切面


    
    
    
    
        
    

切面類(lèi)處理邏輯即注解處理器代碼如

@Component("apiAuthAspect")
public class ApiAuthAspect {

    public Object auth(ProceedingJoinPoint pjp) throws Throwable {
        Method method = ((MethodSignature) pjp.getSignature()).getMethod();
        ApiAuthAnnotation apiAuthAnnotation = method.getAnnotation(ApiAuthAnnotation.class);
        Integer age = apiAuthAnnotation.age();
        if (age > 18) {
            return pjp.proceed();
        } else {
            throw new RuntimeException("你未滿(mǎn)18歲,禁止訪(fǎng)問(wèn)");
        }
    }
}
總結(jié)

注解其實(shí)在我們的代碼中用的也越來(lái)越多了,特別是框架里面都會(huì)提供很多的注解,把注解的概念搞清楚之后,對(duì)于以后看別人的代碼和框架源碼都很多幫助,所以平時(shí)沒(méi)事也可以多了解了解。比如我們經(jīng)常使用的 @Autowired 注解,其背后做了什么事情,有興趣都可以去了解一下。再比如,權(quán)限框架 Shiro,里面也提供很多注解來(lái)管理權(quán)限,他們是怎么使用注解和處理注解的,都可以去研究下。有什么問(wèn)題,歡迎老鐵們一起交流。。。

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

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

相關(guān)文章

  • Spring Boot 最核心的 3 個(gè)注解詳解

    摘要:核心注解講解最大的特點(diǎn)是無(wú)需配置文件,能自動(dòng)掃描包路徑裝載并注入對(duì)象,并能做到根據(jù)下的包自動(dòng)配置。所以最核心的個(gè)注解就是這是添加的一個(gè)注解,用來(lái)代替配置文件,所有這個(gè)配置文件里面能做到的事情都可以通過(guò)這個(gè)注解所在類(lèi)來(lái)進(jìn)行注冊(cè)。 最近面試一些 Java 開(kāi)發(fā)者,他們其中有些在公司實(shí)際用過(guò) Spring Boot, 有些是自己興趣愛(ài)好在業(yè)余自己學(xué)習(xí)過(guò)。然而,當(dāng)我問(wèn)他們 Spring Boo...

    hzx 評(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
  • 第12章 元編程與注解、反射 《Kotlin 項(xiàng)目實(shí)戰(zhàn)開(kāi)發(fā)》

    摘要:第章元編程與注解反射反射是在運(yùn)行時(shí)獲取類(lèi)的函數(shù)方法屬性父類(lèi)接口注解元數(shù)據(jù)泛型信息等類(lèi)的內(nèi)部信息的機(jī)制。本章介紹中的注解與反射編程的相關(guān)內(nèi)容。元編程本質(zhì)上是一種對(duì)源代碼本身進(jìn)行高層次抽象的編碼技術(shù)。反射是促進(jìn)元編程的一種很有價(jià)值的語(yǔ)言特性。 第12章 元編程與注解、反射 反射(Reflection)是在運(yùn)行時(shí)獲取類(lèi)的函數(shù)(方法)、屬性、父類(lèi)、接口、注解元數(shù)據(jù)、泛型信息等類(lèi)的內(nèi)部信息的機(jī)...

    joyqi 評(píng)論0 收藏0
  • SpringBoot 實(shí)戰(zhàn) (十五) | 服務(wù)端參數(shù)校驗(yàn)之一

    摘要:前言估計(jì)很多朋友都認(rèn)為參數(shù)校驗(yàn)是客戶(hù)端的職責(zé),不關(guān)服務(wù)端的事。輕則導(dǎo)致服務(wù)器宕機(jī),重則泄露數(shù)據(jù)。所以,這時(shí)就需要設(shè)置第二道關(guān)卡,服務(wù)端驗(yàn)證了。老項(xiàng)目的服務(wù)端校驗(yàn)不能為空不能為空看以上代碼,就一個(gè)的校驗(yàn)就如此麻煩。 前言 估計(jì)很多朋友都認(rèn)為參數(shù)校驗(yàn)是客戶(hù)端的職責(zé),不關(guān)服務(wù)端的事。其實(shí)這是錯(cuò)誤的,學(xué)過(guò) Web 安全的都知道,客戶(hù)端的驗(yàn)證只是第一道關(guān)卡。它的參數(shù)驗(yàn)證并不是安全的,一旦被有心人...

    QiShare 評(píng)論0 收藏0
  • SpringBoot 實(shí)戰(zhàn) (十) | 聲明式事務(wù)

    摘要:前言如題,今天介紹的聲明式事務(wù)。提供一個(gè)注解在配置類(lèi)上來(lái)開(kāi)啟聲明式事務(wù)的支持。而在配置里還開(kāi)啟了對(duì)聲明式事務(wù)的支持,代碼如下所以在中,無(wú)須顯式開(kāi)啟使用注解。源碼下載后語(yǔ)以上為聲明式事務(wù)的教程。 微信公眾號(hào):一個(gè)優(yōu)秀的廢人如有問(wèn)題或建議,請(qǐng)后臺(tái)留言,我會(huì)盡力解決你的問(wèn)題。 前言 如題,今天介紹 SpringBoot 的 聲明式事務(wù)。 Spring 的事務(wù)機(jī)制 所有的數(shù)據(jù)訪(fǎng)問(wèn)技術(shù)都有事務(wù)處...

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

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

0條評(píng)論

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