<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          手寫web服務器:定義Autorwired注解,實現屬性自動注入

          共 6733字,需瀏覽 14分鐘

           ·

          2021-06-12 06:34

          前言

          昨天,我們已經解決了post請求的阻塞問題,所以我們今天又可以繼續(xù)搞事情了,今天我們要實現的也是spring中很核心的注解——Autowired。這個注解想必大家肯定不陌生,在spring項目中,我們經常用它來為我們的屬性注入值,實現屬性的自動裝配。

          好了,話不多說,我們來看具體如何實現.

          實現過程

          定義注解

          這一塊就很簡單了,前面我們也不止一次寫過,這里target指定的是屬性

          @Target(ElementType.FIELD)
          @Retention(RetentionPolicy.RUNTIME)
          public @interface Autowired {
          }

          加到屬性上

          直接把@Autowired注解加在我們要注入的屬性上

          優(yōu)化掃描方法

          屬性是在類初始化的時候,自動被賦值的,所以我們要調整初始化流程

          private static void initRequestMappingMap() {
                  logger.info("start to scanRequestMapping, controllerSet = {}", classSet);
                  if (classSet == null) {
                      return;
                  }
                  classSet.forEach(aClass -> {
                      Annotation controller = aClass.getAnnotation(Controller.class);
                      if (Objects.isNull(controller)) {
                          return;
                      }
                      Method[] methods = aClass.getDeclaredMethods();
                      for (Method method : methods) {
                          RequestMapping annotation = method.getAnnotation(RequestMapping.class);
                          if (Objects.nonNull(annotation)) {
                              requestMappingMap.put(annotation.value(), method);
                          }
                      }
                      Field[] fields = aClass.getDeclaredFields();
                      try {
                          Object o = aClass.newInstance();
                          for (Field field : fields) {
                              Autowired annotation = field.getAnnotation(Autowired.class);
                              if (Objects.nonNull(annotation)) {
                                  field.setAccessible(true);
                                  field.set(o, contentMap.get(field.getType().getName()));
                              }
                          }
                          contentMap.put(aClass.getName(), o);
                      } catch (InstantiationException e) {
                          logger.error("初始controller失?。?, e);
                      } catch (IllegalAccessException e) {
                          logger.error("初始controller失?。?, e);
                      }
                  });
                  logger.info("scanRequestMapping end, requestMappingMap = {}", requestMappingMap);
              }

          我們在初始化這里加了一段字段初始化的代碼,上面是完整代碼,字段初始化只有短短幾行:

          Field[] fields = aClass.getDeclaredFields();
          try {
              Object o = aClass.newInstance();
              for (Field field : fields) {
                  Autowired annotation = field.getAnnotation(Autowired.class);
                  if (Objects.nonNull(annotation)) {
                      field.setAccessible(true);
                      field.set(o, contentMap.get(field.getType().getName()));
                  }
              }
              contentMap.put(aClass.getName(), o);
          catch (InstantiationException e) {
              logger.error("初始controller失?。?, e);
          catch (IllegalAccessException e) {
              logger.error("初始controller失?。?, e);
          }

          這里需要注意的是,因為屬性是私有的,必須通過getDeclaredFields獲取屬性值,getFields方法是沒辦法拿到私有屬性的;

          另外一個需要注意的點是,私有屬性必須通過setAccessible設置為可訪問才可以,否則會報錯:

          因為字段賦值是基于對象實例的,所以我們要先創(chuàng)建類的實例:

          Object o = aClass.newInstance()

          然后通過field.set給屬性賦值,這里賦值要通過IOC容器拿到賦值對象的實例,所以被賦值屬性的實例必須先初始化,否則會有問題。

          同時,我們把帶有@Autowired注解的類的實例也存進了IOC容器,這樣在后面調用controller對應mapping方法的時候,我們直接從ioc容器中拿出來即可:

          Object o = contentMap.get(declaringClass.getName());
          Object invoke = method.invoke(o, parameters);

          這是因為如果你在調用的時候再去創(chuàng)建實例,這時候屬性也要賦值,否則會報錯的,所以初始化的時候直接創(chuàng)建實例是比較合理的方式。

          測試

          瀏覽器調用下試下:

          可以看到,我們調用的時候,service已經有值了,方法調用完成后,結果正常返回:

          總結

          好了,今天的內容到這里就結束了。在上面的內容中,我們展示了@Autowired注解的定義、具體的應用,以及Ioc對于Autowired注解的處理過程,最后我們經過測試,結果與預期一致,當然具體springboot是如何實現的,還需要進一步的研究和探討,我這里分享的是自己的實現思路,感興趣的小伙伴可以自己動手試下。

          下面是項目的開源倉庫,有興趣的小伙伴可以去看看,如果有想法的小伙伴,我真心推薦你自己動個手,自己寫一下,真的感覺不錯:

          https://github.com/Syske/syske-boot
          - END -


          瀏覽 53
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美日韩一区在线观看视频 | 欧美性猛交ⅩXXX乱大交 | 91久久精品人人槡人妻人 | www日本黄色 | 国内免费黄色视频 |