91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

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

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

Java中怎么使用自定義注解

發布時間:2021-06-30 17:56:45 來源:億速云 閱讀:165 作者:Leah 欄目:編程語言

本篇文章為大家展示了Java中怎么使用自定義注解,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。

一. 什么是注解(Annotation)

Java注解是什么,以下是引用自維基百科的內容

Java注解又稱Java標注,是JDK5.0版本開始支持加入源代碼的特殊語法元數據。

Java語言中的類、方法、變量、參數和包等都可以被標注。和Javadoc不同,Java標注可以通過反射獲取標注內容。在編譯器生成類文件時,標注可以被嵌入到字節碼中。Java虛擬機可以保留標注內容,在運行時可以獲取到標注內容。當然它也支持自定義Java標注。

 

二. 注解體系圖

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

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


因此,只要我們通過反射拿到Class, Method, Field類,就能夠通過getAnnotation(Class<T>)拿到我們想要的注解并取值。

搜索Java知音公眾號,回復“后端面試”,送你一份Java面試題寶典

 

三. 常用元注解

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

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

Retention: 表示注解保留時間長短。取值在java.lang.annotation.RetentionPolicy中,取值為:

  • SOURCE:在源文件中有效,編譯過程中會被忽略
  • CLASS:隨源文件一起編譯在class文件中,運行時忽略
  • RUNTIME:在運行時有效

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

所以,假設我們要自定義一個注解,它用在字段上,并且可以通過反射獲取到,功能是用來描述字段的長度和作用。

@Target(ElementType.FIELD)  //  注解用于字段上
@Retention(RetentionPolicy.RUNTIME)  // 保留到運行時,可通過注解獲取
public @interface MyField {
    String description();
    int length();
}
   

四. 示例-反射獲取注解

先定義一個注解:

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyField {
    String description();
    int length();
}
 

通過反射獲取注解

public class MyFieldTest {

    //使用我們的自定義注解
    @MyField(description = "用戶名", length = 12)
    private String username;

    @Test
    public void testMyField(){

        // 獲取類模板
        Class c = MyFieldTest.class;

        // 獲取所有字段
        for(Field f : c.getDeclaredFields()){
            // 判斷這個字段是否有MyField注解
            if(f.isAnnotationPresent(MyField.class)){
                MyField annotation = f.getAnnotation(MyField.class);
                System.out.println("字段:[" + f.getName() + "], 描述:[" + annotation.description() + "], 長度:[" + annotation.length() +"]");
            }
        }

    }
}
   

應用場景一:自定義注解+攔截器 實現登錄校驗

接下來,我們使用springboot攔截器實現這樣一個功能,如果方法上加了@LoginRequired,則提示用戶該接口需要登錄才能訪問,否則不需要登錄。

首先定義一個LoginRequired注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginRequired {
    
}
 

然后寫兩個簡單的接口,訪問sourceA,sourceB資源

@RestController
public class IndexController {

    @GetMapping("/sourceA")
    public String sourceA(){
        return "你正在訪問sourceA資源";
    }

    @GetMapping("/sourceB")
    public String sourceB(){
        return "你正在訪問sourceB資源";
    }

}

實現spring的HandlerInterceptor 類先實現攔截器,但不攔截,只是簡單打印日志,如下:

public class SourceAccessInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("進入攔截器了");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}
 

實現spring類WebMvcConfigurer,創建配置類把攔截器添加到攔截器鏈中

@Configuration
public class InterceptorTrainConfigurer implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new SourceAccessInterceptor()).addPathPatterns("/**");
    }
}

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

@RestController
public class IndexController {

    @GetMapping("/sourceA")
    public String sourceA(){
        return "你正在訪問sourceA資源";
    }

    @LoginRequired
    @GetMapping("/sourceB")
    public String sourceB(){
        return "你正在訪問sourceB資源";
    }

}
 

簡單實現登錄攔截邏輯

@Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("進入攔截器了");

        // 反射獲取方法上的LoginRequred注解
        HandlerMethod handlerMethod = (HandlerMethod)handler;
        LoginRequired loginRequired = handlerMethod.getMethod().getAnnotation(LoginRequired.class);
        if(loginRequired == null){
            return true;
        }

        // 有LoginRequired注解說明需要登錄,提示用戶登錄
        response.setContentType("application/json; charset=utf-8");
        response.getWriter().print("你訪問的資源需要登錄");
        return false;
    }

運行成功,訪問sourceB時需要登錄了,訪問sourceA則不用登錄

應用場景二:自定義注解+AOP 實現日志打印

先導入切面需要的依賴包

<dependency>
      <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
 

定義一個注解@MyLog

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyLog {
    
}
 

定義一個切面類,見如下代碼注釋理解:

@Aspect // 1.表明這是一個切面類
@Component
public class MyLogAspect {

    // 2. PointCut表示這是一個切點,@annotation表示這個切點切到一個注解上,后面帶該注解的全類名
    // 切面最主要的就是切點,所有的故事都圍繞切點發生
    // logPointCut()代表切點名稱
    @Pointcut("@annotation(me.zebin.demo.annotationdemo.aoplog.MyLog)")
    public void logPointCut(){};

    // 3. 環繞通知
    @Around("logPointCut()")
    public void logAround(ProceedingJoinPoint joinPoint){
        // 獲取方法名稱
        String methodName = joinPoint.getSignature().getName();
        // 獲取入參
        Object[] param = joinPoint.getArgs();

        StringBuilder sb = new StringBuilder();
        for(Object o : param){
            sb.append(o + "; ");
        }
        System.out.println("進入[" + methodName + "]方法,參數為:" + sb.toString());

        // 繼續執行方法
        try {
            joinPoint.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        System.out.println(methodName + "方法執行結束");

    }
}
 

在步驟二中的IndexController寫一個sourceC進行測試,加上我們的自定義注解:

    @MyLog
    @GetMapping("/sourceC/{source_name}")
    public String sourceC(@PathVariable("source_name") String sourceName){
        return "你正在訪問sourceC資源";
    }

上述內容就是Java中怎么使用自定義注解,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。

向AI問一下細節

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

AI

威宁| 韶山市| 鄂伦春自治旗| 颍上县| 台山市| 龙山县| 陆丰市| 星子县| 晋城| 南宁市| 静安区| 青田县| 黑水县| 多伦县| 安岳县| 句容市| 张家界市| 什邡市| 镇安县| 定日县| 武定县| 紫阳县| 尼玛县| 寻甸| 安塞县| 丰都县| 宜丰县| 兴城市| 平泉县| 德保县| 临安市| 乌鲁木齐市| 富源县| 金华市| 沙雅县| 湖北省| 阿图什市| 台山市| 贵州省| 齐齐哈尔市| 城固县|