漫谈Spring原理之IOC

漫淡Spring原理之IOC

IOC是什么?

IOC ---- Inversion Of Control 即 控制反转 。要理解IOC究竟是何物,我们首先要抛出两个问题:

  1. 控制什么? 在非IOC设计思想的框架中,对象的创建是由调用方来决定的。比如我们想要一个ObjectA,那么需要传入ObjectA所需的一切资源来创建一个它,这种情况就可以说我们控制了对象创建的权利
    class I{
    	private 铸剑师 欧冶子 ;
    	private 材料 玄铁;
    	private 材料 龙葵;
    	剑 魔剑 = new(欧冶子,玄铁,龙葵);
    
    	public void 斩妖除魔(剑 魔剑){
    		魔剑.kill();
    	}
    }
    
  2. 什么反转了? 控制对象创建的权利被反转了,对象不再由我们人来创建,而是由第三方容器接管,此时我们想要一个ObjectA,只需跟容器“说一声”我们想要哪个对象,就可以拿到了。
    class I{
    	// 向容器索取所需对象
    	@Autowired
    	private 剑 魔剑;
    
    	public void 斩妖除魔(剑 魔剑){
    		魔剑.kill();
    	}
    }
    

经由上面两段伪代码,相信大家已经能够看出来控制反转给我们带来了什么好处。有了IOC容器就可以将组件的创建和我们的业务代码解耦,程序员只需关心业务代码,不再需要维护组件的创建。相当于我们去斩妖除魔的时候,只需要喊一声“剑来!”,打铁铸剑什么的就交给专业的人去做吧。

DI是什么?

DI ---- Dependency Injection 即 依赖注入 。与IOC一样,我们同样首先抛出两个问题:

  1. 何为依赖? ObjectA这个对象中,使用到了另一个对象ObjectB,就叫做ObjectA依赖ObjectB。

    Class I{
    	private 剑 魔剑;
    }
    
  2. 何为注入? 有了IOC容器以后,当ObjectA使用了ObjectB的时候,只需要喊一声我要“ObjectB”就有了,那么问题就来了:ObjectB是哪来的?答案就是我们在容器中定义一个ObjectB,并给它赋值的这个过程就是注入。

从上述可得:正是由于有了控制反转,把对象的创建交给容器管理的这种能力,才有了依赖注入的功能

但是,依赖注入同样带来了一个新的挑战 ---------> 循环依赖

循环依赖

什么是循环依赖?

Class 剑 {
	private 铸剑师 欧冶子;
	private 材料 玄铁;
	private 材料 龙葵;
}
Class 铸剑师 {
	private 剑 魔剑;
}

如何解决循环依赖?

IOC使用了三级缓存的策略解决了这个问题。三级缓存分别是:

  1. 一级缓存:单例缓存池singletonObjects
  2. 二级缓存:早期提前暴露的对象缓存earlySingletonObjects
  3. 三级缓存:singletonFactories单例对象工厂缓存

