Spring中的IOC深度解读

 更新时间:2023年09月15日 08:49:03   作者:猎户星座。  
这篇文章主要介绍了Spring中的IOC深度解读,spring容器会创建和组装好清单中的对象,然后将这些对象存放在spring容器中,当程序中需要使用的时候,可以到容器中查找获取,然后直接使用,需要的朋友可以参考下

spring容器

spring容器的概念,容器这个名字起的相当好,容器可以放很多东西,我们的程序启动的时候会创建spring容器,会给spring容器一个清单,清单中列出了需要创建的对象以及对象依赖关系,spring容器会创建和组装好清单中的对象,然后将这些对象存放在spring容器中,当程序中需要使用的时候,可以到容器中查找获取,然后直接使用。

IOC:控制反转

使用者之前使用B对象的时候都需要自己去创建和组装,而现在这些创建和组装都交给spring容器去给完成了,使用者只需要去spring容器中查找需要使用的对象就可以了;这个过程中B对象的创建和组装过程被反转了,之前是使用者自己主动去控制的,现在交给spring容器去创建和组装了,对象的构建过程被反转了,所以叫做控制反转;IOC是是面相对象编程中的一种设计原则,主要是为了降低系统代码的耦合度,让系统利于维护和扩展。

DI:依赖注入

依赖注入是spring容器中创建对象时给其设置依赖对象的方式,比如给spring一个清单,清单中列出了需要创建B对象以及其他的一些对象(可能包含了B类型中需要依赖对象),此时spring在创建B对象的时候,会看B对象需要依赖于哪些对象,然后去查找一下清单中有没有包含这些被依赖的对象,如果有就去将其创建好,然后将其传递给B对象;可能B需要依赖于很多对象,B创建之前完全不需要知道其他对象是否存在或者其他对象在哪里以及被他们是如何创建,而spring容器会将B依赖对象主动创建好并将其注入到B中去,比如spring容器创建B的时候,发现B需要依赖于A,那么spring容器在清单中找到A的定义并将其创建好之后,注入到B对象中。

spring中依赖注入主要分为手动注入和自动注入:

手动注入需要由程序员自己配置、描述好依赖关系,来实现自动注入(但是实际开发中手动装配的场景比较少,比如在缺少源码的情况下可能会使用这种手动装配情况)。

自动注入采用约定大于配置的方式来实现的,程序和spring容器之间约定好,遵守某一种都认同的规则,来实现自动注入。

DI:依赖注入的实现方式

分别是基于构造方法的依赖注入和基于setter(setXxxx(…))的依赖注入。

不管是手动装配还是自动装配都是基于这两种方式或者变体方式来的;但是这里一定要回答到主要和变体两个名词,因为有的注入方式就不是这两种,而是这两种其中一种的变体方式;比如在一个类的属性上面加@Autowired,这种方式注入属性的方式就是利用了java的反射知识,field.set(value,targetObject);关于这个我在后面的文章中对spring源码解析的时候会说明@Autowired的原理;所以@Autowired这种注入的方式是setter注入方式的一种变体

DI:依赖注入的自动装配模型

依赖注入是一个过程,主要通过setter或构造方法以及一些变体的方式完成把对象依赖、或者填充上的这个过程叫做依赖注入,不管手动装配还是自动装配都有这个过程;

手动装配通过ref标签来指定依赖关系,而自动装配没有显示的指定依赖关系,所以需要通过一些规则,来从容器中查找到符合条件的bean进行自动装配的工作,而自动装配模型就是完成自动装配依赖的手段体现。

每一种模型都使用了不同的技术去查找和填充bean;而从spring官网上面可以看到spring只提出了4中自动装配模型(严格意义上是三种、因为第一种是no,表示不使用自动装配、使用),这四个模型分别用一个整形来表示,存在spring的beanDefinition当中,任何一个类默认是no这个装配模型

我们可以在AutowireCapableBeanFactory类中看下这几种自动装配模型对应的整形分别是多少

public interface AutowireCapableBeanFactory extends BeanFactory {
	int AUTOWIRE_NO = 0;
	int AUTOWIRE_BY_NAME = 1;
	int AUTOWIRE_BY_TYPE = 2;
	int AUTOWIRE_CONSTRUCTOR = 3;
	@Deprecated
	int AUTOWIRE_AUTODETECT = 4;
}

@Autowired就是根据byType来进行自动装配

我们先抛出@Autowired的查找逻辑的结论:

首先spring根据类型去容器中找,找到了直接注入。如果根据类型找到了多个,那么spring不会立马异常,而是根据名字再去找,如果根据名字找到一个合理的则注入这个合理的。

