中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

java自定義注解的使用

發布時間:2020-07-19 20:56:09 來源:網絡 閱讀:751 作者:專注地一哥 欄目:編程語言

一、定義Java文件叫做Annotation,用@interface表示。
br/>Java文件叫做Annotation,用@interface表示。
二、元注解
@Retention 從源代碼中可以看出,主要用于提示注解要保留多長時間
package java.lang.annotation;
/**

  • Indicates how long annotations with the annotated type are to
  • be retained. If no Retention annotation is present on
  • an annotation type declaration, the retention policy defaults to
  • {@code RetentionPolicy.CLASS}.
  • <p>A Retention meta-annotation has effect only if the
  • meta-annotated type is used directly for annotation. It has no
  • effect if the meta-annotated type is used as a member type in
  • another annotation type.
  • @author Joshua Bloch
  • @since 1.5
  • @jls 9.6.3.2 @Retention*/
    @Documented
    br/>*/
    @Documented
    br/>@Target(ElementType.ANNOTATION_TYPE)
    /**
    • Returns the retention policy.
    • @return the retention policy
      */
      RetentionPolicy value();
      }
      有三種取值:
      RetentionPolicy.SOURCE 將會被編譯器拋棄
      RetentionPolicy.CLASS 注解會被編輯器保留在類文件中,但是會被vm拋棄
      RetentionPolicy.RUNTIME 注解會被編輯器保留在類文件中,也會被vm保留,所以可以通過反射讀取。
      package java.lang.annotation;
      /**
  • Annotation retention policy. The constants of this enumerated type
  • describe the various policies for retaining annotations. They are used
  • in conjunction with the {@link Retention} meta-annotation type to specify
  • how long annotations are to be retained.
  • @author Joshua Bloch
  • @since 1.5
    */
    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
      }
      @Target 用于提示該注解使用的地方@Documented
      br/>@Documented
      br/>@Target(ElementType.ANNOTATION_TYPE)
      /**
    • Returns an array of the kinds of elements an annotation type
    • can be applied to.
    • @return an array of the kinds of elements an annotation type
    • can be applied to
      */
      ElementType[] value();
      }
      其中ElementType的取值有下面十種:
      ElementType.TYPE 用于類,接口(包括注解)或者枚舉類型
      ElementType.FIELD 用于屬性字段包括枚舉常量
      ElementType.METHOD 用于方法級別
      ElementType.PARAMETER 用于參數聲明
      ElementType.CONSTRUCTOR 用于構造函數聲明
      ElementType.LOCAL_VARIABLE 用于局部變量聲明
      ElementType.ANNOTATION_TYPE 用于注解類型聲明
      ElementType.PACKAGE 用于包聲明
      ElementType.TYPE_PARAMETER 用于泛型聲明
      ElementType.TYPE_USE 用于任意類型聲明
      public enum ElementType {
      / 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
    • @since 1.8
      */
      TYPE_PARAMETER,
      /**
    • Use of a type
    • @since 1.8
      */
      TYPE_USE
      }
      @Documented 將注解包含在Javadoc中
      package java.lang.annotation;
      /**
  • Indicates that annotations with a type are to be documented by javadoc
  • and similar tools by default. This type should be used to annotate the
  • declarations of types whose annotations affect the use of annotated
  • elements by their clients. If a type declaration is annotated with
  • Documented, its annotations become part of the public API
  • of the annotated elements.
  • @author Joshua Bloch
  • @since 1.5*/
    @Documented
    br/>*/
    @Documented
    br/>@Target(ElementType.ANNOTATION_TYPE)
    }
    @Inherited 允許子類繼承父類
    package java.lang.annotation;
    /**
  • Indicates that an annotation type is automatically inherited. If
  • an Inherited meta-annotation is present on an annotation type
  • declaration, and the user queries the annotation type on a class
  • declaration, and the class declaration has no annotation for this type,
  • then the class's superclass will automatically be queried for the
  • annotation type. This process will be repeated until an annotation for this
  • type is found, or the top of the class hierarchy (Object)
  • is reached. If no superclass has an annotation for this type, then
  • the query will indicate that the class in question has no such annotation.
  • <p>Note that this meta-annotation type has no effect if the annotated
  • type is used to annotate anything other than a class. Note also
  • that this meta-annotation only causes annotations to be inherited
  • from superclasses; annotations on implemented interfaces have no
  • effect.
  • @author Joshua Bloch
  • @since 1.5
  • @jls 9.6.3.3 @Inherited*/
    @Documented
    br/>*/
    @Documented
    br/>@Target(ElementType.ANNOTATION_TYPE)
    }
    三、自定義注解的使用
    創建一個自定義注解
    import java.lang.annotation.*;
    /**
  • Created Date: 2019/3/1
  • 創建自定義注解
    */
    @Target({ ElementType.METHOD, ElementType.TYPE })@Retention(RetentionPolicy.RUNTIME)
    br/>@Retention(RetentionPolicy.RUNTIME)
    public @interface TestAnnotation {

    String value();
    }
    通過反射獲取注解
    public class Test {
    @TestAnnotation(value = "測試方法")
    public static void main(String args[]){
    try {
    Class c=Test.class;
    Method[] methods=c.getDeclaredMethods();
    for(Method method:methods){
    Annotation[] annotations=method.getDeclaredAnnotations();
    for(Annotation annotation:annotations){
    TestAnnotation testAnnotation= (TestAnnotation) annotation;
    System.out.println(testAnnotation.value());
    }
    }
    } catch (ClassNotFoundException e) {e.printStackTrace();
    }
    }
    }
    四、web開發中的運用
    在web開發中,權限控制非常重要,所以有些接口會限制必須登錄之后才能訪問,但是個別接口并沒有這種限制。一種方式是把需要過濾的ThinkMarkets代理申請www.kaifx.cn/broker/thinkmarkets.html接口或者方法配置在文件中,每次請求時在攔截器中根據請求的路徑與配置文件中的對比過濾。其實還有另外一種方式就是通過注解方式。
    定義一個注解NoLogin
    @Target(ElementType.METHOD)
    br/>e.printStackTrace();
    }
    }
    }
    四、web開發中的運用
    在web開發中,權限控制非常重要,所以有些接口會限制必須登錄之后才能訪問,但是個別接口并沒有這種限制。一種方式是把需要過濾的ThinkMarkets代理申請www.kaifx.cn/broker/thinkmarkets.html接口或者方法配置在文件中,每次請求時在攔截器中根據請求的路徑與配置文件中的對比過濾。其實還有另外一種方式就是通過注解方式。
    定義一個注解NoLogin
    @Target(ElementType.METHOD)
    br/>@Documented
    }
    標注在方法上
    在攔截器中判斷方法上是否有NoLogin注解
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
    //支持兩種方式過濾 1、注解方式 添加@NoLogin注解
    HandlerMethod handlerMethod= (HandlerMethod) o;
    NoLogin noLogin=handlerMethod.getMethod().getDeclaredAnnotation(NoLogin.class);
    if(null!=noLogin){
    return true;
    }
    }
    五、java內置的注解
    除了上述的四個元注解,java還內置了另外三個注解:
    @Override 它沒有任何的屬性,不能存儲任何其他信息。它只能作用于方法之上,編譯結束后將被丟棄。在java編譯器編譯成字節碼的時候,一旦發現某個方法被這個注解標識過,就會匹配父類中是否存在同一方法,如果不存在就回編譯失敗。@Target(ElementType.METHOD)
    br/>@Target(ElementType.METHOD)
    public @interface Override {
    }
    @Deprecated 棄用的注解@Documented
    br/>@Documented
    @Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
    public @interface Deprecated {
    }
    @SuppressWarnings 壓制警告,比如某段代碼中存在過時的方法,那么在編譯過程中,會有warn警告,如果不想出現類似的警告,可在方法上添加這個注解。這個注解有一個value的值,這個value表示需要壓制的警告類型。
    @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})@Retention(RetentionPolicy.SOURCE)
    br/>@Retention(RetentionPolicy.SOURCE)
    /**

    • The set of warnings that are to be suppressed by the compiler in the
    • annotated element. Duplicate names are permitted. The second and
    • successive occurrences of a name are ignored. The presence of
    • unrecognized warning names is <i>not</i> an error: Compilers must
    • ignore any warning names they do not recognize. They are, however,
    • free to emit a warning if an annotation contains an unrecognized
    • warning name.
    • <p> The string {@code "unchecked"} is used to suppress
    • unchecked warnings. Compiler vendors should document the
    • additional warning names they support in conjunction with this
    • annotation type. They are encouraged to cooperate to ensure
    • that the same names work across multiple compilers.
    • @return the set of warnings to be suppressed
      */
      String[] value();
      }
      六、注解的原理
      1、java.lang.annotation.Annotation中有這么一句話:The common interface extended by all annotation types 所有的注解都繼承于這個接口。怎么理解呢?其實剛才上面例子中的注解可以理解為:
      public @interface TestAnnotation extends Annotation{
      }
      注解的本質就是一個繼承了 Annotation 接口的接口
      為了方便理解和掌握注解,還是以剛才的TestAnnotation注解為例。在idea中配置啟動參數,方便查看代理產生的類,參數如下:
      Dsun.misc.ProxyGenerator.saveGeneratedFiles=true
      main方法運行結束后,會在/com/sun/proxy目錄下生成一個代理類,反編譯之后是這樣的:
      代理類proxy1重寫了TestAnnotation的所有方法,包括value()和從Annotation繼承來的equals()、hashCode()等方法。
      package com.sun.proxy;
      import java.lang.reflect.InvocationHandler;
      import java.lang.reflect.Method;
      import java.lang.reflect.Proxy;
      import java.lang.reflect.UndeclaredThrowableException;
      import org.fy.annotation.TestAnnotation;
      public final class $Proxy1 extends Proxy implements TestAnnotation {
      private static Method m1;
      private static Method m2;
      private static Method m4;
      private static Method m0;
      private static Method m3;
      public $Proxy1(InvocationHandler var1) throws {
      super(var1);
      }
      public final boolean equals(Object var1) throws {
      try {
      return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
      } catch (RuntimeException | Error var3) {
      throw var3;
      } catch (Throwable var4) {
      throw new UndeclaredThrowableException(var4);
      }
      }
      public final String toString() throws {
      try {
      return (String)super.h.invoke(this, m2, (Object[])null);
      } catch (RuntimeException | Error var2) {
      throw var2;
      } catch (Throwable var3) {
      throw new UndeclaredThrowableException(var3);
      }
      }
      public final Class annotationType() throws {
      try {
      return (Class)super.h.invoke(this, m4, (Object[])null);
      } catch (RuntimeException | Error var2) {
      throw var2;
      } catch (Throwable var3) {
      throw new UndeclaredThrowableException(var3);
      }
      }
      public final int hashCode() throws {
      try {
      return (Integer)super.h.invoke(this, m0, (Object[])null);
      } catch (RuntimeException | Error var2) {
      throw var2;
      } catch (Throwable var3) {
      throw new UndeclaredThrowableException(var3);
      }
      }
      public final String value() throws {
      try {
      return (String)super.h.invoke(this, m3, (Object[])null);
      } catch (RuntimeException | Error var2) {
      throw var2;
      } catch (Throwable var3) {
      throw new UndeclaredThrowableException(var3);
      }
      }
      static {
      try {
      m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
      m2 = Class.forName("java.lang.Object").getMethod("toString");
      m4 = Class.forName("org.fy.annotation.TestAnnotation").getMethod("annotationType");
      m0 = Class.forName("java.lang.Object").getMethod("hashCode");
      m3 = Class.forName("org.fy.annotation.TestAnnotation").getMethod("value");
      } catch (NoSuchMethodException var2) {
      throw new NoSuchMethodError(var2.getMessage());
      } catch (ClassNotFoundException var3) {
      throw new NoClassDefFoundError(var3.getMessage());
      }
      }
      }
      在看proxy1構造函數中有一個接口InvocationHandler,這個接口的實例化對象又是誰?
      java中有一個專門用于注解類型的代理對象AnnotationInvocationHandler,位于sun.reflect.annotation包中。同樣是invoke方法用于處理具體的業務。
      public Object invoke(Object var1, Method var2, Object[] var3) {
      String var4 = var2.getName();
      Class[] var5 = var2.getParameterTypes();
      if (var4.equals("equals") && var5.length == 1 && var5[0] == Object.class) {
      return this.equalsImpl(var3[0]);
      } else if (var5.length != 0) {
      throw new AssertionError("Too many parameters for an annotation method");
      } else {
      byte var7 = -1;
      switch(var4.hashCode()) {
      case -1776922004:
      if (var4.equals("toString")) {
      var7 = 0;
      }
      break;
      case 147696667:
      if (var4.equals("hashCode")) {
      var7 = 1;
      }
      break;
      case 1444986633:
      if (var4.equals("annotationType")) {
      var7 = 2;
      }
      }
      switch(var7) {
      case 0:
      return this.toStringImpl();
      case 1:
      return this.hashCodeImpl();
      case 2:
      return this.type;
      default:
      Object var6 = this.memberValues.get(var4);
      if (var6 == null) {
      throw new IncompleteAnnotationException(this.type, var4);
      } else if (var6 instanceof ExceptionProxy) {
      throw ((ExceptionProxy)var6).generateException();
      } else {
      if (var6.getClass().isArray() && Array.getLength(var6) != 0) {
      var6 = this.cloneArray(var6);
      }
      return var6;
      }
      }
      }
      }
向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

湟源县| 抚顺县| 临朐县| 修水县| 南华县| 西盟| 穆棱市| 济宁市| 天峻县| 桓仁| 改则县| 定西市| 宁河县| 西昌市| 河池市| 襄城县| 滦平县| 黑龙江省| 阿鲁科尔沁旗| 顺义区| 万源市| 许昌县| 嘉义县| 太和县| 云阳县| 吴江市| 旺苍县| 东乌珠穆沁旗| 太保市| 应用必备| 长海县| 全椒县| 岳阳县| 塔河县| 东港市| 海安县| 辉南县| 大石桥市| 黄山市| 鄂托克旗| 吉林市|