【源码Spring系列】——IOC设计理念以及自动装配原理

        凡是使用Spring的开发者都知道Spring中两大核心IOC和AOP,要问这两点,一般都会说IOC实现控制反转,AOP实现了面向切面编程。本文主要讲解IOC,所以深入提问IOC归根结底解决的是什么问题,通过何种方式实现,控制反转是从何方转向何处呢?IOC和DI有什么关系?

没有IOC时,开发是什么样子?

当项目比较庞大的时候,这种开发存在什么问题?

1、上面案例中D会被重复创建

2、对象创建过程引用其他类多的情况时,对象缺少管理

3、从UML来讲,A 和 B、D的关系是组合关系,不可分割,属于强耦合关系。现实中B、D可能在A中发挥价值不大,并不是不可分割的关系,可能聚合关系更适合

在没有IOC的时候,怎么解决上述问题呢?

1、组合关系改成聚合关系,利用set,属性,构造器方式实现

2、利用单例模式,防止对象被重复创建

3、利用抽象工厂模式,使用反射机制,管理对象的创建

说的这些解决方案,其实基本上就是IOC最基础的原理了。这也为什么单例设计模式,以及反射,工厂模式等在面试中额外重要的原因。

IOC容器的设计理念

This chapter covers the Spring Framework implementation of the Inversion of Control (IoC) principle. IoC is also known as dependency injection (DI). It is a process whereby objects define their dependencies (that is, the other objects they work with) only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean. This process is fundamentally the inverse (hence the name, Inversion of Control) of the bean itself controlling the instantiation or location of its dependencies by using direct construction of classes or a mechanism such as the Service Locator pattern.

IoC(Inversion of Control) 也称为依赖注入(dependency injection, DI)。它是一个对象定义依赖关系的过程,也就是说,对象只通过构造函数参数、工厂方法的参数或对象实例构造或从工厂方法返回后在对象实例上设置的属性来定义它们所使用的其他对象。然后容器在创建bean时注入这些依赖项。这个过程基本上是bean的逆过程,因此称为控制反转(IoC)。

在Spring中,构成应用程序主干并由Spring IoC容器管理的对象称为bean。bean是由Spring IoC容器 实例化、组装和管理的对象。

IoC容器设计理念:通过容器统一对象的构建方式,并且自动维护对象的依赖关系。

结合上面的例子来阐述为什么是控制反转。例子中B的创建是因为A主动new,如果放到Spring中,利用IOC,IOC容器不管是否依赖关系,将所有可用装配的bean都放到容器中,B对象的创建从A改为由IOC创建,创建的控制权反转了。控制反转,说到底由对象自身决定,B是否可以创建,不会再因为A中是否存在new而决定。一般通常配合出现的还有DI依赖注入,A需B怎么办,依赖注入。A在容器中拿到B,进而可以正常使用。

上面例子使用IOC之后的关系图

PS:注意分区两图中箭头的方向,图1中是被动创建,图2中是主动注入

回答下开头的问题

1、控制反转是从何方转向何处 ?

对象从被其他使用而创建,改为主动创建。如果其他对象需要,依靠的DI,从容器中拿取

2、IOC和DI有什么关系?

IOC是设计思想,那么DI依赖注入就是IOC的实现,如果A无法拿到B,那么程序是无法正常运行的。所以IOC和DI总是一起出现的。

IOC的应用——bean是如何装配到容器中的?

早期bean的装配方式 xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="user"  class="mandy.spring.com.bean.User" />
</beans>
 @Test
    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
        System.out.println(context.getBean("user"));
    }

最后的表现就是通过xml创建了一个user对象,那么在spring中整个创建过程是如何呢?

图解自动装配原理

模拟自动装配代码流程

@Test
    public void testXml() {
        //资源加载器
        ResourceLoader resourceLoader = new DefaultResourceLoader();
        //获取资源
        Resource resource = resourceLoader.getResource("spring.xml");

        //注册器  
        //ioc最最最核心的类 DefaultListableBeanFactory
        BeanDefinitionRegistry registry = new DefaultListableBeanFactory();
        
        //读取器
        BeanDefinitionReader reader = new XmlBeanDefinitionReader(registry);

        //读取资源
        reader.loadBeanDefinitions(resource);

        //读取到的资源bean
        for (String beanDefinitionName : registry.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }
        
        //反射创建bean user
        System.out.println(((DefaultListableBeanFactory) registry).getBean("user"));
    }

解释下BeanDefinition是什么?

在创建的bean的时候每个bean虽然都是Object,但是bean各自有些属性,例如beanName,构造方法,scope等等,如何保证创建的每个bean与定义的相符呢?BeanDefinition就是用于存储bean的元数据,最后反射创建就是BeanDefinition中存储的元数据完成createBean。理论上Bean和BeanDefinition是一一对应的关系,即存在一个BeanDefinition则存在一个Bean对象,但是存在特殊情况,这个特殊情况会在后面的博客中更新(小神秘啊,连载记得追啊,😝)。

搞明白了BeanDefinition就理解为什么IOC过程中有个BeanDefinitionRegistry 注册器,本质上就是管理BeanDefinition的CRUD。

总结

       IOC过程的本质其实很简单,就是为了解决对象管理问题,整个IOC过程中首先就是自动装配,所谓装配加载资源解析资源创建bean,然后整个过程就结束了。本文讲解的IOC设计理念以及自动装配的原理,但是除此之外Spring中还有很多内容值得去探索。bean的装配方式,bean的创建过程是如何保证单例,在创建过程中经常遇到的BeanFactory和FactoryBean又有什么不同,又是如何完成的依赖注入等等。所以一起学习哟!

                                                 漫漫长途,终有回转;余味苦涩,终有回甘

                                                             Trying to light up the dark

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mandy_i

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值