一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|JavaScript|易語言|

服務器之家 - 編程語言 - JAVA教程 - Java注解Annotation與自定義注解詳解

Java注解Annotation與自定義注解詳解

2021-04-13 14:46Java之家 JAVA教程

本文全面講述了Java注解Annotation與Java自定義注解及相關內容,大家可以認真看看

一:Java注解簡介

開發中經常使用到注解,在項目中也偶爾會見到過自定義注解,今天就來探討一下這個注解是什么鬼,以及注解的應用場景和如何自定義注解。

下面列舉開發中常見的注解

@Override:用于標識該方法繼承自超類, 當父類的方法被刪除或修改了,編譯器會提示錯誤信息(我們最經常看到的toString()方法上總能看到這貨)

@Deprecated:表示該類或者該方法已經不推薦使用,已經過期了,如果用戶還是要使用,會生成編譯的警告

@SuppressWarnings:用于忽略的編譯器警告信息

Junit測試:@Test

Spring的一些注解:@Controller、@RequestMapping、@RequestParam、@ResponseBody、@Service、@Component、@Repository、@Resource、@Autowire

Java驗證的注解:@NotNull、@Email

下面看一下注解Override.java的廬山真面目

?
1
2
3
4
5
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
 
}

二:Java注解基本知識

1. Java注解數據類型

注解是寫在.java文件中,使用@interface作為關鍵字, 所以注解也是Java的一種數據類型,從廣泛的定義來說,Class、Interface、Enum、Annotation都屬于Class類型。

2. Java元注解

在創建注解的時候,需要使用一些注解來描述自己創建的注解,就是寫在@interface上面的那些注解,這些注解被稱為元注解,如在Override中看到的@Target、@Retention等。下面列出一些元注解

@Documented: 用于標記在生成javadoc時是否將注解包含進去,可以看到這個注解和@Override一樣,注解中空空如也,什么東西都沒有

?
1
2
3
4
5
6
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
 
}

@Target:用于定義注解可以在什么地方使用,默認可以在任何地方使用,也可以指定使用的范圍,開發中將注解用在類上(如@Controller)、字段上(如@Autowire)、方法上(如@RequestMapping)、方法的參數上(如@RequestParam)等比較常見。

TYPE : 類、接口或enum聲明
FIELD: 域(屬性)聲明
METHOD: 方法聲明
PARAMETER: 參數聲明
CONSTRUCTOR: 構造方法聲明
LOCAL_VARIABLE:局部變量聲明
ANNOTATION_TYPE:注釋類型聲明
PACKAGE: 包聲明

Target.java

?
1
2
3
4
5
6
7
8
9
10
11
12
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
  /**
   * 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();
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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 */
  TYPE_PARAMETER,
 
  /** Use of a type */
  TYPE_USE
}

@Inherited:允許子類繼承父類中的注解,可以通過反射獲取到父類的注解

?
1
2
3
4
5
6
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
 
}

@Constraint:用于校驗屬性值是否合法

?
1
2
3
4
5
6
@Documented
@Target({ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Constraint {
  Class<? extends ConstraintValidator<?, ?>>[] validatedBy();
}

@Retention:注解的聲明周期,用于定義注解的存活階段,可以存活在源碼級別、編譯級別(字節碼級別)、運行時級別

SOURCE:源碼級別,注解只存在源碼中,一般用于和編譯器交互,用于檢測代碼。如@Override, @SuppressWarings。

CLASS:字節碼級別,注解存在于源碼和字節碼文件中,主要用于編譯時生成額外的文件,如XML,Java文件等,但運行時無法獲得。 如mybatis生成實體和映射文件,這個級別需要添加JVM加載時候的代理(javaagent),使用代理來動態修改字節碼文件。

RUNTIME:運行時級別,注解存在于源碼、字節碼、java虛擬機中,主要用于運行時,可以使用反射獲取相關的信息。

?
1
2
3
4
5
6
7
8
9
10
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
  /**
   * Returns the retention policy.
   * @return the retention policy
   */
  RetentionPolicy value();
}

3. Java注解的內容

在上面的注解源碼中可以看到有的注解中沒有任何內容,有的注解的有內容,看似像方法。

注解的內容的語法格式: 數據類型 屬性名() default 默認值,數據類型用于描述屬性的數據類型,默認值是說當沒有給屬性賦值時使用默認值,一般String使用空字符串”“作為默認值,數組一般使用空數組{ }作為默認值.

下面看一下SpringMVC中的RequestMapping的注解的聲明

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
  String name() default "";
 
  @AliasFor("path")
  String[] value() default {};
 
  @AliasFor("value")
  String[] path() default {};
 
  RequestMethod[] method() default {};
  String[] params() default {};
  String[] headers() default {};
  String[] consumes() default {};
  String[] produces() default {};
}

