IoC容器+依赖注入大大降低了对象间依赖管理的复杂性,给Java开发带来了极大的便利。我们的应用同样遵循这个设计思想。
考察OA系统中可能可用的IoC容器,发现都不适合我们:
- Spring IoC容器:Spring的版本为1.2.6,有IoC容器功能,但由于版本过早,不支持注解。
- OA系统自己的IoC容器
com.weaverboot.frame.ioc.container.WeaIocContainer:与OA系统各机制强相关,无法确定是否能保证我们应用的隔离性,有互相影响的风险。
其实我们需要的特性很简单:
- 只需要支持单例。
- 只需要按类型注入。
- 基于注解的Bean类扫描和依赖注入。
因此,我们自己实现IoC容器。
Component注解:具有此注解的具体类(非抽象类)将会作为Bean管理。
IoCContainer类:
- 使用
Map<Class<?>, Object> beanMap保存每个类对应的Bean实例。 - 使用Hutool(在OA系统的三方库中)的
ClassScanner扫描应用的包,对每个带有@Component注解的具体类,调用registerBean()注册Bean实例。 registerBean(Class<?> clazz)方法:先检查clazz在beanMap中是否存在,存在则不重复注册。不存在,则调用clazz的无参构造器创建Bean实例,并保存到beanMap中,然后调用injectDependencies()注入依赖。注意:这里要先保存到beanMap,再注入依赖,否则在循环依赖、自身依赖的场景下会无限递归。injectDependencies(Object object)方法:遍历object所在类及所有祖先类的实例属性,如果属性有@Resource注解,且属性值为null,则按属性的类型获取Bean实例,并设置为属性值。如果该类型对应的Bean实例不存在,则先调用registerBean()注册之。
应用启动时,会调用IoCContainer扫描、注册Bean实例,并注入依赖,完成IoC容器的初始化。