参考自:https://blog.csdn.net/lj1314ailj/article/details/80517836
Spring中IOC容器的依赖注入主要有两种方式,一种是基于XML的依赖注入,一种是基于Annotation的依赖注入。接下来将对这两种依赖注入的方式进行分析,依赖注入的代码也比较复杂,所以还是分成几篇进行讲解。
一、依赖注入发生的时间
当 Spring IOC容器完成了Bean定义资源的定位、载入和解析注册以后,IOC 容器中已经管理类Bean定义的相关数据,但是此时IOC容器还没有对所管理的 Bean 进行依赖注入,依赖注入在以下两种情况发生:
(1).用户第一次通过 getBean 方法向 IOC 容索要 Bean 时,IOC 容器触发依赖注入。
(2).当用户在 Bean 定义资源中为元素配置了lazy-init属性,即让容器在解析注册 Bean 定义时进行预实例化,触发依赖注入。
BeanFactory 接口定义了 Spring IOC 容器的基本功能规范,是 Spring IOC 容器所应遵守的最底层和最基本的编程规范。BeanFactory 接口中定义了几个 getBean 方法,就是用户向 IOC 容器索取管理的Bean 的方法,我们通过分析其子类的具体实现,理解Spring IOC容器在用户索取Bean时如何完成依赖注入。 我们还是以FileSystemXmlApplicationContext为例调用getBean跟进代码!
ApplicationContext fileSystemXmlApplicationContext = new FileSystemXmlApplicationContext(xmlPath);
fileSystemXmlApplicationContext.getBean("");
跟进去我们发现 调用的是AbstractBeanFactory的getBean实现,至于为什么调用的是AbstractBeanFactory的子类。,其实我们在前面的文章中注册bean的有提到DefaultListableBeanFactory类,DefaultListableBeanFactory是AbstractBeanFactory的子类。下面给出DefaultListableBeanFactory类结构图。
二、AbstractBeanFactory通过getBean向IOC容器获取被管理的Bean
Spring中真正实现业务逻辑方法都以do开头,同理getBean方法真正由doGetBean()实现,图示如下:
图示中红色框分析(并不是依赖注入部分,只是在实例化依赖的bean):
1.registerDependentBean 保存依赖者和被依赖者的关系 存放在dependentBeanMap和dependenciesForBeanMap
2.对依赖的bean同样调用doGetBean(进入递归,此方法不结束,便不会创建bean)
图示中紫色框分析(上述红色框执行完毕,所依赖的对象也全部创建完毕):
1.单例对象的创建
2.原型对象的创建
图中其他部分分析,主要完成创建对象前的准备工作:
1.对bean名称的处理
2.父子beanDefinition的合并
3.单例对象从缓存的直接获取
通过上面对向IOC容器获取Bean方法的分析,我们可以看到在 Spring 中,如果 Bean 定义的单例模式(Singleton),则容器在创建之前先从缓存中查找,以确保整个容器中只存在一个实例对象。如果Bean定义的是原型模式(Prototype),则容器每次都会创建一个新的实例对象.除此之外,Bean 定义还可以扩展为指定其生命周期范围。上面的源码只是定义了根据Bean定义的模式,采取的不同创建 Bean 实例对象的策略,具体的 Bean实例对象的创建过程由实现了ObejctFactory 接口的匿名内部类的 createBean 方法完 成,ObejctFactory使用委派模式具体的Bean实例创 建过程交由其实现类AbstractAutowireCapableBeanFactory完成,我们继 续分析AbstractAutowireCapableBeanFactory的createBean方法的源码,理解其创建 Bean 实例的具体实现过程。