IOC容器

BeanFactory体系

在这里插入图片描述

先来一张图压压惊,由上图可见DefaultListableBeanFactory为集大成者,实现了所有接口,具备容器的基本功能,所以下文中提到的bean容器都指的是DefaultListableBeanFactory。下面对BeanFactory接口的继承体系简单进行介绍。

  • BeanFactory
bean 容器的顶级接口,该接口定义了容器提供的基本功能。getBean(String beanName)--->根据名称获取bean

注意:此处只提供了获取单个bean实例的功能

BeanFactory的直接子接口:
  HierarchicalBeanFactory,     ListableBeanFactory,      AutowireCapableBeanFactory
  • HierarchicalBeanFactory
具备分层能力的工厂,主要增加getParentBeanFactory()方法,所谓的父子容器
  • ListableBeanFactory
具备获取多个bean实例功能的工厂 ,主要增加
String [] getBeanNamesForType(Class<T> classType)--->获取bean容器中指定类型的bean名称集合,所谓面向接口,所以可能存在多个实现类的实例
Map<String,T> getBeanOfType(Class<T> classType)--->获取bean容器中指定类型的bean实例集合
  • AutowireCapableBeanFactory
具备装备能力的工厂,增加autowireBean(),createBean(Class<T> classType)...等相关方法

IOC源码解析

前置知识:
getBean步骤
  • 实例化 Instantiation
3种方式 :
###  Supplier接口 ()
###  静态工厂方法和工厂实例方法 (@Bean注解的方法会走这里哦)
###  ~有参构造 ~无参构造(一般是无参)
  • 属性填充 Population
注入属性,所谓DI(依赖注入)@Value @Autowired @Resource
  • 初始化 Initialization
此处会按顺序完成如下操作:
###	 invokeAwareMethods (各种回调)
###  postProcessBeforeInitialization (@PostConstruct)
 @PostConstruct会被 CommonAnnotationBeanPostProcessor---->InitDestroyAnnotationBeanPostProcessor #postProcessBeforeInitialization方法处理
###  afterPropertiesSet (InitializingBean)  , 然后init-method 
###  postProcessAfterInitialization (除循环依赖的AOP入口)
三级缓存
  • singletonObjects ---------- IOC容器

    Map singletonObjects = new ConcurrentHashMap<>(256)     --->    一级缓存
    
  • earlySingletonObjects ---------解决循环依赖的过渡容器

    Map earlySingletonObjects = new HashMap<>(16)    --->     二级缓存
    

注意: 正常的bean创建或者循环依赖(AB都不是代理对象)正常来说不需要二级缓存过渡的, 但是循环依赖中有代理对象的时候, 需要二级缓存缓存一下proxy对象,具体后续会讲到…

  • singletonFactories --------- 刚创建的对象放入的初始容器

    Map singletonFactories = new HashMap<>(16)			--->    三级缓存
    ###  存放的是ObjectFactory的匿名内部类实例, 一个获取提前暴露的单例bean引用的回调`getEarlyBeanReference()`,此处画重点,因为这个方法就是解决循环依赖中的代理对象的关键 
    
具体源码:
主流程getBean

此抽象类实现了getBean(),内部调用doGetBean(),该方法的主要处理流程如下:

