造一个方形轮子文章目录:造一个方形的轮子
01、先把车正过来
在上一篇《造一个方形的轮子3–控制反转》的最后提出了一个问题,如果同一个接口有一个以上的实现类,那么在初始化的时候,实现相同接口的BeanObject对象,后一个放入Map容器中时会把前边的覆盖掉,这样肯定有问题,简单处理一下,在BeanObject类中添加一个next指针引用,把他改造成一个可以支持链表的形式。
BeanObject.java 添加:
1 | //......上略 |
在原来的BeansInitUtil.loadClass()方法里修改以下代码:
1 | //......上略 |
可以看到在按接口全限定名保存容器时,由原来的直接保存改为先查询,如果原来有值(tmp不为空)说明已有其它实现类,被初始化,那么将当然beanObject的next指针指向原来保存的值就可以了(为什么要将当前beanObject的next指针指向已存在的tmp对象,而不是将tmp的next指针指向beanObject? )。
02、依赖注入准备
到目前为止bean的实例化已经完成了,现在把依赖注入的过程大概理一下:
1、找到每个bean中添加的注入注解的字段
2、按类型、接口、名称去容器中查找Bean实例
3、如果找到了且为一,则使用反射设值
4、如果没有找到或者找到多个没法确定使用哪一个,则抛出异常(启动失败)
好,先来实现第一步,改造一下BeanObject 把字段也保存起来,好在DI阶段使用,注解的这里就不自己实现了直接使用Java提供的@Resource
, @Resource
注解有一个name的字段,我们把他定义为指定的bean名字。
BeanObject.java 添加字段属性:
1 | //..... |
03、处理依赖注入
在BeansInitUtil.java中添加initDI()方法负责处理依赖注入:
1 | //....上略 |
看注释就可以了,基本就是按照上边说的逻辑一步一步做的,这里主要的关注点在,同一个接口有多个实现的时候,怎么去确认要注入的bean,上边代码里使用的是如果有多个实例则按需要注入字段的名字去匹配。
在BeansInitUtil.java的init()方法中添加调用initDI()。
1 | //...上略 |
04、验证依赖注入
为了验证效果我们先在com.jisuye.service包下添加几个类
ClassDI.java
1 | package com.jisuye.service; |
Def.java
1 | package com.jisuye.service; |
添加两个Def接口实现类
DefImpl.java
1 | package com.jisuye.service.impl; |
Def2Impl.java
1 | package com.jisuye.service.impl; |
修改AbcImpl.java(上一篇创建的类) 添加需要注入的引入
1 | package com.jisuye.service.impl; |
在SquareApplication.run()方法中添加调用查看注入是否成功
1 | public static void run(Class clzz, String[] args) { |
查看控制台输出:
1 | 20:42:07.749 [main] INFO com.jisuye.core.SquareApplication - beans size is:10 |
ok 可以看到对应的属性都已经注入成功
05、翻车时间
重新思考一下,上一篇只考虑了同一接口的不同实现类,会造成BeanObject覆盖问题,但其实按类型简称(不带包名)以及按注解上设置的Bean名字去初始化Bean的时候都会有覆盖问题,比如不同包下的相同的类,或者在注解上设置了相同Bean名字的类,想一下要怎么处理呢?
本篇代码地址: https://github.com/iuv/square/tree/square4
本文链接: http://blog.jisuye.com/2019/06/29/square4/
版权声明: 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!