欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

spring容器

程序员文章站 2022-05-06 18:20:21
...

BeanFactory体系

spring容器

先来一张图压压惊,由上图可见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;
  }
}
流程图

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

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

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

相关标签: Spring