使用SpringMVC中的RequestMapping注解

?
1
2
3
4
5
6
@RequestMapping(value = "/list",
        method = RequestMethod.POST,
        produces = {"application/json;charset=UTF-8;"})
public String list(){
 
}

4. 注解的使用場景

可以通過注解的聲明周期來分析注解的使用場景:

SOURCE源碼級別:給編譯器使用,如@Override、@Deprecated 等, 這部分開發者應該使用的場景不多

CLASS:字節碼級別,這部分也很少見到

RUNTIME:運行時級別,這個是最多的,幾乎開發者使用到的注解都是運行時級別,運行時注解常用的有以下幾種情況

注解中沒有任何屬性的,空的注解,這部分注解通常起到一個標注的作用,如@Test、@Before、@After,通過獲取這些標記注解在邏輯上做一些特殊的處理

可以使用約束注解@Constraint來對屬性值進行校驗,如@Email, @NotNull等

可以通過在注解中使用屬性來配置一些參數,然后可以使用反射獲取這些參數,這些注解沒有其他特殊的功能,只是簡單的代替xml配置的方式來配置一些參數。使用注解來配置參數這在Spring boot中得到了熱捧,如@Configuration

關于配置方式xml vs annotation, 一般使用xml配置一些和業務關系不太緊密的配置,使用注解配置一些和業務密切相關的參數。

三:Java注解和反射基本API

?
1
2
3
4
5
6
7
8
9
10
11
12
13
// 獲取某個類型的注解
public <A extends Annotation> A getAnnotation(Class<A> annotationClass);
// 獲取所有注解(包括父類中被Inherited修飾的注解)
public Annotation[] getAnnotations();
// 獲取聲明的注解(但是不包括父類中被Inherited修飾的注解)
public Annotation[] getDeclaredAnnotations();
// 判斷某個對象上是否被某個注解進行標注
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
 
// 獲取某個類聲明的所有字段
public Field[] getDeclaredFields() throws SecurityException;
// 獲取某個方法
public Method getMethod(String name, Class<?>... parameterTypes);

四:自定義注解

使用自定義注解+攔截器或者是AOP等可以進行權限的控制。

下面通過定義一個注解用來限制當用戶訪問接口時必須要登錄的示例

步驟一:定義注解

RequiresLogin.java

?
1
2
3
4
5
6
@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RequiresLogin {
 
}

步驟二:使用注解

?
1
2
3
4
5
6
7
8
9
10
11
@Controller
@RequestMapping("/user")
public class UserController {
  @RequiresLogin
  @RequestMapping(value = "/list", produces = {"application/json;charset=UTF-8;"})
  public String getUserList(){
 
    System.out.println("--------------");
    return "[{'id': 1, 'username':'zhangsan'}]";
  }
}

