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服务器:定义Configuration和Bean注解,实现更灵活的类注入

前言

前几天,我们实现了Service注解,解决了类注入的问题(component注解后面实现,这个就很简单了),但是这种方式不够灵活,比如我们要实现某些属性的赋值,或者其他特殊的构建方法,这些注解就不够灵活了,为了解决这个问题,spring提供了Configuration注解和Bean注解,今天我们就参照这两个注解的功用,用我自己的方式来实现这两个注解,让我们的类注入更灵活。

话不多说,直接开始。

实现过程

定义注解

configuration注解,我们从一开始就在写注解,所以到现在都是闭着眼睛写的,so easy

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Configuration {
}

Bean注解

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

核心实现

我们说的核心实现,主要是指这两个注解的使用,因为Bean注解的作用是创建对象,所以必须在服务器启动前完成创建,但是不能早于包扫描前,我们要在包扫描完成后进行:

// 扫描包
componentScanInit(aClass);
// 初始化配置类
initConfiguration();

我们看下配置类初始化里面是如何实现的:

	/**
     * 初始化配置类
     */
private static void initConfiguration() {
    classSet.forEach(c -> {
        try {
            if (hasAnnotation(c, Configuration.class)) {
                Method[] methods = c.getMethods();
                Object o = c.newInstance();
                for (Method method : methods) {
                    Bean annotation = method.getAnnotation(Bean.class);
                    if (Objects.nonNull(annotation)) {
                        Object invoke = method.invoke(o);
                        contentMap.put(method.getReturnType().getName(), invoke);
                    }
                }
            }
        } catch (Exception e) {
            logger.error("扫描配置类错误", e);
        }
    });
}

这里也很简单,就是循环遍历我们的包扫描结果,拿出有Configuration注解的类,然后找到有Bean注解的方法,运行方法,把方法运行结果放进我们的Ioc容器即可。

简单应用

我们有这样一个类,我们需要通过BeanConfiguration注解来实现更灵活的类注入

public class TestBean {
    private String name;
    private int age;

    public TestBean() {
    }

    public TestBean(String name) {
        System.out.println("create bean, " + name);
    }
    public void testBean() {
        System.out.println(this);
        System.out.println("hello bean");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "TestBean{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

我们的配置类:

@Configuration
public class TestConfig {
    @Bean
    public TestBean testBean() {
        TestBean testBean = new TestBean();
        testBean.setAge(18);
        testBean.setName("云中志");
        return testBean;
    }
}

测试

我们在Controller中注入testBean:

@Controller
public class Test2Controller {

    @Autowired
    private TestService service;

    @Autowired
    private TestBean testBean;

    @RequestMapping("/testAutowire")
    public String testAutowire(@RequestParameter("name") String name){
        testBean.testBean();
        return service.helloIoc(name);
    }
}

然后,我们前端访问下看下效果:

配置类中的属性也已经被注入进来了,这种方式的好处就是比较灵活,你可以根据自己的需要调用对应的方法,实现符合你需求的构建方式,是不是很简单呀!

总结

今天的内容总体来说还是比较简单的,核心的点就是注解的解析和方法的反射调用,当然难点也是有的,你要在实现之前考虑好思路,因为代码本身只是思路的表达,所以在我的认知理解中,我觉得合格的软件工程师,首先得是个合格的架构师和设计师,否则你真的是能当个小码农了,遇到需求的时候,先想想如果让你来做,你会如何实现,而不是考虑该不该你来做,每一次你排斥的事情,其实对你而言,都是一次机会,重要的是你如何看待它。

好了,今天的内容就到这里吧。

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

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

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