控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体,将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。
前言
以上这段是引用自维基百科的解释。在采用面向对象方法设计的系统中,所有的对象通过彼此间的合作,最终实现业务逻辑。所谓的控制反转,即是将我们代码里面需要实现的依赖对象创建及销毁工作交给一个容器来实现。Spring 框架的 IOC 是比较知名,也是应用较广泛的一个实现。之前花了段时间研究了下它的代码,然后为了好玩儿,自己造了一个简单轮子。
可能会有人问,你为什么又重复造轮子呢,已经有 Spring 框架可以用啦。我倒不认为重复造轮子是不好的,知道怎么造轮子,并且把轮子造出来对解决开发中遇见的问题是非常有帮助的。因为你知道它怎么实现的,自然就知道去哪里找解决问题的办法。我认为学习一个技术,不仅仅止步于用得熟练,更应该深究其原理和实现,从中得到启发就更好了。先透露下,我后面会再分享另外一个轮子叫 sunflower-mvc,很轻量级的一个框架,也会加入一些最佳实践,非常适合写 API应用。下面就进入今天的主题:
实现
今天我们要使用的方法便是依赖注入中的基于注解和set函数的方式。大致分为以下几个步骤:
- 定义注解类;
- 扫描指定包路径下的类;
- 分析注解和依赖关系并创建对象,注入依赖;
- BeanFactory 开放获取类实例的函数;
定义注解类
首先,我们定义两个注解@Bean
和@Resource
,前者用于标注一个对象需要容器管理,后者用于标注所依赖的对象。注解@Bean
的值不允许为空,@Resource
的值可以为空(则使用字段名称)。至于关于注解的语法,请自行查询相关资料。
扫描类
然后就是扫描指定包下的类,这段代码比较长,从 Spring 源码中直接拿过来复用的。总结来说,通过递归扫描指定包路径下的文件把你要进行依赖注入的所有Class加入一个Set集合中,后面会遍历这个集合并分析每个类的依赖关系。
依赖注入
接下来是分析注解和依赖并创建对象,注入依赖。
遍历类集合,如果检测到有@Bean
注解则实例化对象存放到Map中,然后继续扫描该类下的所有field,如果发现@Resource
注解则记录依赖值Map中。 然后遍历依赖关系Map,进行依赖注入。
BeanFactory
再提供一个函数用于从工厂中获取Bean对象。
测试
在com.mlongbo.sunflower.ioc.bean包中定义两个Bean: 最后再写个例子单元测试下:
结尾
至此,大功告成~ 如果有错误和需要完善的地方还请指正,也欢迎你到Github参与讨论。完整代码请查看 GitHub仓库。
点击 {链接},访问项目主页。
扫描二维码,关注我。
内容大多会是后端技术、前端工程、DevOps,偶尔会有一些大数据相关,会推荐一些好玩的东西。希望你会喜欢~
一切,源于喜欢。