IOC原理解读(二)

IOC原理解读(二)

继上篇

今天解读的是:

    基于xml配置的bean的IOC过程中的实例化跟依赖注入原理。

xml配置文件spring-bean.xml内容如下:

15253776-e8b063a0433d43c4.png

在加载完各个bean的definition到一个beanDefinitionMap后,是如何实例化bean呢?

先看看那些地方在需要获取bean definition,从这里找入口

1、查看获取definition的方法是哪被调用的

15253776-de7ab8982c954ecd.png

在AbstractBeanFactory类中看到具体调用

15253776-8199a051cad50709.png

然后在doGetBean方法中找到了

15253776-a364f4086a5b9b43.png
15253776-2a2f9889d2e9bed1.png

然后终于找到了 是AbstractBeanFactory 类中的 getBean(String name) 是真正调用的地方

15253776-4b46d21ea3694f79.png

然后在AbstractApplicationContext中找到了调用

15253776-fab057a6e9541ead.png

同类中调用

15253776-3e14fe3c9c0f79b3.png

同类中调用(beanFactory 在refresh方法中始终贯穿)

15253776-1e5cbc1b74e907de.png

看到这,我们大致知道了,实例化bean跟依赖注入的流程

Spring IoC容器对Bean定义资源的载入是从 AbstractApplicationContext 的 refresh() 函数开始的

refresh()是一个模板方法,refresh()函数的作用在于:在创建Ioc容器前,如果已经有容器存在,则需要把已有的容器销毁和关闭,以保证在refresh之后使用的是新建立起来的IoC容器。

refresh的作用类似于对IoC容器的重启,在新建立好的容器中对容器进行初始化,对Bean定义资源进行载入。

AbstractApplicationContext

15253776-e6a5f8aeb2993394.png

refresh中的具体步骤

1、准备刷新此上下文;

2、告诉子类刷新内部bean工厂;

3、准备bean工厂以便在此上下文中使用;

4、允许在上下文子类中对bean工厂进行后处理;

5、调用上下文中注册为bean的工厂处理器;

6、注册拦截bean创建的bean处理器;

7、为此上下文初始化消息源;

8、为此上下文初始化事件多主机;

9、初始化特定上下文子类中的其他特殊bean;

10、检查侦听器bean并注册它们;

11、实例化所有剩余(非lazy init)单例;

15253776-14ab25940f3503c7.png

   第二个参数false代表,这次加载的没有排除单例的bean定义,根据这些bean的名字,获取bean,实例化bean,并且在实例化过程中完成依赖注入

12、最后一步:发布对应事件;


下面我们看看具体是如何对bean进行实例化,然后完成依赖注入的

先看是如何完成所有需要实例化对象的实例化的

doGetBean方法

//这里是实际取得Bean的地方,也是触发依赖注入的地方

先不着急,看看具体实例化是如何操作的(也就是doGetBean())?逐个实例化

15253776-29830bf57963905c.png

如果有依赖的对象,那么将依赖的对象全部实例化!直到逐层依赖的对象,全部创建成功为止。

getBean是依赖注入的起点,之后会调用createBean,下面我们分析createBean的代码

15253776-7098aac84c236886.png

doCreateBean方法

15253776-1171bcd99cfaa8de.png

createBeanInstance方法

15253776-b17af0833f37c079.png

跟随上面的步伐,上面实例化的时候调用了instantiateBean方法,该方法代码如下:

15253776-0fc39ad887bfa54e.png

我们重点关注 getInstantiationStrategy() 这个方法,可以看到instantiateBean方法的功能实现是通过调用getInstantiationStrategy().instantiate方法实现的。 

getInstantiationStrategy 方法的作用是获得实例化的策略对象,也就是指通过哪种方案进行实例化的过程。继续跟踪下去我们可以发现,Spring当中提供了两种实例化方案: BeanUtils 和 Cglib 方式。

BeanUtils实现机制是通过Java的反射机制,Cglib是一个第三方类库采用的是一种字节码加强方式机制。 

Spring中采用的默认实例化策略是Cglib。 

重点关注如下方法

15253776-2d2908bd24e48a68.png

如果没有重写,则不要用cglib重写类

其他地方没有改变当前对象的方法逻辑(没有被重写)

存在重写的方法就用Cglib

为什么?

正确解释如下:跟lookup-method注入和replace-method注入有关 见:

https://www.smwenku.com/a/5b9959102b717757338f4b18/

https://blog.csdn.net/lyc_liyanchao/article/details/82432993


Java 反射机制 创建对象

15253776-96f30bc1aeeb6f4e.png

使用Cglib API 实例化对象

15253776-fab2b63bb5d7f819.png
15253776-1b94cfdf995b76c8.png

然后讲解注入依赖

看了上面的代码后,我们应该重点关注 createBeanInstance() 和 populateBean() 这两个方法。其中,populateBean() 开始 就是注入依赖

注入依赖

15253776-ee171521713c100d.png

1、填充bean对象

2、暴露对象;

15253776-e2d8c9b96b689db4.png

至此,终于完成了 实例化、依赖注入

猜你喜欢

转载自blog.csdn.net/weixin_34416649/article/details/87411079
今日推荐