Spring IOC底层分析

IOC初始化

  • IOC容器的初始化分为三个过程以及我们在使用spring时的代码对应(不是完全一一对应,这是顶层的方法,内部有较多的细节):
    1.Resource定位:ClassPathReource resource = new ClassPathReource(“bean.xml”);
    2.BeanDefinition的载入和解析: DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); , XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
    3.BeanDefinition注册: reader.loadBeanDefinition(resource);
    4.怎么理解BeanDefinition,可以将BeanDefinition在IOC初始化的地位看做是JVM中类的Class对象在类初始化中的地位,虽然二者没什么关系,但是好理解一些.

  • Reource定位
    1.主要是两个接口:ResourceSpring中的统一资源抽象接口;ResourceLoader是统一的资源加载抽象接口
    2.具体的方法实现不细说,只需要知道接口的具体实现类会将外部的资源加载到Spring中,当然是以被封装的形式存在.(resource->EncodedResource).最后会以EncodedResource对象的形式用于bean的后续初始化.

  • BeanDefinition的载入和解析
    1.EncodedResource并不是直接就转换成BeanDefinition对象,而是要先转换成Document对象,然后再转换为BeanDefinition对象.这样做的原因也很简单,就是Document更方便.
    2.从EncodedResource到Document的转换过程有很多细节(比如文件解析器,错误处理,命名空间的问题),这里暂时将这个过程看做黑盒.
    3.Document -> BeanDefinition的过程其实主要是和对Document的操作有关,也就是对xml标签的处理,有默认标签和自定义标签,不详细说.

  • 注册BeanDefinition
    1.IOC是什么?在逻辑定义层面有很多形象通俗的解释,我见过最好的一篇是这个,这里我们说一下代码层面的,代码层面的IOC容器其实就是一些Map,有存储BeanDefinition的Map,有存储实例化后的单例Bean的Map等等.这里先说一下存储BeanDefinition的Map.
    2.这是一个ConcurrentHashMap,源代码如下:
    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
    所谓注册,就是添加进入这个Map的过程,这里的key是beanName;

  • 初始化的过程就是这样,用一张图结束吧:
    在这里插入图片描述

Bean实例化

  • 实例化时机分为很多种,一是使用BeanFactory和ApplicationContext的区别,二是Bean单例和多例的区别,三是单例情况下设置延迟加载的区别;
  • 如果是非延迟加载,那么会在容器启动时实例化bean.
  • 如果是延迟加载,那么Bean的加载就是第一次显示或隐式的调用getBean方法(该方法调用doGetBean方法),所以从这个方法开始:
    1.转换beanName,因为getBean传入的name不一定是beanName,可能传入的是aliasName或FactoryBean
    2.从缓存中获取bean,这里需要根据bean的作用域分一下情况:
    2.1 单例:spring的IOC只会保存一个对象实例,所有该对象的引用都共享这个实例,Spring容器只会创建唯一一个实例,保存在缓存中,并对该bean的后续请求和引用都会返回到该缓存的对象实例中.
    2.2 多例:每次对bean的请求都会返回一个新的实例
    2.3.1 request : 每次http请求都会有一个bean实例
    2.3.2 session: 一个session中,一个bean定义对应一个bean实例
    2.4 所以,从缓存中获取的bean一定是单例的,这里的缓存也是一个Map,名为singletonObjects,同层次还有两个Map,一个是earlySingletonObjects,另一个是singletonFactories.分别保存早期单例对象和bean工厂.之所以使用三个缓存,是为了解决bean之间的循环依赖.
    3.缓存中没有找到的话,会在父容器的缓存中寻找
    4.如果没有父容器或者父容器中也没有就会创建bean实例对象.这里的方法是createBean
    4.1 如果createBean维持的一个缓存中没有对应bean的beanWrapper,这里会先创建BeanWrapper,这是一个对要实例化Bean的包装.创建BeanWrapper的方法是createBeanInstrance,同时,这个方法也是非单例bean的创建实例的方法.使用的就是初始化时创建的BeanDefinition,大致的步骤就是确定构造方法,然后实例化.实现起来有很多细节,比如如果有动态代理,就需要使用cglib来实例化,否则使用反射实例化.
    4.2 回到createBean方法,得到BeanWrapper对象后,就要进行一系列的处理,主要是属性注入和循环依赖的处理.然后初始化Bean.
    4.3 初始化Bean主要是为了完成用户设定,例如激活Aware方法,应用后置处理器方法,激活自定义的方法.
    5.得到了bean实例,但是并没有结束,无论是从单例缓存中获取的或者createBean中创建的bean,都只是bean实例,还需要从bean实例中获取对象.这里很难理解,bean实例难道不是对象吗,我看的博客中都是这样说的,但是从我的理解来看,这里的bean实例其实是FactoryBean实例,不知道FactoryBean的可以了解一下.总之,最后需要从FactoryBean中拿到对象,其实就是调用了getObject方法,不过框架嘛,你懂得,总是需要处理很多情况,所以嵌套的比较深,可以从getObjectForBeanInstance和getObjectFromFactoryBean两个方法入手自己看一下.
    6.主要的流程就是这样,但是旁支的东西数不胜数,代码远多于这些主线的内容,这里就主线内容说一下.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring IOC(Inversion of Control)的底层实现原理是基于反射和工厂模式的。 在 Spring IOC 中,当一个 Bean 被 Spring 容器创建时,Spring 会通过反射机制创建这个 Bean 的实例,并通过依赖注入的方式为这个 Bean 的属性赋值。在依赖注入的过程中,Spring 会检查这个 Bean 的依赖关系,如果发现依赖的 Bean 还没有被创建,Spring 会先创建依赖的 Bean,然后再为这个 Bean 的属性赋值。 Spring IOC 通过 BeanFactory 和 ApplicationContext 两个接口来实现。BeanFactory 是 Spring IOC 的核心接口,它定义了 Spring IOC 容器的基本功能,例如 Bean 的创建、依赖注入、生命周期管理等。ApplicationContext 是 BeanFactory 的子接口,它在 BeanFactory 的基础上增加了更多的功能,例如事件发布、国际化、资源管理等。 在 Spring IOC 中,Bean 的创建过程是由 BeanFactory 或 ApplicationContext 来完成的。BeanFactory 是延迟初始化的,也就是说,只有在获取 Bean 的时候才会创建 Bean。而 ApplicationContext 是预先初始化的,也就是说,在容器启动时就会创建所有的 Bean。 Spring IOC 通过工厂模式来创建 Bean。具体来说,Spring IOC 会先读取 Bean 的配置信息,然后根据配置信息创建 BeanDefinition 对象。BeanDefinition 定义了 Bean 的属性、依赖关系、生命周期等信息。然后,Spring IOC 会根据 BeanDefinition 来创建 Bean 实例,并将它们放入容器中。在创建 Bean 实例时,Spring IOC 会使用反射机制来调用 Bean 的构造方法,然后通过反射机制为 Bean 的属性赋值。 总的来说,Spring IOC底层实现原理是基于反射和工厂模式的。Spring IOC 通过反射机制创建 Bean 的实例,并通过工厂模式来管理 Bean 的创建、依赖注入、生命周期等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值