如果没有找到,再根据名字去找,找到了则注入,没有找到则报异常。

我们再来用代码来验证下

定义一个空接口I,XY类分别实现I接口,Z类中注入I

public interface I {
}
package com.yj.service.impl;
import org.springframework.stereotype.Component;
import com.yj.service.I;
@Component("ix")
public class X implements I{
}
package com.yj.service.impl;
import org.springframework.stereotype.Component;
import com.yj.service.I;
@Component("iy")
public class Y implements I{
}
@Component
public class Z {
	@Autowired
	private I ix;
	public I getIx() {
		return ix;
	}
	public void setIx(I ix) {
		this.ix = ix;
	}
}

扫描配置类

package com.yj.conf;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.yj")
public class AppConfig {
}

MyBeanFactoryProcessor

package com.yj.conf;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.stereotype.Component;
@Component
public class MyBeanFactoryProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
            throws BeansException {
        AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition)beanFactory.getBeanDefinition("z");
        //beanDefinition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
        System.out.println("beanDefinition.getAutowireMode():"+beanDefinition.getAutowireMode());
    }
}

首先,我们可以观察到被@Autowired注解的z类的getAutowireMode值为0,不是2。而且我们如果手动将z类的AutowireMode设置为ByType,只是根据类型来查找的话,会查出XY两个bean,程序会报错的。

但是采用@Autowired默认的注入方式,是不会报错的,也就是说@Autowired的查找逻辑并不能简单的认为等价于ByType,@Autowired首先根据类型然后再根据名字去查找,完成bean注入的过程。

到此这篇关于Spring中的IOC深度解读的文章就介绍到这了,更多相关IOC深度解读内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • spring mvc4中相关注解的详细讲解教程

    spring mvc4中相关注解的详细讲解教程

    这篇文章主要给大家介绍了关于spring mvc4中相关注解的相关资料,其中详细介绍了关于@Controller、@RequestMapping、@RathVariable、@RequestParam及@RequestBody等等注解的相关内容,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-06-06
  • java创建线程池的7种实现方法

    java创建线程池的7种实现方法

    在Java中线程池是一种管理线程的机制,它可以创建一组线程并重复使用它们,避免了创建和销毁线程的开销,这篇文章主要给大家介绍了关于java创建线程池的7种实现方法,需要的朋友可以参考下
    2023-10-10
  • Java归并排序算法代码实现

    Java归并排序算法代码实现

    归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的,下面这篇文章主要给大家介绍了关于Java归并排序算法的相关资料,需要的朋友可以参考下
    2024-03-03
  • Spring Boot 2.0快速构建服务组件全步骤

    Spring Boot 2.0快速构建服务组件全步骤

    这篇文章主要给大家介绍了关于Spring Boot 2.0快速构建服务组件的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Spring Boot 2.0具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-04-04
  • 对比Java中的Comparable排序接口和Comparator比较器接口

    对比Java中的Comparable排序接口和Comparator比较器接口

    Comparable和Comparator接口都可用作普通意义上对象间的比大小,但两个接口在实例化方面的用法不尽相同,接下来我们就来详细对比Java中的Comparable排序接口和Comparator比较器接口
    2016-05-05
  • Jmeter生成UUID作为唯一标识符过程图解

    Jmeter生成UUID作为唯一标识符过程图解

    这篇文章主要介绍了Jmeter生成UUID作为唯一标识符过程图解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-08-08
  • java读写excel文件实现POI解析Excel的方法

    java读写excel文件实现POI解析Excel的方法

    在日常工作中,我们常常会进行Excel文件读写操作,这篇文章主要介绍了java读写excel文件实现POI解析Excel的方法,实例分析了java读写excel的技巧,非常具有实用价值,需要的朋友可以参考下
    2018-10-10
  • Springboot使用redis实现接口Api限流的实例

    Springboot使用redis实现接口Api限流的实例

    本文介绍的内容如题,就是利用redis实现接口的限流(某时间范围内,最大的访问次数),具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-07-07
  • Java httpcomponents发送get post请求代码实例

    Java httpcomponents发送get post请求代码实例

    这篇文章主要介绍了Java httpcomponents发送get post请求代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-09-09
  • SpringBoot使用Editor.md构建Markdown富文本编辑器示例

    SpringBoot使用Editor.md构建Markdown富文本编辑器示例

    这篇文章主要介绍了SpringBoot使用Editor.md构建Markdown富文本编辑器示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-03-03

最新评论