######  AbstractBeanFactory (getBean的实现类)     代理就贴一些重要的地方出来了
protected <T> T doGetBean() {
  /*
   * 去掉name的前缀"&"
   * 从aliasMap中获取bean的原始名称  解决aliasA--->aliasB--->ABean多重别名的情况
   */
  final String beanName = transformedBeanName(name);

		// 一级缓存去获取bean
    /*
     *------------注意这是第一个getSingleton(beanName)方法------------11111111111111
     *	此时bean还未在创建状态,相当于去一级缓存拿bean , 肯定没有 返回null
     */
		Object sharedInstance = `getSingleton` (beanName);
  
    //存在的话直接返回
		if (sharedInstance != null && args == null) {
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}else {
      //不存在的话
      
      //这里去父容器里面拿 , 目前没有子父容器一说  只有一个容器 这里忽略
			BeanFactory parentBeanFactory = getParentBeanFactory();
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
          //重复dogetbean   一样的逻辑
					return ((AbstractBeanFactory) parentBeanFactory).doGetBean()
				}
      
      //-----------创建bean的地方-----------------
			try {
        //父类和子类的beandefinition合并
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
        //depend-on 循环依赖报错
				String[] dependsOn = mbd.getDependsOn();
				...throw new BeanCreationException

				// Create bean instance.
        /*
         *-----------此处是第二个getSingleton(beanName,ObjectFactory)-----222222222222
         * 这个重载方法主要就是做2件事情,
         * 1.ObjectFactory#Object方法 , 也就是createBean()
         * 2.createBean回调完成后, 将返回的bean放进一缓存,同时删除二级和三级缓存
         */
				if (mbd.isSingleton()) {
					sharedInstance = ``getSingleton``(beanName, () -> {
							return createBean(beanName, mbd, args);});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}
 //name前缀有& , 返回FactoryBean,没有的话,调用sharedInstance.getObject()方法返回真正的bean
        T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
		return (T) bean;
  }
     
第一个getSingleton

一级缓存(ioc容器)拿bean

​```DefaultSingletonBeanRegistry#getSingleton````
@Override
	@Nullable
	public Object getSingleton(String beanName) {
		return getSingleton(beanName, true);
	}
    // 重载方法一
    @Nullable
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		// 从一级缓存中获取单例对象
		Object singletonObject = this.singletonObjects.get(beanName);
    //因为isSingletonCurrentlyInCreatio为fasle  后面不会走了,当前没有在创建当中
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {...............}
	
		return singletonObject;
	}  
}       
第二个getSingleton

回调ObjectFactory.getObject方法 ,创建bean的实际逻辑全在这里() -> {return createBean(beanName, mbd, args);}),创建完最后会统一把返回的bean放进一级缓存

​```DefaultSingletonBeanRegistry#getSingleton````
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
	synchronized (this.singletonObjects) {
    //添加beanName到正在创建的容器中
    beforeSingletonCreation(beanName);
			try {
						singletonObject = singletonFactory.getObject();
						newSingleton = true;
					}
    //移除正在创建的容器的beanName
    afterSingletonCreation(beanName);
			if (newSingleton) {
        //创建完最后会统一把返回的bean放进一级缓存
						addSingleton(beanName, singletonObject);
			}
	}
}
createBean()
​````AbstractAutowireCapableBeanFactory # createBean````
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
/* 
     * BeanWrapper 是一个基础接口,由接口名可看出这个接口的实现类用于包裹 bean 实例。
     * 通过 BeanWrapper 的实现类可以方便的设置/获取 bean 实例的属性
     */
