在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Java注解及其底層原理解析2

jf_78858299 ? 來源:小牛呼嚕嚕 ? 作者:小牛呼嚕嚕 ? 2023-02-09 14:18 ? 次閱讀

最后我們寫一個測試類

public class TestAn {
    public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException {

        //獲取Person class 實例
        Class c1 = Person.class;

        //反射獲取 類上的注解
        MyAnnotation classAnnotation = c1.getAnnotation(MyAnnotation.class);
        System.out.println(classAnnotation.msg());

        //反射獲取 private屬性上的注解
        Field we = c1.getDeclaredField("weight");
        MyAnnotation fieldAnnotation = we.getAnnotation(MyAnnotation.class);
        System.out.println(fieldAnnotation.msg());

        //反射獲取 public屬性上的注解
        Field he = c1.getDeclaredField("height");
        MyAnnotation field2Annotation = he.getAnnotation(MyAnnotation.class);
        System.out.println(field2Annotation.msg());

        //反射獲取 方法上的注解
        Method me = c1.getMethod("dance",null);
        MyAnnotation methodAnnotation = me.getAnnotation(MyAnnotation.class);
        System.out.println(methodAnnotation.msg());
        

    }
}

結果:

this person class this person field private this person field public this person method

我們通過反射讀取api時,一般會先去校驗這個注解存不存在:

if(c1.isAnnotationPresent(MyAnnotation.class)) {
    //存在 MyAnnotation 注解
}else {
    //不存在 MyAnnotation 注解
}

我們發現反射真的很強大,不僅可以讀取類的屬性、方法、構造器等信息,還可以讀取類的注解相關信息。

那反射是如何實現工作的?

我們來看下源碼:

c1.getAnnotation(MyAnnotation.class);通過idea點進去查看源碼,把重點的給貼出來,其他的就省略了

Map<Classextends Annotation>, Annotation> declaredAnnotations =
            AnnotationParser.parseAnnotations(getRawAnnotations(), getConstantPool(), this);

parseAnnotations()去 分析注解 ,其第一個參數是 獲取原始注解,第二個參數是獲取常量池內容

public static Annotation annotationForMap(final Classextends Annotation> var0, final Map<String, Object> var1) {
        return (Annotation)AccessController.doPrivileged(new PrivilegedAction() {
            public Annotation run() {
                return (Annotation)Proxy.newProxyInstance(var0.getClassLoader(), new Class[]{var0}, new AnnotationInvocationHandler(var0, var1));
            }
        });
    }

Proxy._newProxyInstance_(var0.getClassLoader(), new Class[]{var0}, new AnnotationInvocationHandler(var0, var1)創建動態代理,此處var0參數是由常量池獲取的數據轉換而來。

我們監聽此處的var0:

圖片

image-20220616225518195

可以推斷出注解相關的信息 是存放在常量池中的

我們來總結一下,反射調用getAnnotations(MyAnnotation.class)方法的背后主要操作:

解析注解parseAnnotations()的時候 從該注解類的常量池中取出注解相關的信息,將其轉換格式后,通過newProxyInstance(注解的類加載器,注解的class實例 ,AnotationInvocationHandler實例)來創建代理對象,作為參數傳進去,最后返回一個代理實例。

其中AnotationInvocationHandler類是一個典型的動態代理類, 這邊先挖個坑,暫不展開,不然這篇文章是寫不完了

關于動態代理類我們只需先知道: 對象的執行方法,交給代理來負責

class AnnotationInvocationHandler implements InvocationHandler, Serializable {
    ...
    private final Map<String, Object> memberValues;//存放該注解所有屬性的值
    private transient volatile Method[] memberMethods = null;

    AnnotationInvocationHandler(Classextends Annotation> var1, Map<String, Object> var2) {
    ...
    }

    public Object invoke(Object var1, Method var2, Object[] var3) {
    ...
     //調用委托類對象的方法,具體等等一些操作
    }
    ...
}

反射調用getAnnotations(MyAnnotation.class),返回一個代理實例,我們可以通過這個實例來操作該注解

示例:注解 模擬訪問權限控制

當我們引入springsecurity來做安全框架,然后只需添加@PreAuthorize**(**"hasRole('Admin')"**)**注解,就能實現權限的控制,簡簡單單地一行代碼,就優雅地實現了權限控制,覺不覺得很神奇?讓我們一起模擬一個出來吧

@Retention(RetentionPolicy.RUNTIME)
public @interface MyPreVer {
    String value() default "no role";
}
public class ResourceLogin {
    private String name;

    @MyPreVer(value = "User")
    private void rsA() {
        System.out.println("資源A");
    }
    @MyPreVer(value = "Admin")
    private void rsB() {
        System.out.println("資源B");
    }
}
public class TestLogin {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
        //模擬 用戶的權限
        String role = "User";
        //模擬 需要的權限
        final String RoleNeeded = "Admin";

        //獲取Class實例
        Class c1 = ResourceLogin.class;

        //訪問資源A
        Method meA = c1.getDeclaredMethod("rsA",null);
        MyPreVer meAPre = meA.getDeclaredAnnotation(MyPreVer.class);
        if(meAPre.value().equals(RoleNeeded)) {//模擬攔截器
            meA.setAccessible(true);
            meA.invoke(c1.newInstance(),null);//模擬訪問資源
        }else {
            System.out.println("騷瑞,你無權訪問該資源");
        }

        //訪問資源B
        Method meB = c1.getDeclaredMethod("rsB",null);
        MyPreVer meBPre = meB.getDeclaredAnnotation(MyPreVer.class);
        if(meBPre.value().equals(RoleNeeded)) {//模擬攔截器
            meB.setAccessible(true);
            meB.invoke(c1.newInstance());//模擬訪問資源

        }else {
            System.out.println("騷瑞,你無權訪問該資源");
        }

    }
}

