HOME 首頁
SERVICE 服務(wù)產(chǎn)品
XINMEITI 新媒體代運(yùn)營(yíng)
CASE 服務(wù)案例
NEWS 熱點(diǎn)資訊
ABOUT 關(guān)于我們
CONTACT 聯(lián)系我們
創(chuàng)意嶺
讓品牌有溫度、有情感
專注品牌策劃15年

    Java什么是注解

    發(fā)布時(shí)間:2023-04-03 18:15:25     稿源: 創(chuàng)意嶺    閱讀: 69        當(dāng)前文章關(guān)鍵詞排名出租

    大家好!今天讓創(chuàng)意嶺的小編來大家介紹下關(guān)于Java什么是注解的問題,以下是小編對(duì)此問題的歸納整理,讓我們一起來看看吧。

    開始之前先推薦一個(gè)非常厲害的Ai人工智能工具,一鍵生成原創(chuàng)文章、方案、文案、工作計(jì)劃、工作報(bào)告、論文、代碼、作文、做題和對(duì)話答疑等等

    只需要輸入關(guān)鍵詞,就能返回你想要的內(nèi)容,越精準(zhǔn),寫出的就越詳細(xì),有微信小程序端、在線網(wǎng)頁版、PC客戶端

    官網(wǎng):https://ai.de1919.com,如需相關(guān)業(yè)務(wù)請(qǐng)撥打電話175-8598-2043,或添加微信:1454722008

    本文目錄:

    Java什么是注解

    一、java注解開發(fā)是什么?是不是不用在xml里配置ssh?以前都是配置xml,注解讓我暈了

    注解(Annotation )就是將一些標(biāo)注的信息,寫在java文件中,實(shí)際上servlet以前在web.xml中注冊(cè)(配置mapping等等),現(xiàn)在servlet也可以采用注解的方式,將配置直接寫在servlet類之上。采用注解的好處就是:不需要單獨(dú)一個(gè)一個(gè)的在外部文件中增加配置信息了,如果采用注解方式,當(dāng)你寫完一個(gè)類(包括注解部分),那個(gè)這個(gè)類的配置也就寫完了,不需要反復(fù)于配置文件和類的編寫。采用注解的壞處是:1、讓一些配置信息寫在java代碼中,導(dǎo)致代碼比較混亂,2、有源碼還好,如果沒源代碼呢?因?yàn)樽⒔馐菍懺趈ava文件中的,所以如果給你的項(xiàng)目是通過注解實(shí)現(xiàn)的,而且給你的項(xiàng)目不是源碼,那么你是沒有辦法修改配置信息的,除非反編譯。

    對(duì)于hibernate我個(gè)人覺得采用注解的方式要比采用xml的方式好(個(gè)人認(rèn)為),即省了一大堆的mapping文件,又提高了效率,而且采用的注解是JPA提供的,可以跨ORM框架。

    Struts2而言還是要掌握xml配置方式,因?yàn)閤ml配置反而效率高,因?yàn)榭梢杂猛ㄅ浞惖?,比較靈活,有時(shí)設(shè)計(jì)的好,配一次就夠了。

    Spring要把xml和注解方式結(jié)合起來最好。對(duì)于IOC方面通過注解比較方便,而對(duì)于AOP方面,通過xml比較方便。所以學(xué)習(xí)時(shí)要有主次之分。

    二、java注解有什么用

    注解常見的作用有以下幾種:

    1.生成文檔。這是最常見的,也是java 最早提供的注解,常用的有@param @return 等;

    2.跟蹤代碼依賴性,實(shí)現(xiàn)替代配置文件功能。比較常見的是spring 2.5 開始的基于注解配置,作用就是減少配置,現(xiàn)在的框架基本都使用了這種配置來減少配置文件的數(shù)量;

    3.在編譯時(shí)進(jìn)行格式檢查。如@Override放在方法前,如果你這個(gè)方法并不是覆蓋了超類方法,則編譯時(shí)就能檢查出。

    三、JAVA程序中注釋的作用及類型分別是什么?

    對(duì)于Java注釋我們主要了解三種:

    1, // 注釋一行  

    2, /* ...... */ 注釋若干行

    3, /**……*/文檔注釋  /** ...... */ 注釋若干行,并寫入 javadoc文檔

    java圖標(biāo)通常這種注釋的多行寫法如下: /** * ......... * ......... */

    Java:

    Java什么是注解

    Java是一門面向?qū)ο缶幊陶Z言,不僅吸收了C++語言的各種優(yōu)點(diǎn),還摒棄了C++里難以理解的多繼承、指針等概念,因此Java語言具有功能強(qiáng)大和簡(jiǎn)單易用兩個(gè)特征。Java語言作為靜態(tài)面向?qū)ο缶幊陶Z言的代表,極好地實(shí)現(xiàn)了面向?qū)ο罄碚?,允許程序員以優(yōu)雅的思維方式進(jìn)行復(fù)雜的編程 。

    Java具有簡(jiǎn)單性、面向?qū)ο蟆⒎植际?、健壯性、安全性、平臺(tái)獨(dú)立與可移植性、多線程、動(dòng)態(tài)性等特點(diǎn) 。Java可以編寫桌面應(yīng)用程序、Web應(yīng)用程序、分布式系統(tǒng)和嵌入式系統(tǒng)應(yīng)用程序等。

    四、java注解的類型可以是哪些

    使用注解

    在一般的Java開發(fā)中,最常接觸到的可能就是@Override和@SupressWarnings這兩個(gè)注解了。使用@Override的時(shí)候只需要一個(gè)簡(jiǎn)單的聲明即可。這種稱為標(biāo)記注解(marker annotation ),它的出現(xiàn)就代表了某種配置語義。而其它的注解是可以有自己的配置參數(shù)的。配置參數(shù)以名值對(duì)的方式出現(xiàn)。使用 @SupressWarnings的時(shí)候需要類似@SupressWarnings({"uncheck", "unused"})這樣的語法。在括號(hào)里面的是該注解可供配置的值。由于這個(gè)注解只有一個(gè)配置參數(shù),該參數(shù)的名稱默認(rèn)為value,并且可以省略。而花括號(hào)則表示是數(shù)組類型。在JPA中的@Table注解使用類似@Table(name = "Customer", schema = "APP")這樣的語法。從這里可以看到名值對(duì)的用法。在使用注解時(shí)候的配置參數(shù)的值必須是編譯時(shí)刻的常量。

    從某種角度來說,可以把注解看成是一個(gè)XML元素,該元素可以有不同的預(yù)定義的屬性。而屬性的值是可以在聲明該元素的時(shí)候自行指定的。在代碼中使用注解,就相當(dāng)于把一部分元數(shù)據(jù)從XML文件移到了代碼本身之中,在一個(gè)地方管理和維護(hù)。

    開發(fā)注解

    在一般的開發(fā)中,只需要通過閱讀相關(guān)的API文檔來了解每個(gè)注解的配置參數(shù)的含義,并在代碼中正確使用即可。在有些情況下,可能會(huì)需要開發(fā)自己的注解。這在庫的開發(fā)中比較常見。注解的定義有點(diǎn)類似接口。下面的代碼給出了一個(gè)簡(jiǎn)單的描述代碼分工安排的注解。通過該注解可以在源代碼中記錄每個(gè)類或接口的分工和進(jìn)度情況。

    @Retention(RetentionPolicy.RUNTIME)

    @Target(ElementType.TYPE)

    public @interface Assignment {

        String assignee();

        int effort();

        double finished() default 0;

    }

    @interface用來聲明一個(gè)注解,其中的每一個(gè)方法實(shí)際上是聲明了一個(gè)配置參數(shù)。方法的名稱就是參數(shù)的名稱,返回值類型就是參數(shù)的類型。可以通過default來聲明參數(shù)的默認(rèn)值。在這里可以看到@Retention和@Target這樣的元注解,用來聲明注解本身的行為。@Retention用來聲明注解的保留策略,有CLASS、RUNTIME和SOURCE這三種,分別表示注解保存在類文件、JVM運(yùn)行時(shí)刻和源代碼中。只有當(dāng)聲明為RUNTIME的時(shí)候,才能夠在運(yùn)行時(shí)刻通過反射API來獲取到注解的信息。@Target用來聲明注解可以被添加在哪些類型的元素上,如類型、方法和域等。

    處理注解

    在程序中添加的注解,可以在編譯時(shí)刻或是運(yùn)行時(shí)刻來進(jìn)行處理。在編譯時(shí)刻處理的時(shí)候,是分成多趟來進(jìn)行的。如果在某趟處理中產(chǎn)生了新的Java源文件,那么就需要另外一趟處理來處理新生成的源文件。如此往復(fù),直到?jīng)]有新文件被生成為止。在完成處理之后,再對(duì)Java代碼進(jìn)行編譯。JDK 5中提供了apt工具用來對(duì)注解進(jìn)行處理。apt是一個(gè)命令行工具,與之配套的還有一套用來描述程序語義結(jié)構(gòu)的Mirror API。Mirror API(com.sun.mirror.*)描述的是程序在編譯時(shí)刻的靜態(tài)結(jié)構(gòu)。通過Mirror API可以獲取到被注解的Java類型元素的信息,從而提供相應(yīng)的處理邏輯。具體的處理工作交給apt工具來完成。編寫注解處理器的核心是AnnotationProcessorFactory和AnnotationProcessor兩個(gè)接口。后者表示的是注解處理器,而前者則是為某些注解類型創(chuàng)建注解處理器的工廠。

    以上面的注解Assignment為例,當(dāng)每個(gè)開發(fā)人員都在源代碼中更新進(jìn)度的話,就可以通過一個(gè)注解處理器來生成一個(gè)項(xiàng)目整體進(jìn)度的報(bào)告。 首先是注解處理器工廠的實(shí)現(xiàn)。

    public class AssignmentApf implements AnnotationProcessorFactory {  

        public AnnotationProcessor getProcessorFor(Set<AnnotationTypeDeclaration> atds,? AnnotationProcessorEnvironment env) {

            if (atds.isEmpty()) {

               return AnnotationProcessors.NO_OP;

            }

            return new AssignmentAp(env); //返回注解處理器

        } 

        public Collection<String> supportedAnnotationTypes() {

            return Collections.unmodifiableList(Arrays.asList("annotation.Assignment"));

        }

        public Collection<String> supportedOptions() {

            return Collections.emptySet();

        }

    }

    AnnotationProcessorFactory接口有三個(gè)方法:getProcessorFor是根據(jù)注解的類型來返回特定的注解處理器;supportedAnnotationTypes是返回該工廠生成的注解處理器所能支持的注解類型;supportedOptions用來表示所支持的附加選項(xiàng)。在運(yùn)行apt命令行工具的時(shí)候,可以通過-A來傳遞額外的參數(shù)給注解處理器,如-Averbose=true。當(dāng)工廠通過 supportedOptions方法聲明了所能識(shí)別的附加選項(xiàng)之后,注解處理器就可以在運(yùn)行時(shí)刻通過AnnotationProcessorEnvironment的getOptions方法獲取到選項(xiàng)的實(shí)際值。注解處理器本身的基本實(shí)現(xiàn)如下所示。

    public class AssignmentAp implements AnnotationProcessor { 

        private AnnotationProcessorEnvironment env;

        private AnnotationTypeDeclaration assignmentDeclaration;

        public AssignmentAp(AnnotationProcessorEnvironment env) {

            this.env = env;

            assignmentDeclaration = (AnnotationTypeDeclaration) env.getTypeDeclaration("annotation.Assignment");

        }

        public void process() {

            Collection<Declaration> declarations = env.getDeclarationsAnnotatedWith(assignmentDeclaration);

            for (Declaration declaration : declarations) {

               processAssignmentAnnotations(declaration);

            }

        }

        private void processAssignmentAnnotations(Declaration declaration) {

            Collection<AnnotationMirror> annotations = declaration.getAnnotationMirrors();

            for (AnnotationMirror mirror : annotations) {

                if (mirror.getAnnotationType().getDeclaration().equals(assignmentDeclaration)) {

                    Map<AnnotationTypeElementDeclaration, AnnotationValue> values = mirror.getElementValues();

                    String assignee = (String) getAnnotationValue(values, "assignee"); //獲取注解的值

                }

            }

        }   

    }

    注解處理器的處理邏輯都在process方法中完成。通過一個(gè)聲明(Declaration)的getAnnotationMirrors方法就可以獲取到該聲明上所添加的注解的實(shí)際值。得到這些值之后,處理起來就不難了。

    在創(chuàng)建好注解處理器之后,就可以通過apt命令行工具來對(duì)源代碼中的注解進(jìn)行處理。 命令的運(yùn)行格式是apt -classpath bin -factory annotation.apt.AssignmentApf src/annotation/work/*.java,即通過-factory來指定注解處理器工廠類的名稱。實(shí)際上,apt工具在完成處理之后,會(huì)自動(dòng)調(diào)用javac來編譯處理完成后的源代碼。

    JDK 5中的apt工具的不足之處在于它是Oracle提供的私有實(shí)現(xiàn)。在JDK 6中,通過JSR 269把自定義注解處理器這一功能進(jìn)行了規(guī)范化,有了新的javax.annotation.processing這個(gè)新的API。對(duì)Mirror API也進(jìn)行了更新,形成了新的javax.lang.model包。注解處理器的使用也進(jìn)行了簡(jiǎn)化,不需要再單獨(dú)運(yùn)行apt這樣的命令行工具,Java編譯器本身就可以完成對(duì)注解的處理。對(duì)于同樣的功能,如果用JSR 269的做法,只需要一個(gè)類就可以了。

    @SupportedSourceVersion(SourceVersion.RELEASE_6)

    @SupportedAnnotationTypes("annotation.Assignment")

    public class AssignmentProcess extends AbstractProcessor {

        private TypeElement assignmentElement; 

        public synchronized void init(ProcessingEnvironment processingEnv) {

            super.init(processingEnv);

            Elements elementUtils = processingEnv.getElementUtils();

            assignmentElement = elementUtils.getTypeElement("annotation.Assignment");

        } 

        public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {

            Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(assignmentElement);

            for (Element element : elements) {

                processAssignment(element);

            }

        }

        private void processAssignment(Element element) {

            List<? extends AnnotationMirror> annotations = element.getAnnotationMirrors();

            for (AnnotationMirror mirror : annotations) {

                if (mirror.getAnnotationType().asElement().equals(assignmentElement)) {

                    Map<? extends ExecutableElement, ? extends AnnotationValue> values = mirror.getElementValues();

                    String assignee = (String) getAnnotationValue(values, "assignee"); //獲取注解的值

                }

            }

        } 

    }

    仔細(xì)比較上面兩段代碼,可以發(fā)現(xiàn)它們的基本結(jié)構(gòu)是類似的。不同之處在于JDK 6中通過元注解@SupportedAnnotationTypes來聲明所支持的注解類型。另外描述程序靜態(tài)結(jié)構(gòu)的javax.lang.model包使用了不同的類型名稱。使用的時(shí)候也更加簡(jiǎn)單,只需要通過javac -processor annotation.pap.AssignmentProcess Demo1.java這樣的方式即可。

    上面介紹的這兩種做法都是在編譯時(shí)刻進(jìn)行處理的。而有些時(shí)候則需要在運(yùn)行時(shí)刻來完成對(duì)注解的處理。這個(gè)時(shí)候就需要用到Java的反射API。反射API提供了在運(yùn)行時(shí)刻讀取注解信息的支持。不過前提是注解的保留策略聲明的是運(yùn)行時(shí)。Java反射API的AnnotatedElement接口提供了獲取類、方法和域上的注解的實(shí)用方法。比如獲取到一個(gè)Class類對(duì)象之后,通過getAnnotation方法就可以獲取到該類上添加的指定注解類型的注解。

    實(shí)例分析

    下面通過一個(gè)具體的實(shí)例來分析說明在實(shí)踐中如何來使用和處理注解。假定有一個(gè)公司的雇員信息系統(tǒng),從訪問控制的角度出發(fā),對(duì)雇員的工資的更新只能由具有特定角色的用戶才能完成。考慮到訪問控制需求的普遍性,可以定義一個(gè)注解來讓開發(fā)人員方便的在代碼中聲明訪問控制權(quán)限。

    @Retention(RetentionPolicy.RUNTIME)

    @Target(ElementType.METHOD)

    public @interface RequiredRoles {

        String[] value();

    }

    下一步則是如何對(duì)注解進(jìn)行處理,這里使用的Java的反射API并結(jié)合動(dòng)態(tài)代理。下面是動(dòng)態(tài)代理中的InvocationHandler接口的實(shí)現(xiàn)。

    public class AccessInvocationHandler<T> implements InvocationHandler {

        final T accessObj;

        public AccessInvocationHandler(T accessObj) {

            this.accessObj = accessObj;

        }

        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

            RequiredRoles annotation = method.getAnnotation(RequiredRoles.class); //通過反射API獲取注解

            if (annotation != null) {

                String[] roles = annotation.value();

                String role = AccessControl.getCurrentRole();

                if (!Arrays.asList(roles).contains(role)) {

                    throw new AccessControlException("The user is not allowed to invoke this method.");

                }

            }

            return method.invoke(accessObj, args);

        } 

    }

    在具體使用的時(shí)候,首先要通過Proxy.newProxyInstance方法創(chuàng)建一個(gè)EmployeeGateway的接口的代理類,使用該代理類來完成實(shí)際的操作。

    以上就是關(guān)于Java什么是注解相關(guān)問題的回答。希望能幫到你,如有更多相關(guān)問題,您也可以聯(lián)系我們的客服進(jìn)行咨詢,客服也會(huì)為您講解更多精彩的知識(shí)和內(nèi)容。


    推薦閱讀:

    基于javaweb的圖書管理系統(tǒng)(基于javaweb的圖書管理系統(tǒng)論文)

    java可變參數(shù)是什么(java可變參數(shù)怎么用)

    杭州Java研發(fā)崗位薪資范圍(杭州java研發(fā)崗位薪資范圍是多少)

    海外視頻APP(海外視頻素材網(wǎng)站)

    競(jìng)價(jià)投放策略(競(jìng)價(jià)投放策略有哪些)