springboot(4.1) springIOC

springIOC基础知识

spring家族包括很多产品和组件,比如spring-framework、springboot、springcloud等等,其中spring-framework是springboot的基础,而springboot又是springcloud的基础,本文就spring-framework5.x相关知识进行学习。本文主要以spring注解的方式进行学习和总结。

在spring-framework中,最为核心的组件为IOC和AOP,本文就IOC的基础知识进行学习和总结。文章下面所谓的spring 特指spring-framework。

IOC

IOC概念,是什么?

定义:IOC即依赖注入,将配置的对象及其所依赖的对象在系统启动时进行创建,并加载到spring的上下文中(准确的说是spring的bean工厂的单例池中),在需要使用时,直接从spring的上下文中获取对应的bean的过程就叫依赖注入。

为什么需要依赖注入?

一般在我们开发web项目时,需要为系统进行分层,如controller层,Service层,dao层,controller层依赖service层,service层依赖dao层,如果不使用spring的依赖注入,则当我们创建一个controller类的实例时,需要先创建一个service类实例,而创建一个service类实例时,我们需要先创建一个dao类实例,创建同一个controller类的另外一个实例时,也需要这同一个过程;如果创建N个controller类实例时,工作量将会进一步加大,大大的加重了开发人员的负担。

使用spring进行依赖注入时,我们需要将spring管理的类及其依赖进行相关配置(包括xml方式和注解方式),在spring启动时由spring负责创建和管理类及其类之间的依赖关系。

被spring创建并管理的类对象称为spring bean。

当我们需要某个bean时,直接从spring中获取,而不需要程序员自己去创建和管理,从而减轻开发人员的负担。

怎么做,即如何进行依赖注入?

依赖注入的方式:

  • setter注入
  • 构造器注入

注意,如果使用setter注入,必须为类提供一个无参构造方法和对应的setter、getter方法,因为spring在使用setter注入时,是先创建对象在调用setter方法设置属性值。

在注入类时,可以使用xml配置文件的方式进行(目前用得较少了),也可以使用注解的方式进行,如@Controller、@RestController、@Service、@Component等。

名词解释

  1. spring上下文:是spring中最大的内存单元,里面包含了spring的各种组件,如beanFactory、BeanFactoryPostProcessor池等
  2. spring的beanFactory:是spring上下文中重要的组件之一,里面包含了单例池、beanDefinetionMap以及各种BeanPostProcessor后置处理器。我们常说的IOC容器指的就是它。
  3. spring的单例池:是spring的bean工厂中重要的组件之一,我们用@Controller等注解的类最终会生成一个springbean,并存储在这个单例池中
  4. spring的BeanFactoryPostProcessor:它是spring上下文中的重要组件之一,通过实现BeanFactoryPostProcessor接口,并重写相关方法,可以获取并重新设置BeanDefinition对象。spring扫描、加载路径下的类就是该接口的一个实现类完成的。
  5. spring的BeanPostProcessor:它是spring的beanFactory中的重要组件之一,通过它,可以完成类的实例化、属性设置和注入、代理设置等一系列的工作。

相关名称的关系对应,如下图所示:
在这里插入图片描述

spring-framework 加载Javabean到IOC容器成为springbean过程

spring-framework是如何将配置和注解的类加载到spring容器中,并成为springbean的呢?
即如下代码执行的过程是什么呢?


@ComponentScan("com.xx")
public class MyApplication {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext configApplicationContext=new AnnotationConfigApplicationContext(MyApplication.class);
    }
}

总体说来,spring将注解的类加载到spring容器中,使之成为springbean,需要经历如下过程:

  • 首先将MyApplication类进行扫描和解析,生成BeanDefinition
  • 初始化spring上下文以及spring的beanFactory等组件
  • 扫描并加载类:扫描某些路径下的所有类,并将扫描到的类用classloader加载到内存。
    如用@ComponentScan注解进行扫描路径的指定,如果是springboot项目,默认扫描main方法所在类路径及其子路径下的所有类
  • 生成并缓存类的BeanDefinition对象:为扫描并加载到的每个类,生成一个BeanDefinition定义描述对象,
    并放到beanFactory的beanDefinetionMap中通过阅读源码,发现扫描、加载类,以及生成类的BeanDefinition对象,
    是通过一个叫ConfigurationClassPostProcessor的后置处理器来完成的。
  • 初始化事件广播器,并向其添加各种需要事件监听
  • 对象的实例化,这系列的操作主要是通过spring的各个BeanPostProcessor来完成的

spring从启动到启动完成,整个过程如下图所示:

在这里插入图片描述

spring处理循环依赖

在spring中,默认支持单例的循环依赖,也可以通过修改BeanFactory中allowCircularReferences属性的值,使程序不支持单例的循环依赖。

假设程序中有类A,需要注入属性B,而B类又需要注入属性A,这样就形成了循环的场景。

那么spring是怎么解决循环依赖的呢?具体见下图说明。
在这里插入图片描述

注意:上图中只是列出了spring是如何解决循环依赖的大概步骤,事实上在spring中解决循环依赖比图中描述的复杂得多。

执行各个BeanPostProcessor

那么默认情况下,spring为我们提供了如下几个BeanPostProcessor:

  1. org.springframework.context.support.ApplicationContextAwareProcessor:回调Aware子类的相关方法,如ApplicationContextAware的setApplicationContext方法等是BeanPostProcessor的直接子类

  2. org.springframework.context.annotation.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor:处理@Import注解相关事宜,是InstantiationAwareBeanPostProcessor和SmartInstantiationAwareBeanPostProcessor的子类

  3. org.springframework.context.support.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:对bean进行校验

  4. org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator:完成springAOP的BeanPostProcessor,是InstantiationAwareBeanPostProcessor和SmartInstantiationAwareBeanPostProcessor的子类

  5. org.springframework.context.annotation.CommonAnnotationBeanPostProcessor:对@PostConstruct和@PreDestroy注解的回调处理,对@Resource注解的注入处理是InstantiationAwareBeanPostProcessor和MergedBeanDefinitionPostProcessor的子类

  6. org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor:对@Autowired注解的注入处理
    是InstantiationAwareBeanPostProcessor、SmartInstantiationAwareBeanPostProcessor和MergedBeanDefinitionPostProcessor的子类

  7. org.springframework.context.support.ApplicationListenerDetector:如果bean实现了ApplicationListener,则将其添加到监听器中
    是MergedBeanDefinitionPostProcessor的子类

spring执行类的实例化过程比较复杂,主要是利用各种BeanPostProcessor的子类来完成,在实例化bean的过程中,依次执行如下步骤:

  1. InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation
  2. SmartInstantiationAwareBeanPostProcessor的determineCandidateConstructors 获取构造函数,并选择合适的构造函数并缓存起来
  3. MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition
  4. InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation
  5. InstantiationAwareBeanPostProcessor的postProcessProperties
  6. BeanPostProcessor的postProcessBeforeInitialization
  7. BeanPostProcessor的postProcessAfterInitialization

目前我看源码,只找到这几个,听说还有更多。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值