内容简介:本篇是《跟我猜Spring-Boot》系列的第2篇(Oh,我竟然已经写了10篇了,真不容易)。在上一篇中,我们实现了我们之前已经在工程中定义了
引&目标
本篇是《跟我猜Spring-Boot》系列的第2篇(Oh,我竟然已经写了10篇了,真不容易)。
在上一篇中,我们实现了 Bean 的创建,但是仅仅是创建而已,并没有真正的实现Bean的注入。那么在今天这篇中,我们要去实现bean的自动注入。
我们之前已经在工程中定义了 SimpleService
和 SimpleController
这两个类,那么这篇文章,我们要把 SimpleService
自动注入到 SimpleController
中;
SimpleController.java
因为目前只是一个控制台程序,没办法进行真正的调用和展示,所以我给 SimpleService
加一个输出,用来表示这个类的的唯一性。这样, SimpleService
就变成了这样:
SimpleService.java
现在虽然有了调用,但是还是没有办法去验证我们的想法。
干脆,将计就计,我们再加上一个 PostContruct
的注解吧 :)
SimpleController.java
依赖注入的需求分析
由我们目标程序的更改,可以看出我们这次对 mini-boot
的更改主要在如下几点:
-
定义
PostConstruct
和Autowired
-
以
Autowired
为标记,实现依赖注入 -
以
PostContruct
为标记,实现Bean在创建的自动初始化
以3条是我们这次要实现的直观目标,然而,由于我们之间 过于简单 的设计,我们有一个问题要解决,即:
我们需要有地方可以存储,查找已经已经生的bean !
那么这个问题显然要比1,2,3条更重要一些,于是
前文挖坑,后文填坑
我们的目标变成了:
-
实现Bean的存储和管理
-
定义
PostConstruct
和Autowired
-
以
Autowired
为标记,实现依赖注入 -
以
PostContruct
为标记,实现Bean在创建的自动初始化
Step 0 Bean的存储和管理
在Spring中,从外部得到一个bean 方式下:
-
通过依赖注入或其他方式得到
ApplicationContext
-
通过
ApplicationContext.getBean
来得到相应的bean.
通过这两条,显而易见:
-
我们也照般一个
ApplicationContext
-
而通过类名或类拿到bean这种逻辑,显然是一个map.这样,我们的
ApplicationContext
变得很好实现:
ApplicationContext.java
嗯,有了 ApplicationContext
之后,我们就可以在生成bean的同时用一个applicationContext把所有的bean都保存起来。这时,我们的 Application.loadBeans
的函数有了一点点变化:
Application.loadBeans
可以看到,这时的变化还很小,我们只是在开始初始化了一个context ,然后在bean生成后,将bean保存在context中
OK,保存bean的功能完成了(只是把前人的坑填了而已),下一步要开始我们正式的工作了。
Step1 定义Annotation
之前已经分析了,我们需要定义 Autowired
和 PostContruct
两个注解,都简单的很,做一下声明即可:
Autowired.java
PostConstruct.java
同样注意,我们在这里要加入 @Retention(RetentionPolicy.RUNTIME)
这一行,具体的功能和区别,咱会找机会详解(又在挖坑,不挖不舒服基)
Step2 以@Autowired为标记,实现依赖注入
嗯,我们要进行最激动人心的部分了,实现依赖注入,即我们要将 SimpleService
自动 注入 到 SimpleController
中。
But ....
一切已经非常水到渠成了,又双叒叕有什么好激动的?我们要做的无非就是:
-
把所有的bean从context里取出来;
-
用反射得到bean的每一个字段;
-
检查这个字段有没有加autowird注解;
-
如果有,检查这个字段类型是不是一个bean;
-
如果是,取出来用反射进行赋值;
因为我们用的是Map进行的存储,所以4,5两步可以合并为:
4-5. 按这个字段类型取到bean,如果不为空,就赋值。
因为想的清楚,代码自然一气呵成,即在 Application.loadBeans
后面增加这个注入的逻辑:
Application.loadBeans
同时,我们为ApplicationContext加了一个新的方法,用来得到所有的bean
ApplicationContext.java
注意这里面有一个点,即Applicaton.loadBeans我们循环了两次:
-
第一次是生成bean并存储
-
第二次是将所有的bean取出来,用依赖注入的形式为每个bean进行赋值
这样做的原因也很明显:
为了保证在注入时可以拿到我们想要的bean,必须在所有的bean都生成后进行处理
Step3 以@PostConstruct为标记,实现初始化方法的自动运行
到上一步,我们的依赖注入实际上已经完成了,但是由于目前我们 mini-boot
这个框架太简单了,根本没办法验证我们成功与否。
所以,我们在这里顺带将@PostContruct的机制也实现一下,即类加载后的自动初始化。
有了上一步的工作,你会发现,我们这次的工作变得非常程式化和无味了,即:
-
把所有的bean从context里取出来;
-
用反射得到bean的每一个 方法 ;
-
检查这个 方法 有没有加 PostContruct 注解;
-
如果有, 使用反射执行这个方法 ;
你一定会注意到,这里我有一些字体是标粗的,标粗的原因是因为:这里的1-4是 我从上面复制下来的,标粗的只是更改的部分 。
即然实现思路都能复制,那么代码也变得很容易了。
Application.loadBeans
OK ,现在编译工程,执行,你会看到如下输出:
这个输出中:
-
第一行是controller自动创建
-
第二行表时service自动创建,并且唯一id 是 xxxx
-
第三行是我们的controller 中init函数的输出,可以看到 这里service 已经不为空了,并且就是我们之间自动创建的那个!
也就是说:
-
我们已经按照预期实现了简单的自动注入
-
我们同时按照预期实现了简单的自动运行初始化函数
现在,静静的回想一下我们此文的内容,是否有某扇大门,已经向您敞开
其他
不给源码的分享都是耍流氓!
所以,我们的项目地址是:https://github.com/yfge/mini-boot 由于,随着文章的发布,本代码会不停的更新,所以,本章的tag是 : article-02
(原谅我起名字的水平)
关于老拐瘦
-
散养程序猿,野生架构狮
-
二流搬砖工,三流摄影师
-
假正经真逗比,装文艺实二逼
所以,这么一个公众号里,会有代码,有段子,有美图,有鸡汤,反正,乱七八遭的,没准碰上哪个刚好就烦到您了呢
啥也不说,扫码关注吧
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 跟我猜 Spring Boot:bean 的注入
- 我猜你需要这个Python调试工具
- iOS 小游戏项目——你话我猜升级版
- 跟我猜 spring-boot: bean 的创建
- 跟我猜 spring-boot: bean 的创建
- 跟我猜 Spring Boot:第一次优化 (bean 的加载)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。