<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服務(wù)器:定義@value注解,實現(xiàn)配置自動注入

          共 10560字,需瀏覽 22分鐘

           ·

          2021-06-12 06:33

          前言

          昨天我們定義了Configuration注解和Bean注解,實現(xiàn)了更靈活的類注入,今天我們來看另一個配置注入的注解Value,這個注解也是我們在springboot中經(jīng)常用到的,今天我們就來看下如何通過value注解實現(xiàn)properties配置的自動注入。

          實現(xiàn)過程

          定義properties工具類

          這個工具類的作用主要是解析我們的配置文件,并生成一個配置文件的字典數(shù)據(jù),然后我們可以根據(jù)自己的需要獲取對應(yīng)的配置,這也是我們實現(xiàn)配置自動注入的第一步。

          public class PropertiesUtil {
              private static HashMap<String, PropertiesUtil> configMap = new HashMap();
              private Date loadTime = null;
              private ResourceBundle resourceBundle = null;
              private static final Integer TIME_OUT = 60000;

              private PropertiesUtil(String name) {
                  this.loadTime = new Date();

                  try {
                      this.resourceBundle = ResourceBundle.getBundle(name);
                  } catch (Exception var3) {
                      this.resourceBundle = null;
                  }

              }

              public static synchronized PropertiesUtil getInstance() {
                  return getInstance("application");
              }

              public static synchronized PropertiesUtil getInstance(String name) {
                  PropertiesUtil conf = configMap.get(name);
                  if (null == conf) {
                      conf = new PropertiesUtil(name);
                      configMap.put(name, conf);
                  }

                  if ((new Date()).getTime() - conf.getLoadTime().getTime() > (long)TIME_OUT) {
                      conf = new PropertiesUtil(name);
                      configMap.put(name, conf);
                  }

                  return conf;
              }

              public String get(String key) {
                  try {
                      String value = this.resourceBundle.getString(key);
                      return value;
                  } catch (MissingResourceException var3) {
                      return "";
                  } catch (NullPointerException var4) {
                      return "";
                  }
              }

              public Integer getInt(String key) {
                  try {
                      String value = this.resourceBundle.getString(key);
                      return Integer.parseInt(value);
                  } catch (MissingResourceException var3) {
                      return null;
                  } catch (NullPointerException var4) {
                      return null;
                  }
              }

              public boolean getBoolean(String key) {
                  try {
                      String value = this.resourceBundle.getString(key);
                      return "true".equals(value);
                  } catch (MissingResourceException var3) {
                      return false;
                  } catch (NullPointerException var4) {
                      return false;
                  }
              }

              public Date getLoadTime() {
                  return this.loadTime;
              }

              public static String getPropertiesValue(String name, String key) {
                  try {
                      return getInstance(name).get(key);
                  } catch (MissingResourceException var3) {
                      return "";
                  } catch (NullPointerException var4) {
                      return "";
                  }
              }
          }

          定義value注解

          依然是輕車熟路,這里的value()是用來接受我們的配置名稱的。

          @Target(ElementType.FIELD)
          @Retention(RetentionPolicy.RUNTIME)
          public @interface Value {
              String value();
          }

          實現(xiàn)配置注入

          在之前的實現(xiàn)基礎(chǔ)上,我們增加了一個配置處理的類,這個類有兩個方法,分別是用于實現(xiàn)單個屬性注入和批量屬性注入:

          public class ConfigurationHandler {
              private static final PropertiesUtil propertiesUtil = PropertiesUtil.getInstance("application");

              /**
               * 初始化value配置信息
               * @param instance
               * @param field
               * @throws IllegalAccessException
               */

              public static void initValueConfig(Object instance, Field field) throws IllegalAccessException {
                  Annotation annotation = field.getAnnotation(Value.class);
                  if (Objects.nonNull(annotation)) {
                      String propertiesKeyName = ((Value) annotation).value();
                      Class<?> type = field.getType();
                      if (!field.isAccessible()) {
                          field.setAccessible(Boolean.TRUE);
                      }
                      if (Integer.class.equals(type)) {
                          field.setInt(instance, propertiesUtil.getInt(propertiesKeyName));
                      } else if (Boolean.class.equals(type)) {
                          field.setBoolean(instance, propertiesUtil.getBoolean(propertiesKeyName));
                      } else {
                          field.set(instance, propertiesUtil.get(propertiesKeyName));
                      }
                  }
              }

              /**
               * 批量初始化value配置
               * @param aClass
               * @param instance
               * @throws IllegalAccessException
               */

              public static void batchInitValueConfig(Class aClass, Object instance) throws IllegalAccessException {
                  Field[] declaredFields = aClass.getDeclaredFields();
                  for (Field declaredField : declaredFields) {
                      initValueConfig(instance, declaredField);
                  }

              }
          }

          首先,我們在IoC實例化階段,對各種組件的字段進(jìn)行掃描,拿出有Value注解的屬性,根據(jù)注解的值獲取對應(yīng)的配置。

          使用效果

          我們在service組件上加入一個屬性,并加上value注解:

          然后在我們的配置文件中增加對應(yīng)的配置:

          運(yùn)行測試

          運(yùn)行測試下:

          可以看到,我們的配置已經(jīng)被注入進(jìn)來了,這樣注入配置,既簡單又方便。當(dāng)然,相比于SpringValue注解,我們的還是顯得比較低級,因為springvalue注解是支持表達(dá)式的,它有一套專門的Spring EL,所以我們看的springvalue是這樣寫的:

          @Value("${syske.boot.server.name}")
          private String serverName;
          // 或者這樣
          @Value("#{syske.boot.server.name}")
          private String serverName;

          好了,今天的內(nèi)容就這么多,我們接下來總結(jié)一下。

          總結(jié)

          注解本質(zhì)上只是一種標(biāo)記,是為了便于我們通過反射操作類的屬性、方法等資源,實現(xiàn)我們的高級功能。value注解就是獲取配置的一種標(biāo)記,我們通過在實例化對象后對其字段操作,實現(xiàn)配置的自動注入。

          在我實際測試的時候,我發(fā)現(xiàn)這種配置注入方式,對靜態(tài)變量也是有效的,但是springvalue對靜態(tài)變量是無效的,暫時沒有去看spring的源碼,不知道是實現(xiàn)方式的問題還是EL表達(dá)式的鍋。

          原本我以為是因為字段和方法的反射操作都是基于類的實例,所以對于靜態(tài)方法和變量是沒有任何效果的,但是經(jīng)過實測的時候,發(fā)現(xiàn)并非如此,后面再好好研究下。

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

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


          瀏覽 80
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <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>
                  欧美黑人大吊 | 操bxx网站在线观看 | 亚洲一级特黄视频 | h片在线观看 | 小电影在线观看黄.999 |