1. 1 不可撤销
  2. 2 小年兽 程嘉敏
  3. 3 手放开 李圣杰
  4. 4 迷人的危险3(翻自 dance flow) FAFA
  5. 5 山楂树之恋 程佳佳
  6. 6 summertime cinnamons / evening cinema
  7. 7 不谓侠(Cover 萧忆情Alex) CRITTY
  8. 8 神武醉相思(翻自 优我女团) 双笙
  9. 9 空山新雨后 音阙诗听 / 锦零
  10. 10 Wonderful U (Demo Version) AGA
  11. 11 广寒宫 丸子呦
  12. 12 陪我看日出 回音哥
  13. 13 春夏秋冬的你 王宇良
  14. 14 世界が终わるまでは… WANDS
  15. 15 多想在平庸的生活拥抱你 隔壁老樊
  16. 16 千禧 徐秉龙
  17. 17 我的一个道姑朋友 双笙
  18. 18 大鱼  (Cover 周深) 双笙
  19. 19 霜雪千年(Cover 洛天依 / 乐正绫) 双笙 / 封茗囧菌
  20. 20 云烟成雨(翻自 房东的猫) 周玥
  21. 21 情深深雨濛濛 杨胖雨
  22. 22 Five Hundred Miles Justin Timberlake / Carey Mulligan / Stark Sands
  23. 23 斑马斑马 房东的猫
  24. 24 See You Again Wiz Khalifa / Charlie Puth
  25. 25 Faded Alan Walker / Iselin Solheim
  26. 26 Natural J.Fla
  27. 27 New Soul Vox Angeli
  28. 28 ハレハレヤ(朗朗晴天)(翻自 v flower) 猫瑾
  29. 29 像鱼 王贰浪
  30. 30 Bye Bye Bye Lovestoned
  31. 31 Blame You 眠 / Lopu$
  32. 32 Believer J.Fla
  33. 33 书信 戴羽彤
  34. 34 柴 鱼 の c a l l i n g【已售】 幸子小姐拜托了
  35. 35 夜空中最亮的星(翻自 逃跑计划) 戴羽彤
  36. 36 慢慢喜欢你 LIve版(翻自 莫文蔚) 戴羽彤
  37. 37 病变(翻自 cubi) 戴羽彤
  38. 38 那女孩对我说 (完整版) Uu
  39. 39 绿色 陈雪凝
  40. 40 月牙湾 LIve版(翻自 F.I.R.) 戴羽彤
夜空中最亮的星(翻自 逃跑计划) - 戴羽彤
00:00 / 04:10

夜空中最亮的星 能否听清

那仰望的人 心底的孤独和叹息

夜空中最亮的星 能否记起

那曾与我同行 消失在风里的身影

我祈祷拥有一颗透明的心灵

和会流泪的眼睛

给我再去相信的勇气

越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请指引我靠近你

夜空中最亮的星 是否知道

那曾与我同行的身影 如今在哪里

夜空中最亮的星 是否在意

是等太阳先升起 还是意外先来临

我宁愿所有痛苦都留在心底

也不愿忘记你的眼睛

哦 给我再去相信的勇气

哦 越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请照亮我向前行 哒~

我祈祷拥有一颗透明的心灵

和会流泪的眼睛 哦

给我再去相信的勇气

哦 越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请照亮我向前行

手写web服务器:定义@value注解,实现配置自动注入

前言

昨天我们定义了Configuration注解和Bean注解,实现了更灵活的类注入,今天我们来看另一个配置注入的注解Value,这个注解也是我们在springboot中经常用到的,今天我们就来看下如何通过value注解实现properties配置的自动注入。

实现过程

定义properties工具类

这个工具类的作用主要是解析我们的配置文件,并生成一个配置文件的字典数据,然后我们可以根据自己的需要获取对应的配置,这也是我们实现配置自动注入的第一步。

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();
}

实现配置注入

在之前的实现基础上,我们增加了一个配置处理的类,这个类有两个方法,分别是用于实现单个属性注入和批量属性注入:

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实例化阶段,对各种组件的字段进行扫描,拿出有Value注解的属性,根据注解的值获取对应的配置。

使用效果

我们在service组件上加入一个属性,并加上value注解:

然后在我们的配置文件中增加对应的配置:

运行测试

运行测试下:

可以看到,我们的配置已经被注入进来了,这样注入配置,既简单又方便。当然,相比于SpringValue注解,我们的还是显得比较低级,因为springvalue注解是支持表达式的,它有一套专门的Spring EL,所以我们看的springvalue是这样写的:

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

好了,今天的内容就这么多,我们接下来总结一下。

总结

注解本质上只是一种标记,是为了便于我们通过反射操作类的属性、方法等资源,实现我们的高级功能。value注解就是获取配置的一种标记,我们通过在实例化对象后对其字段操作,实现配置的自动注入。

在我实际测试的时候,我发现这种配置注入方式,对静态变量也是有效的,但是springvalue对静态变量是无效的,暂时没有去看spring的源码,不知道是实现方式的问题还是EL表达式的锅。

原本我以为是因为字段和方法的反射操作都是基于类的实例,所以对于静态方法和变量是没有任何效果的,但是经过实测的时候,发现并非如此,后面再好好研究下。

下面是项目的开源仓库,有兴趣的小伙伴可以去看看,如果有想法的小伙伴,我真心推荐你自己动个手,自己写一下,真的感觉不错:

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

posted @ 2021-06-09 13:11  云中志  阅读(211)  评论(0编辑  收藏  举报