日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢(xún)
選擇下列產(chǎn)品馬上在線(xiàn)溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
談?wù)凧ava中自定義注解及使用場(chǎng)景

Java自定義注解一般使用場(chǎng)景為:自定義注解+攔截器或者AOP,使用自定義注解來(lái)自己設(shè)計(jì)框架,使得代碼看起來(lái)非常優(yōu)雅。本文將先從自定義注解的基礎(chǔ)概念說(shuō)起,然后開(kāi)始實(shí)戰(zhàn),寫(xiě)小段代碼實(shí)現(xiàn)自定義注解+攔截器,自定義注解+AOP。

來(lái)賓網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián),來(lái)賓網(wǎng)站設(shè)計(jì)制作,有大型網(wǎng)站制作公司豐富經(jīng)驗(yàn)。已為來(lái)賓近千家提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\外貿(mào)網(wǎng)站制作要多少錢(qián),請(qǐng)找那個(gè)售后服務(wù)好的來(lái)賓做網(wǎng)站的公司定做!

一. 什么是注解(Annotation)

Java注解是什么,以下是引用自維基百科的內(nèi)容

Java注解又稱(chēng)Java標(biāo)注,是JDK5.0版本開(kāi)始支持加入源代碼的特殊語(yǔ)法元數(shù)據(jù)。

Java語(yǔ)言中的類(lèi)、方法、變量、參數(shù)和包等都可以被標(biāo)注。和Javadoc不同,Java標(biāo)注可以通過(guò)反射獲取標(biāo)注內(nèi)容。在編譯器生成類(lèi)文件時(shí),標(biāo)注可以被嵌入到字節(jié)碼中。Java虛擬機(jī)可以保留標(biāo)注內(nèi)容,在運(yùn)行時(shí)可以獲取到標(biāo)注內(nèi)容。當(dāng)然它也支持自定義Java標(biāo)注。

二. 注解體系圖

元注解:java.lang.annotation中提供了元注解,可以使用這些注解來(lái)定義自己的注解。主要使用的是Target和Retention注解

注解處理類(lèi):既然上面定義了注解,那得有辦法拿到我們定義的注解啊。java.lang.reflect.AnnotationElement接口則提供了該功能。注解的處理是通過(guò)java反射來(lái)處理的。

如下,反射相關(guān)的類(lèi)Class, Method, Field都實(shí)現(xiàn)了AnnotationElement接口。

因此,只要我們通過(guò)反射拿到Class, Method, Field類(lèi),就能夠通過(guò)getAnnotation(Class)拿到我們想要的注解并取值。

搜索Java知音公眾號(hào),回復(fù)“后端面試”,送你一份Java面試題寶典

三. 常用元注解

Target:描述了注解修飾的對(duì)象范圍,取值在java.lang.annotation.ElementType定義,常用的包括:

  •  METHOD:用于描述方法
  •  PACKAGE:用于描述包
  •  PARAMETER:用于描述方法變量
  •  TYPE:用于描述類(lèi)、接口或enum類(lèi)型

Retention: 表示注解保留時(shí)間長(zhǎng)短。取值在java.lang.annotation.RetentionPolicy中,取值為:

  •  SOURCE:在源文件中有效,編譯過(guò)程中會(huì)被忽略
  •  CLASS:隨源文件一起編譯在class文件中,運(yùn)行時(shí)忽略
  •  RUNTIME:在運(yùn)行時(shí)有效

只有定義為RetentionPolicy.RUNTIME時(shí),我們才能通過(guò)注解反射獲取到注解。

所以,假設(shè)我們要自定義一個(gè)注解,它用在字段上,并且可以通過(guò)反射獲取到,功能是用來(lái)描述字段的長(zhǎng)度和作用。

 
 
 
 
  1. @Target(ElementType.FIELD)  //  注解用于字段上 
  2. @Retention(RetentionPolicy.RUNTIME)  // 保留到運(yùn)行時(shí),可通過(guò)注解獲取 
  3. public @interface MyField { 
  4.     String description(); 
  5.     int length(); 
  6. }

四. 示例-反射獲取注解