​````AbstractAutowireCapableBeanFactory # createBean````
protected Object doCreateBean(){
        /* 
         * 创建 bean 实例,并将实例包裹在 BeanWrapper 实现类对象中返回。createBeanInstance 
         * 中包含三种创建 bean 实例的方式:
    		 *   Supplier接口 ()
			   *   态工厂方法和工厂实例方法 (@Bean注解的方法会走这里哦)
				 *   ~有参构造 ~无参构造(一般是无参)
         *
         * 若 bean 的配置信息中配置了 lookup-method 和 replace-method,则会使用 CGLIB 
         * 增强 bean 实例。
         */
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    // 此处的 bean 可以认为是一个原始的 bean 实例,暂未填充属性

    /*
     * earlySingletonExposure 是一个重要的变量,这里要说明一下。该变量用于表示是否提前暴露
     * 单例 bean,用于解决循环依赖。earlySingletonExposure 由三个条件综合而成,如下:
     *   条件1:mbd.isSingleton() - 表示 bean 是否是单例类型
     *   条件2:allowCircularReferences - 是否允许循环依赖
     *   条件3:isSingletonCurrentlyInCreation(beanName) - 当前 bean 是否处于创建的状态中
     * 
     * earlySingletonExposure = 条件1 && 条件2 && 条件3 
     *                        = 单例 && 是否允许循环依赖 && 是否存于创建状态中。
     * 默认为ture , 也就是会走下面的逻辑
     */
    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&isSingletonCurrentlyInCreation(beanName));
    if (earlySingletonExposure) {
        // 添加工厂对象到 singletonFactories(三级缓存)
        /*
         *	这个getEarlyBeanReference是解决循环依依赖获取bean对象或者proxy的地方
         *---------这个方法很重要,也是为什么要三级缓存,而不是二级缓存的关键点--------
         */
        addSingletonFactory(beanName, () -> getEarlyBeanReference();
            }
        });
    }

    Object exposedObject = bean;
    try {
        // 向 bean 实例中填充属性,populateBean 方法也是一个很重要的方法
        populateBean(beanName, mbd, instanceWrapper);
        if (exposedObject != null) {
            /*
             * 进行余下的初始化工作,详细如下:
             * 1. 判断 bean 是否实现了 BeanNameAware、BeanFactoryAware、
             *    BeanClassLoaderAware 等接口,并执行接口方法
             * 2. 应用 bean 初始化前置操作	(@PostConstruct)
             * 3. 如果 bean 实现了 InitializingBean 接口,则执行 afterPropertiesSet 
             *    方法。如果用户配置了 init-method,则调用相关方法执行自定义初始化逻辑
             * 4. 应用 bean 初始化后置操作 (AOP入口)
             * 
             * 另外,AOP 相关逻辑也会在该方法中织入切面逻辑,此时的 exposedObject 就变成了
             * 一个代理对象了
             */
            exposedObject = initializeBean(beanName, exposedObject, mbd);
        }
    }
    
     //  此处要画一个重点,我刚开始看这里的时候忽略掉了
	if (earlySingletonExposure) {
    /**
     *---------	第三处getSingleton()------------------  3333333333333333333333
     *	返回的可能为proxy对象 , 也可能是愿对象 , 去的是二级缓存拿bean
     */
		Object earlySingletonReference = ```getSingleton```(beanName, false);
    
    // 只有循环依赖的bean才会走的逻辑
		if (earlySingletonReference != null) {
      
      /*
       *	如果完成初始化之后的bean与提前暴露的bean相等时,提前暴露的bean是target
       *	因为在初始化时后置处理器的postProcessAfterInitialization()方法处理可能创建代理对象
       *  不创建代理对象的原因有两种 : 
       *		1.bean本身不需要被代理
       *    2.getEarlySingletonReference中被代理并添加到earlyProxyReferences中,此时会跳过代理直接返回原始对象, 循环依赖才会触发getEarlyBeanReference,循环依赖中有代理条件才会传教proxy
       *	此处若相等,则说明postProcessAfterInitialization中未创建代理
       * 	进来这肯定都是循环依赖,所以直接把二级缓存中的bean返回(target或者proxy)
       */
			if (exposedObject == bean) {
				exposedObject = earlySingletonReference;
			}
      
      //这里是错误的创建bean的逻辑了
			else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
        //exposedObject != bean说明postProcessAfterInitialization()返回的是代理对象
				String[] dependentBeans = getDependentBeans(beanName);
				Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
				for (String dependentBean : dependentBeans) {
          
        // 如果依赖了当前对象A的对象B发现依赖的对象A是原始对象,则报错,因为容器中真正准备放的是代理对象A    @Async注解存在循环依赖且使用不当的时候可能会报这个错误,因为此种方式代理对象的创建是通过postProcessAfterInitialization()完成的,在getEarlyBeanReference()不会对代理对象进行创建
					if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
						actualDependentBeans.add(dependentBean);
					}
				}
	return exposedObject;
}
第三个getSingleton
​```DefaultSingletonBeanRegistry#getSingleton````//处理循环依赖的
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
				singletonObject = this.earlySingletonObjects.get(beanName);
        //allowEarlyReference传进来的是fasle , 所以这里返回的是二级缓存的bean
				if (singletonObject == null && allowEarlyReference) {.......}
			}
		}
		return singletonObject;
	}
getEarlyBeanReference
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
      implements AutowireCapableBeanFactory {
      
    protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
   Object exposedObject = bean;
   if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
      for (BeanPostProcessor bp : getBeanPostProcessors()) {
         if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
            SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
             // AOP创建代理对象的第二个入口 默认由AbstractAutoProxyCreator创建
            exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
         }
      }
   }
   return exposedObject;
  }
}
流程图

在这里插入图片描述
注意 : 不是循环依赖的代理对象的创建是在postProcessAfterInitialization,也就是在初始化后生成代理对象,直接返回,二级缓存为空,只用到了三级缓存和一级缓存
在这里插入图片描述
在这里插入图片描述

createBean

  1. InstantiationAwareBeanPostProcessor:Object bean = resolveBeforeInstantiation(beanName, mbdToUse),创建 bean 的逻辑会走 createBean 方法,该方法中会先执行所有 InstantiationAwareBeanPostProcessor 的 postProcessBeforeInstantiation 方法尝试创建 bean 实例,如果成功创建,则会直接调用 postProcessAfterInitialization 方法初始化 bean 后返回;如果 InstantiationAwareBeanPostProcessor 没有创建 bean 实例,则会调用 doCreateBean 方法创建 bean 实例。在 doCreateBean 方法中,会先根据 bean 的 Class 中的构造器定义,决定如何实例化 bean ,如果没有定义构造器,则会使用无参构造器,反射创建 bean 对象。
  2. createBeanInstance 创建bean
  3. MergedBeanDefinitionPostProcessor:applyMergedBeanDefinitionPostProcessors(InitDestroyAnnotationBeanPostProcessor,CommonAnnotationBeanPostProcessor,AutowiredAnnotationBeanPostProcessor),处理注入注解等

populateBean

  1. InstantiationAwareBeanPostProcessor:postProcessAfterInstantiation,postProcessAfterInstantiation 方法也是干预 bean 的属性等东西的。而且有一个小细节注意一下,postProcessAfterInstantiation 方法返回的是 boolean 类型,当 postProcessAfterInstantiation 返回 false 时,会直接 return 出去,不再执行下面的属性赋值 + 组件依赖注入的逻辑!(通常这个方法一定是返回 true 的,底层默认也是返回 true )------->>就是让咱在 bean 已经初始化好,但还没有开始属性赋值和依赖注入时切入自定义逻辑。
  2. InstantiationAwareBeanPostProcessor:postProcessProperties(AutowiredAnnotationBeanPostProcessor )

initializeBean

  1. invokeAwareMethods(beanName, bean)

  2. wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName) 前置回调

    • InitDestroyAnnotationBeanPostProcessor这个调用了**@PostConstruct**注解的方法
    • ApplicationContextAwareProcessor:调用invokeAwareInterfaces
  3. invokeInitMethods(beanName, wrappedBean, mbd): InitializingBean----->>>>initMetod

  4. wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName) 后置回调

    • AbstractAutoProxyCreator:创建代理对象的关键
    • ApplicationListenerDetector:用来关联所有的监听器引用

扩展点

invokeBeanFactoryPostProcessors

  • ImportSelector/ImportBeanDefinitionRegistrar
  • BeanDefinitionRegistryPostProcessor

自定义的 BeanDefinitionRegistryPostProcessor 执行时机比内置的 ConfigurationClassPostProcessor 要晚,这也是 SpringFramework 最开始的设计( ConfigurationClassPostProcessor 实现了 PriorityOrdered 接口,且优先级最高)

  • BeanFactoryPostProcessor

registerBeanPostProcessors

finishBeanFactoryInitialization

  • InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation

从 bean 的创建阶段之前,就有 InstantiationAwareBeanPostProcessor 来拦截创建了,每个 bean 在创建之前都会尝试着使用 InstantiationAwareBeanPostProcessor 来代替创建,如果没有任何 InstantiationAwareBeanPostProcessor 可以拦截创建,则会走真正的 bean 对象实例化流程。

InstantiationAwareBeanPostProcessorpostProcessBeforeInstantiation 方法中,只能拿到 bean 对应的 Class 类型,以及 bean 的名称(当然啦,本来就是凭空造,有 Class 类型就够了),如果方法没有返回值,则代表 InstantiationAwareBeanPostProcessor 不参与拦截 bean 创建的动作。

  • SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors
  • MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition

在 createBeanInstance 方法执行完毕之后,此时 bean 对象已经创建出来了,只是没有任何属性值的注入而已。此时 doCreateBean 方法会走到 applyMergedBeanDefinitionPostProcessors 方法,让这些 MergedBeanDefinitionPostProcessor 去收集 bean 所属的 Class 中的注解信息。三个关键的 MergedBeanDefinitionPostProcessor ,它们分别是 InitDestroyAnnotationBeanPostProcessor (收集 @PostConstruct 与 @PreDestroy 注解)、CommonAnnotationBeanPostProcessor (收集 JSR 250 的其它注解)、AutowiredAnnotationBeanPostProcessor (收集自动注入相关的注解)。

  • InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation

等这些 MergedBeanDefinitionPostProcessor 都工作完毕后,此时 bean 对象所属的 Class 中的信息都收集完毕了,接下来还得让 InstantiationAwareBeanPostProcessor 出场,它要负责控制是否继续走接下来的 populateBean 和 initializeBean 方法初始化 bean 。

  • InstantiationAwareBeanPostProcessor#postProcessProperties

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean 1414

不过这次它调用的是 postProcessProperties 方法,这个步骤会将 bean 对象对应的 PropertyValues 中封装赋值和注入的数据应用给 bean 实例。通常情况下,在该阶段 SpringFramework 内部起作用的后置处理器是 AutowiredAnnotationBeanPostProcessor ,它会搜集 bean 所属的 Class 中标注了 @Autowired 、@Value 等注解的属性和方法,并反射赋值 / 调用。CommonAnnotationBeanPostProcessor处理@Resource 注解

  • BeanPostProcessor

接下来的两个动作就发生在 initializeBean 方法中了,它就是 BeanPostProcessor 的前后两个执行动作 postProcessBeforeInitialization 和 postProcessAfterInitialization 。进入到 initializeBean 方法后,bean 的生命周期已经到了初始化逻辑回调的阶段,此时 bean 中应该注入的属性均已完备,BeanPostProcessor 的切入也只是给 bean 添加一些额外的属性的赋值、回调等等,以及生成代理对象。

  • SmartInitializingSingleton

它是在所有非延迟加载的单实例 bean 全部初始化完成后才回调的。这个阶段底层会取出所有实现了 SmartInitializingSingleton 接口的 bean ,去回调 afterSingletonsInstantiated 方法。而且当时小册还说了,这个设计只是为了让 BeanFactory 也能插一脚初始化的后处理,仅此而已。

在这里插入图片描述

下面是转载一位大神的AOP入口,待以后学习aop

转载链接 : https://blog.csdn.net/forever_ddaxx/article/details/105608020

IoC (Inversion of Control,控制反转)是一种设计模式,它将程序中的控制权从代码中转移到了容器中,使得程序的可扩展性和可维护性更强。IoC 容器就是实现 IoC 模式的一个工具,它可以自动创建、装配和管理对象,从而简化了应用程序的开发和维护。 在 C# 中,有很多开源的 IoC 容器可供选择,比如 Unity、Autofac、Castle Windsor 等。这些 IoC 容器都有一个共同的特点,就是它们提供了一种机制,可以将应用程序中的对象的创建、装配和生命周期管理交给容器来完成,从而减少了应用程序代码的耦合性。开发人员只需要在应用程序中声明依赖关系和对象的生命周期要求,IoC 容器就可以自动完成对象的创建和装配。 以下是一个使用 Autofac IoC 容器的示例代码: ``` // 定义服务接口和实现类 public interface IService { void DoSomething(); } public class ServiceImpl : IService { public void DoSomething() { Console.WriteLine("Service is doing something."); } } // 注册服务到容器中 var builder = new ContainerBuilder(); builder.RegisterType<ServiceImpl>().As<IService>(); var container = builder.Build(); // 从容器中获取服务实例并调用方法 var service = container.Resolve<IService>(); service.DoSomething(); ``` 上面的代码中,我们首先定义了一个 IService 接口和一个 ServiceImpl 实现类。然后,使用 Autofac 的 ContainerBuilder 类将 ServiceImpl 类注册为 IService 接口的实现类。最后,使用容器的 Resolve 方法从容器中获取 IService 接口的实例,并调用其 DoSomething 方法。 使用 IoC 容器可以使应用程序更加灵活和可扩展,因为它可以动态地创建和管理对象,从而减少了代码的耦合性。但是,开发人员也需要注意 IoC 容器的使用和配置,以确保应用程序的性能和可维护性。同时,由于 IoC 容器需要在应用程序启动时初始化,因此它可能会对应用程序的启动时间产生一定的影响。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值