結果:

騷瑞,你無權訪問該資源 資源B

尾語

注解 是一種 標記、標簽 來修飾代碼, 但它不是代碼本身的一部分,即 注解本身對代碼邏輯沒有任何影響 ,如何使用注解完全取決于我們開發者Java反射來讀取和使用。

我們發現反射真的很強大,不僅可以讀取類的屬性、方法、構造器等信息,還可以讀取類的注解相關信息,以后還會經常遇到它。

注解一般用于

  • 編譯器可以利用注解來探測錯誤和檢查信息,像@override檢查是否重寫
  • 適合工具類型的軟件用的,避免繁瑣的代碼,生成代碼配置,比如jpa自動生成sql,日志注解,權限控制
  • 程序運行時的處理:某些注解可以在程序運行的時候接受代碼的讀取,比如我們可以自定義注解

平時我們只知道如何使用注解,卻不知道其是如何起作用的,理所當然的往往是我們所忽視的。

參考資料

《Java核心技術 卷一》

https://blog.csdn.net/qq_20009015/article/details/106038023

https://zhuanlan.zhihu.com/p/258429599

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • JAVA
    +關注

    關注

    19

    文章

    2967

    瀏覽量

    104748
  • spring
    +關注

    關注

    0

    文章

    340

    瀏覽量

    14343
  • 注解
    +關注

    關注

    0

    文章

    18

    瀏覽量

    2674