先定義一個(gè)注解:

 
 
 
 
  1. @Target(ElementType.FIELD) 
  2. @Retention(RetentionPolicy.RUNTIME) 
  3. public @interface MyField { 
  4.     String description(); 
  5.     int length(); 
  6. }

通過(guò)反射獲取注解

 
 
 
 
  1. public class MyFieldTest { 
  2.     //使用我們的自定義注解 
  3.     @MyField(description = "用戶(hù)名", length = 12) 
  4.     private String username; 
  5.     @Test 
  6.     public void testMyField(){ 
  7.         // 獲取類(lèi)模板 
  8.         Class c = MyFieldTest.class; 
  9.         // 獲取所有字段 
  10.         for(Field f : c.getDeclaredFields()){ 
  11.             // 判斷這個(gè)字段是否有MyField注解 
  12.             if(f.isAnnotationPresent(MyField.class)){ 
  13.                 MyField annotation = f.getAnnotation(MyField.class); 
  14.                 System.out.println("字段:[" + f.getName() + "], 描述:[" + annotation.description() + "], 長(zhǎng)度:[" + annotation.length() +"]"); 
  15.             } 
  16.         } 
  17.     } 
  18. }

運(yùn)行結(jié)果

應(yīng)用場(chǎng)景一:自定義注解+攔截器 實(shí)現(xiàn)登錄校驗(yàn)

接下來(lái),我們使用springboot攔截器實(shí)現(xiàn)這樣一個(gè)功能,如果方法上加了@LoginRequired,則提示用戶(hù)該接口需要登錄才能訪(fǎng)問(wèn),否則不需要登錄。

首先定義一個(gè)LoginRequired注解

 
 
 
 
  1. @Target(ElementType.METHOD) 
  2. @Retention(RetentionPolicy.RUNTIME) 
  3. public @interface LoginRequired { 
  4. }

然后寫(xiě)兩個(gè)簡(jiǎn)單的接口,訪(fǎng)問(wèn)sourceA,sourceB資源

 
 
 
 
  1. @RestController 
  2. public class IndexController { 
  3.     @GetMapping("/sourceA") 
  4.     public String sourceA(){ 
  5.         return "你正在訪(fǎng)問(wèn)sourceA資源"; 
  6.     }
  7.     @GetMapping("/sourceB") 
  8.     public String sourceB(){ 
  9.         return "你正在訪(fǎng)問(wèn)sourceB資源"; 
  10.     } 
  11. }

沒(méi)添加攔截器之前成功訪(fǎng)問(wèn)

實(shí)現(xiàn)spring的HandlerInterceptor 類(lèi)先實(shí)現(xiàn)攔截器,但不攔截,只是簡(jiǎn)單打印日志,如下:

 
 
 
 
  1. public class SourceAccessInterceptor implements HandlerInterceptor { 
  2.     @Override 
  3.     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 
  4.         System.out.println("進(jìn)入攔截器了"); 
  5.         return true;
  6.      } 
  7.     @Override 
  8.     public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { 
  9.     } 
  10.     @Override 
  11.     public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { 
  12.     } 
  13. }

實(shí)現(xiàn)spring類(lèi)WebMvcConfigurer,創(chuàng)建配置類(lèi)把攔截器添加到攔截器鏈中

 
 
 
 
  1. @Configuration 
  2. public class InterceptorTrainConfigurer implements WebMvcConfigurer { 
  3.     @Override 
  4.     public void addInterceptors(InterceptorRegistry registry) { 
  5.         registry.addInterceptor(new SourceAccessInterceptor()).addPathPatterns("/**"); 
  6.     } 
  7. }

攔截成功如下

在sourceB方法上添加我們的登錄注解@LoginRequired

 
 
 
 
  1. @RestController 
  2. public class IndexController { 
  3.     @GetMapping("/sourceA") 
  4.     public String sourceA(){ 
  5.         return "你正在訪(fǎng)問(wèn)sourceA資源"; 
  6.     } 
  7.     @LoginRequired 
  8.     @GetMapping("/sourceB") 
  9.     public String sourceB(){ 
  10.         return "你正在訪(fǎng)問(wèn)sourceB資源"; 
  11.     } 
  12. }