有了三级缓存,spring IOC到底是如何用的呢?我们从spring源码及流程图来看:
spring循环依赖的数据流程图

  1. getBean
  2. doGetBean
  3. getSingleton
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		// 从单例缓存池中获取bean的实例,但是第一次进来这个实例一定是不存在的。
        Object singletonObject = this.singletonObjects.get(beanName);
        // 判断bean实例不存在的同时,再判断当前对象是否正在创建
        if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
            synchronized(this.singletonObjects) {
            	// 以上条件均为true,从二级缓存早期单例对象池里获取
                singletonObject = this.earlySingletonObjects.get(beanName);
                /** 如果仍未获取到,再判断是否允许从单例工厂对象缓存中去获取
				*   allowEarlyReference 这个参数默认为true
				*/
                if (singletonObject == null && allowEarlyReference) {
                	// 从单例工厂缓存池中获取获取单例工厂
                    ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                    	// 如果单例工厂不为空,获取对象,然后将对象从三级缓存中移除并加入到二级缓存中
                        singletonObject = singletonFactory.getObject();
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }

        return singletonObject;
    }
  1. createBean
	protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
        
        RootBeanDefinition mbdToUse = mbd;
        // 根据bean定义和beanName来解析class
        Class<?> resolvedClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
        if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
            mbdToUse = new RootBeanDefinition(mbd);
            mbdToUse.setBeanClass(resolvedClass);
        }

        try {
        	// 给bean的后置处理器一个机会来生成一个代理对象返回 
            mbdToUse.prepareMethodOverrides();
        } catch (BeanDefinitionValidationException var9) {
            throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", var9);
        }

        Object beanInstance;
        try {
        	/** 创建Bean前执行,去代理AOPBean定义注册信息。此时Bean并未被创建,
        	*   所以代理的只是Bean定义的信息。在这里把Bean定义信息放进缓存中,
        	*   以便我要代理真正的对象时,直接从缓存中读取。
        	*/
            beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);
            if (beanInstance != null) {
                return beanInstance;
            }
        } catch (Throwable var10) {
            throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", var10);
        }

        try {
        	// 真正进行主要业务逻辑方法来创建bean的地方
            beanInstance = this.doCreateBean(beanName, mbdToUse, args);
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("Finished creating instance of bean '" + beanName + "'");
            }

            return beanInstance;
        } catch (ImplicitlyAppearedSingletonException | BeanCreationException var7) {
            throw var7;
        } catch (Throwable var8) {
            throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", var8);
        }
    }
  1. doCreateBean
	protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
        }
		
		// 调用构造方法,创建Bean的实例
        if (instanceWrapper == null) {
        	/**
        	*	如果存在工厂方法则使用工厂方法进行初始化
        	* 	一个类由多个构造函数,每个构造函数都有不同的参数,所以需要根据参数锁定构造函数并进行初始化
        	* 	如果既不存在工厂方法也不存在带有参数的构造函数,则使用默认的构造函数进行Bean 的实例化
        	*/
            instanceWrapper = this.createBeanInstance(beanName, mbd, args);
        }

        Object bean = instanceWrapper.getWrappedInstance();
        Class<?> beanType = instanceWrapper.getWrappedClass();
        if (beanType != NullBean.class) {
            mbd.resolvedTargetType = beanType;
        }

        synchronized(mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                	// bean的后置处理器
                	// bean合并后的处理,@Autowired 注解正是通过此方法实现基于类型的预解析
                    this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                } catch (Throwable var17) {
                    throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", var17);
                }

                mbd.postProcessed = true;
            }
        }

		// 判断当前Bean是否需要暴露到缓存对象中
        boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
        if (earlySingletonExposure) {
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
            }

			// 暴露早期对象到缓存中用于解决依赖
            this.addSingletonFactory(beanName, () -> {
                return this.getEarlyBeanReference(beanName, mbd, bean);
            });
        }

        Object exposedObject = bean;

        try {
        	// 为当前的bean填充属性,循环依赖在此方法内解决!!! 
            this.populateBean(beanName, mbd, instanceWrapper);
            exposedObject = this.initializeBean(beanName, exposedObject, mbd);
        } catch (Throwable var18) {
            if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
                throw (BeanCreationException)var18;
            }

            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
        }

        if (earlySingletonExposure) {
        	// 去缓存中获取对象 只有bean 没有循环依赖 earlySingletonReference 才会为空
            Object earlySingletonReference = this.getSingleton(beanName, false);
            if (earlySingletonReference != null) {
            	// 检查当前的Bean 在初始化方法中没有被增强(代理)过
                if (exposedObject == bean) {
                    exposedObject = earlySingletonReference;
                } else if (!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {
                    String[] dependentBeans = this.getDependentBeans(beanName);
                    Set<String> actualDependentBeans = new LinkedHashSet(dependentBeans.length);
                    String[] var12 = dependentBeans;
                    int var13 = dependentBeans.length;

                    for(int var14 = 0; var14 < var13; ++var14) {
                        String dependentBean = var12[var14];
                        if (!this.removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                            actualDependentBeans.add(dependentBean);
                        }
                    }

                    if (!actualDependentBeans.isEmpty()) {
                        throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
                    }
                }
            }
        }

        try {
        	// 注册DisposableBean。  如果配置了destory-method,这里需要注册以便于销毁时调用
            this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
            return exposedObject;
        } catch (BeanDefinitionValidationException var16) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);
        }
    }

  1. createBeanInstance
	/**
	*	因为一个类可能由多个构造函数,所以需要根据配置文件中配置的参数或传入的参数来确定最终调用的构造函数。
	*	因为判断过程会比较,所以spring会将解析、确定好的构造函数缓存到BeanDefinition中的resolvedConstructorOrFactoryMethod字段中。
	*	在下次创建相同时直接从RootBeanDefinition中的属性resolvedConstructorOrFactoryMethod缓存的值获取,避免再次解析
	*/
	protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
        Class<?> beanClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
        if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
        } else {
            Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
            if (instanceSupplier != null) {
                return this.obtainFromSupplier(instanceSupplier, beanName);
            } 
            // 工厂方法不为空则使工厂方法初始化策略 也就是bean的配置过程中设置了 factory-method方法
            else if (mbd.getFactoryMethodName() != null) {
                return this.instantiateUsingFactoryMethod(beanName, mbd, args);
            } else {
                boolean resolved = false;
                boolean autowireNecessary = false;
                if (args == null) {
                	// 如果一缓存的解析的构造函数或者工厂方法不为空,则可以利用构造函数解析
                	// 因为需要根据参数确认到底使用哪个构造函数,该过程比较耗费性能,所以采用缓存机制
                    synchronized(mbd.constructorArgumentLock) {
                        if (mbd.resolvedConstructorOrFactoryMethod != null) {
                            resolved = true;
                            autowireNecessary = mbd.constructorArgumentsResolved;
                        }
                    }
                }

                if (resolved) {
                    return autowireNecessary ? this.autowireConstructor(beanName, mbd, (Constructor[])null, (Object[])null) : this.instantiateBean(beanName, mbd);
                } else {
                    Constructor<?>[] ctors = this.determineConstructorsFromBeanPostProcessors(beanClass, beanName);
                    if (ctors == null && mbd.getResolvedAutowireMode() != 3 && !mbd.hasConstructorArgumentValues() && ObjectUtils.isEmpty(args)) {
                        ctors = mbd.getPreferredConstructors();
                        return ctors != null ? this.autowireConstructor(beanName, mbd, ctors, (Object[])null) : this.instantiateBean(beanName, mbd);
                    } else {
                        return this.autowireConstructor(beanName, mbd, ctors, args);
                    }
                }
            }
        }
    }

  1. addSingletonFactory
    protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(singletonFactory, "Singleton factory must not be null");
        synchronized(this.singletonObjects) {
            if (!this.singletonObjects.containsKey(beanName)) {
            	// 将创建好的bean放入三级缓存中,并移除早期暴露的对象
                this.singletonFactories.put(beanName, singletonFactory);
                this.earlySingletonObjects.remove(beanName);
                this.registeredSingletons.add(beanName);
            }
        }
    }
  1. populateBean
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {

	//从bean定义中获取属性列表
	PropertyValues pvs = mbd.getPropertyValues();

	if (bw == null) {
		if (!pvs.isEmpty()) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance"
			}
		else {
		//Skip property population phase for null instance. return;
		}
	}

	/*
	 * 在属性被填充前,给 InstantiationAwareBeanPostProcessor 类型的后置处理器一个修改
     * bean 状态的机会。官方的解释是:让用户可以自定义属性注入。比如用户实现一
     * 个 InstantiationAwareBeanPostProcessor 类型的后置处理器,并通过
	 * postProcessAfterInstantiation 方法向 bean 的成员变量注入自定义的信息。当然,如果无
	 * 特殊需求,直接使用配置中的信息注入即可。
	*/
	boolean continueWithPropertyPopulation = true;
	if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { 
		for (BeanPostProcessor bp :getBeanPostProcessors()) {
			if (bp instanceof InstantiationAwareBeanPostProcessor) { 
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; 
				if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
					continueWithPropertyPopulation = false;
					break;
				}
			}
		}
	}

	//上面返回为flase 表示你已经通过自己写的InstantiationAwareBeanPostProcessor 类型的处理器已经设置过bean的属性值了 
	if (!continueWithPropertyPopulation) {
		return;
	}

	/**
	 *  判断注入模型是不是byName 或者是byType的
	 */

		if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
			//封装属性列表
			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
			//若是基于byName自动转入的
			if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) { 
				autowireByName(beanName, mbd, bw, newPvs);
			}
			//计入byType自动注入的
			if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { 
				autowireByType(beanName, mbd, bw, newPvs);
			}

			//把处理过的属性覆盖原来的
			pvs = newPvs;
		}

	/**
	 *	判断有没有InstantiationAwareBeanPostProcessors类型的处理器
	 **/
	boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();

	/**
	*判断是否需要依赖检查(默认是0)
	*DEPENDENCY_CHECK_NONE(0) 不做检查
	*DEPENDENCY_CHECK_OBJECTS(1) 只检查对象引用
	*DEPENDENCY_CHECK_SIMPLE(2)检查简单属性
	*DEPENDENCY_CHECK_ALL(3)检查所有的
	**/
	boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);

	/*
	*这里又是一种后置处理,用于在 Spring 填充属性到 bean 对象前,对属性的值进行相应的处理,
	*比如可以修改某些属性的值。这时注入到 bean 中的值就不是配置文件中的内容了,
	*而是经过后置处理器修改后的内容
	*/

	if (hasInstAwareBpps || needsDepCheck) {
		//过滤出所有需要进行依赖检查的属性编辑器并且进行缓存起来
		PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
		//通过后置处理器来修改属性
		if (hasInstAwareBpps) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanNam if (pvs == null) {
					return;
				}
			}
		}
	}

	//需要检查的话,那么需要检查依赖
	if (needsDepCheck) {
		checkDependencies(beanName, mbd, filteredPds, pvs);
	}

	//设置属性到beanWapper中
	applyPropertyValues(beanName, mbd, bw, pvs);
}

1)获取了bw的属性列表

2)在属性列表中被填充的之前,通过InstantiationAwareBeanPostProcessor 对bw的属性进行修改

3)判断自动装配模型来判断是调用byTypeh还是byName

4)再次应用后置处理,用于动态修改属性列表 pvs 的内容

5)把属性设置到bw中

至此,我们已经把ioc解决循环依赖问题的步骤和源码讲完了。那么可能会有杠精来一句,然后呢?还不是面试造火箭,入职拧螺丝。那么下面我们就从使用的角度来谈一谈,学了IOC究竟有什么用!

IOC 容器的使用

  • Spring 和 MyBatis整合利用的就是Spring的扩展接口BeanFactoryPostProcessor接口
  • Spring 和 Eureka 利用的是SmartLifecycle接口
  • Spring 和 Nacos 利用的是ApplicationListener 接口
  • Spring 和 Ribbon 利用的就是 SmartInitializingSingleton 接口
  • Spring 整合 Sentinel 利用的就是BeanPostProcessor 接口
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值