步驟三:使用AOP進行攔截,解析注解

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class LoginAdvices {
  public void before(JoinPoint joinPoint) throws Exception{
 
    Object target = joinPoint.getTarget();
    String methodName = joinPoint.getSignature().getName();
 
    System.out.println(target + "-------" + methodName);
    Method method = target.getClass().getMethod(methodName);
    boolean annotationPresent = method.isAnnotationPresent(RequiresLogin.class);
    if (annotationPresent) {
      // 用戶必須登錄
      boolean isLogin = false;
      if (!isLogin) {
        throw new Exception("訪問該接口必須先登錄");
      } else {
        System.out.println("已登錄...");
      }
    }
  }
}

在applicationContext.xml中配置aop

?
1
2
3
4
5
6
7
8
9
10
11
<bean id="loginAdvices" class="com.mengdee.manager.aop.LoginAdvices"/>
  <!-- aop配置 -->
  <aop:config proxy-target-class="true">
    <!--切面 -->
    <aop:aspect ref="loginAdvices">
      <!-- 切點 -->
      <aop:pointcut id="pointcut1" expression="execution(* com.mengdee.manager.controller.*.*(..))"/>
      <!--連接通知方法與切點 -->
      <aop:before method="before" pointcut-ref="pointcut1"/>
    </aop:aspect>
  </aop:config>

自定義異常

為什么要自定義異常

Java雖然提供了豐富的異常處理類,但是在項目中還會經常使用自定義異常,其主要原因是Java提供的異常類在某些情況下還是不能滿足各種業務的需求。 例如系統中有些錯誤是符合Java語法,但不符合業務邏輯。如當用戶登錄時賬號不存在或者賬號已鎖定可以自定義一個賬號異常AccountException。

或者有些情況下Java的同一個異常可能會有多種原因引起,在排查問題時不容易定位錯誤,此時可以使用自定義一個更加明確的異常。

自定義異常的好處:自定義異常可以使異常更加明確,可以隱藏底層的異常,這樣更安全,異常信息更加直觀。

自定義異常的使用:自定義異常一般繼承自Exception或者RuntimeException,根據業務需要可以帶一些屬性作為構造函數的參數,自定義異常需要程序員手動拋出異常,并處理異常。

下面是Apache Shiro中自定義異常的示例

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class ShiroException extends RuntimeException {
  public ShiroException() {
  }
 
  public ShiroException(String message) {
    super(message);
  }
 
  public ShiroException(Throwable cause) {
    super(cause);
  }
 
  public ShiroException(String message, Throwable cause) {
    super(message, cause);
  }
}

以上即是關于Java注解Annotation與自定義注解的詳細說明

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 肉色欧美久久久久久久蜜桃 | 成品人视频w免费观看w | 精品国产理论在线观看不卡 | 女子监狱第二季在线观看免费完整版 | 免费视频完整版在线观看网站 | 欧美一级艳片视频免费观看 | 鸥美毛片 | 九九精品视频在线观看 | 四虎影院在线免费播放 | 国产在线精品亚洲第一区香蕉 | 亚洲欧美自偷自拍另类小说 | 欧美撒尿屁股嘘嘘撒尿 | 日你逼 | 国产真实伦对白在线播放 | 欧美乱码视频 | 国产在线一区二区杨幂 | 午夜久久影院 | 色综合网天天综合色中文男男 | 任我淫| 精品手机在线视频 | 免费永久观看美女视频网站网址 | 亚洲日日做天天做日日谢 | 日韩一区三区 | 娇妻被朋友征服中文字幕 | 日本高清全集免费观看 | 99热精品在线播放 | 国产精品视频视频久久 | 亚洲人成在线观看一区二区 | 97热在线| 大jjjj免费看视频 | 日本人欧美xx | 天美传媒传媒免费观看 | 男人与雌性宠物交啪啪小说 | 亚洲欧美精品一区天堂久久 | 日本视频免费看 | 精品久久洲久久久久护士免费 | 午夜A级理论片左线播放 | 色图大全 | 美女被狂干 | 国产精品啪啪 | 国产精品99久久免费观看 |