收藏 人收藏

    評論

    相關推薦

    如何通過注解來優化我們的Java代碼

    Java注解可以說是我們編碼過程中最常用的。本篇文章將給大家介紹Java注解的概念、作用以及如何使用注解來提升代碼的可讀性和靈活性,并介紹如
    的頭像 發表于 09-30 11:39 ?639次閱讀

    java經典面試題深度解析

    免費視頻教程:java經典面試題深度解析對于很多初學者來說,學好java在后期面試的階段都沒什么經驗,為了讓大家更好的了解面試相關知識,今天在這里給大家分享了一個java經典面試題深度
    發表于 06-20 15:16

    詳細介紹了Java泛型、注解、并發編程

    介紹了Java泛型、注解、并發編程、數據傳輸與序列化、高效IO、容器集合、反射與類加載以及JVM重點知識線程、內存模型、JVM運行時內存、垃圾回收與算法、Java中四種引用類型、GC 分代收集算法
    發表于 08-20 06:09

    HarmonyOS注解的使用方法分享

    定義我們的注解自定義注解1、聲明注解功能:檢測類中是否有規范的get方法新建java libray的module,命名為annotation,創建
    發表于 03-28 14:04

    微信ANR原理解析與解決方案

    理解析 CSDN 博客專家@三精-大精wing 對于導致微信 ANR 的根本原因進行了解析(以下為授權發布): 本文目的在于學習研究Android技術,若有侵犯,聯系作者將及時刪除。 首先,微信
    發表于 09-26 17:09 ?0次下載
    微信ANR原<b class='flag-5'>理解析</b>與解決方案

    分析java注解基本概念

    什么是注解(Annotation): Annotation(注解)就是Java提供了一種元程序中的元素關聯任何信息和著任何元數據(metadata)的途徑和方法。Annotion(注解
    發表于 09-27 14:53 ?0次下載

    Java底層實現,CPU還有10個術語!

    Java底層實現——CPU的10個術語
    的頭像 發表于 03-28 14:14 ?6257次閱讀

    注解定義Bean及開發

    注解本質是一個繼承了Annotation 的特殊接口,其具體實現類是Java 運行時生成的動態代理類。
    發表于 08-02 10:26 ?442次閱讀

    Java注解及其底層理解析 1

    什么是注解? 當我們開發SpringBoot項目,我們只需對啟動類加上`@SpringBootApplication`,就能自動裝配,不需要編寫冗余的xml配置。當我們為項目添加lombok
    的頭像 發表于 02-09 14:18 ?764次閱讀
    <b class='flag-5'>Java</b><b class='flag-5'>注解</b><b class='flag-5'>及其</b><b class='flag-5'>底層</b>原<b class='flag-5'>理解析</b> 1

    容器配置及Spring Boot注解

    Autowired注解用于標記Spring將要解析和注入的依賴項。此注解可以作用在構造函數、字段和setter方法上。
    的頭像 發表于 04-07 11:45 ?578次閱讀
    容器配置及Spring Boot<b class='flag-5'>注解</b>

    SpringBoot的核心注解2

    今天跟大家來探討下SpringBoot的核心注解@SpringBootApplication以及run方法,理解下springBoot為什么不需要XML,達到零配置
    的頭像 發表于 04-07 14:34 ?1963次閱讀
    SpringBoot的核心<b class='flag-5'>注解</b><b class='flag-5'>2</b>

    JAVA注解是怎么做到的(上)

    。它可以聲明在包、類、字段、方法、局部變量、方法參數等的前面,用來對這些元素進行說明,注釋。那么你知道JDK什么是元注解嗎?注解有哪些分類嗎?以及注解Java中最本質究竟是什么東西,
    的頭像 發表于 05-11 10:57 ?645次閱讀

    JAVA注解是怎么做到的(下)

    。它可以聲明在包、類、字段、方法、局部變量、方法參數等的前面,用來對這些元素進行說明,注釋。那么你知道JDK什么是元注解嗎?注解有哪些分類嗎?以及注解Java中最本質究竟是什么東西,
    的頭像 發表于 05-11 10:57 ?571次閱讀
    <b class='flag-5'>JAVA</b>中<b class='flag-5'>注解</b>是怎么做到的(下)

    3分鐘純Java注解搭個管理系統

    Erupt一個通用后臺管理框架,據說有 超低代碼量 、 零前端代碼 、零 CURD操作 、無需建表 ,純Java注解開發 等特色,號稱三分鐘就可以搭建一個完整的后臺管理系統。
    的頭像 發表于 07-28 11:27 ?1112次閱讀
    3分鐘純<b class='flag-5'>Java</b><b class='flag-5'>注解</b>搭個管理系統

    springmvc常用5種注解

    SpringMVC是一種基于Java的Web框架,使用注解可以更加方便靈活地開發和管理控制器,實現請求的映射和處理。在SpringMVC中,有許多常用的注解,本文將詳細介紹其中的五種注解
    的頭像 發表于 11-22 16:51 ?898次閱讀
    主站蜘蛛池模板: 久操中文| 美女无遮挡拍拍拍免费视频| 亚洲1234区乱码| 婷婷色香五月激情综合2020| 综合亚洲一区二区三区| 国产男女免费视频| 四虎影院视频| 美女扒开尿囗给男人玩的动图| 四虎影视院| 久久精品视频5| 国产精品电影一区| 天天爱夜夜| 国产精品任我爽爆在线播放6080| 国产在线麻豆自在拍91精品| 天堂在线影院| 久久夜色精品国产噜噜小说| 奇米网在线观看| 中文字幕视频二区| 天天色综合色| 成 人在线观看视频网站| 久久久久免费| 全是肉的高h短篇列车| 色女人在线| 国产成人永久免费视频| 日本欧美强乱视频在线| 18男女很黄的视频| 欧美伊人| 夜夜操天天干| 最新黄色在线| 一区国产传媒国产精品| 蕾丝视频成人★在线观看| 天天做天天爱天天干| 欧美乱理伦另类视频| 亚洲国产激情在线一区| 久久国产视频一区| bt天堂网在线| 99久久精品费精品国产| 国产经典一区| 亚洲一本视频| 日本黄色免费一级片| 午夜免费理论片在线看|