簡(jiǎn)單實(shí)現(xiàn)登錄攔截邏輯

 
 
 
 
  1. @Override 
  2.     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 
  3.         System.out.println("進(jìn)入攔截器了"); 
  4.         // 反射獲取方法上的LoginRequred注解 
  5.         HandlerMethod handlerMethod = (HandlerMethod)handler; 
  6.         LoginRequired loginRequired = handlerMethod.getMethod().getAnnotation(LoginRequired.class); 
  7.         if(loginRequired == null){ 
  8.             return true; 
  9.         }
  10.         // 有LoginRequired注解說(shuō)明需要登錄,提示用戶(hù)登錄 
  11.         response.setContentType("application/json; charset=utf-8"); 
  12.         response.getWriter().print("你訪(fǎng)問(wèn)的資源需要登錄"); 
  13.         return false; 
  14.     }

運(yùn)行成功,訪(fǎng)問(wèn)sourceB時(shí)需要登錄了,訪(fǎng)問(wèn)sourceA則不用登錄

應(yīng)用場(chǎng)景二:自定義注解+AOP 實(shí)現(xiàn)日志打印

先導(dǎo)入切面需要的依賴(lài)包

 
 
 
 
  1.  
  2.       org.springframework.boot 
  3.      spring-boot-starter-aop 

定義一個(gè)注解@MyLog

 
 
 
 
  1. @Target(ElementType.METHOD) 
  2. @Retention(RetentionPolicy.RUNTIME) 
  3. public @interface MyLog {  
  4. }

定義一個(gè)切面類(lèi),見(jiàn)如下代碼注釋理解:

 
 
 
 
  1. @Aspect // 1.表明這是一個(gè)切面類(lèi) 
  2. @Component 
  3. public class MyLogAspect { 
  4.     // 2. PointCut表示這是一個(gè)切點(diǎn),@annotation表示這個(gè)切點(diǎn)切到一個(gè)注解上,后面帶該注解的全類(lèi)名 
  5.     // 切面最主要的就是切點(diǎn),所有的故事都圍繞切點(diǎn)發(fā)生 
  6.     // logPointCut()代表切點(diǎn)名稱(chēng) 
  7.     @Pointcut("@annotation(me.zebin.demo.annotationdemo.aoplog.MyLog)") 
  8.     public void logPointCut(){}; 
  9.     // 3. 環(huán)繞通知 
  10.     @Around("logPointCut()") 
  11.     public void logAround(ProceedingJoinPoint joinPoint){ 
  12.         // 獲取方法名稱(chēng) 
  13.         String methodName = joinPoint.getSignature().getName(); 
  14.         // 獲取入?yún)?nbsp;
  15.         Object[] param = joinPoint.getArgs(); 
  16.         StringBuilder sb = new StringBuilder(); 
  17.         for(Object o : param){ 
  18.             sb.append(o + "; "); 
  19.         } 
  20.         System.out.println("進(jìn)入[" + methodName + "]方法,參數(shù)為:" + sb.toString()); 
  21.         // 繼續(xù)執(zhí)行方法 
  22.         try { 
  23.             joinPoint.proceed(); 
  24.         } catch (Throwable throwable) { 
  25.             throwable.printStackTrace(); 
  26.         } 
  27.         System.out.println(methodName + "方法執(zhí)行結(jié)束");
  28.     } 
  29. }

在步驟二中的IndexController寫(xiě)一個(gè)sourceC進(jìn)行測(cè)試,加上我們的自定義注解:

 
 
 
 
  1. @MyLog 
  2. @GetMapping("/sourceC/{source_name}") 
  3. public String sourceC(@PathVariable("source_name") String sourceName){ 
  4.     return "你正在訪(fǎng)問(wèn)sourceC資源"; 
  5. }

啟動(dòng)springboot web項(xiàng)目,輸入訪(fǎng)問(wèn)地址


文章名稱(chēng):談?wù)凧ava中自定義注解及使用場(chǎng)景
路徑分享:http://www.5511xx.com/article/coggcio.html