spring源码分析之bean的加载

目录

一、bean的加载

         1、getBean()方法

2、doGetBean()方法

   2.1、获取初始beanName

   2.2、从缓存中获取bean实例

3、对于原型对象的循环依赖检查

4、从父BeanFactory中获取bean实例

5、合并BeanDefinition

6、对于bean的依赖对象的注册

7、不同scope属性的对象的实例化和初始化

8、类型转换

二、bean的转换操作

1、bean的获取操作

2、getObjectFromFactoryBean()方法

3、doGetObjectFromFactoryBean()方法

 


前言:在程序员会用spring的xml类型的bean实例的过程其实很简单,仅仅两行代码就能够获取到我们想要使用的bean实例进行相关的业务操作。在spring源码分析之容器的使用 这篇博文中我们已经讲解了其中的第一行代码 xml解析操作,在第一行代码中程序已经完成了将<beans />标签解析为BeanDefinition实例并存放在spring容器中。

1、XmlBeanFactory  beanFactory = new XmlBeanFactory(new ClassPathResource("spring-mytag.xml"));
2、User user = beanFactory.getBean("myUser",User.class);

下面我们就来详细的介绍一下如上的第二行代码 bean的加载流程。

 

一、bean的加载

    1、getBean()方法

         通过代码分析第一步是调用AbstractBeanFactory的getBean()方法来获取bean实例,在spring中为我们提供了四种类型的获取bean实例的操作。

Object getBean(String name) 
根据bean配置的唯一标识取bean实例,如果BeanDefintion有id使用id,没有id 使用name的第一个名字作为其唯一标识
<T> T getBean(String name,  Class<T> requiredType)
根据bean配置的唯一标识以及对应的bean的class属性获取bean 
 Object getBean(String name, Object... args)
根据bean配置的唯一标识和对应的bean的构造函数参数获取bean
 getBean(String name, Class<T>requiredType, Object... args)
根据bean配置的唯一标识和bean的class属性和构造函数参数获取bean

通过代码可以知道getBean() 一系列的重载方法最终都会调用doGetBean(),由此看来对于获取bean的实例操作应该在该doGetBean()方法中,下面我们来一起探究一下doGetBean()方法

2、doGetBean()方法

      doGetBean()方法对于创建bean实例的进行了全局的统筹操作,因为是框架需要考虑的问题有很多,所以该方法只是做了大致逻辑的区分,具体的细节相关的实现,放在不同的方法中(不同的方法中可能为了将代码可读性 会将更细节的东西继续抽成方法或者委托不同类来进行相关功能的实现 这也体现了设计模式的单一原则)。

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
		@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

//1、获取最初的beanName 

    //因为bean实例可能存在多个别名,或者别名之间的相互引用,所以需要获取到其最初始的beanName
    // 别名->beanName  A->B   B->C  C->D 则最初始的名字是D
	final String beanName = transformedBeanName(name);
	Object bean;

//2、尝试先从缓存中获取

	//返回一个已经缓存的beanName对应的实例 为了防止setter类型的循环引用
	//这里要插入几句 bean的循环依赖有两种 构造器循环依赖、
    //setter循环依赖单例、 setter循环依赖原型
	//会提前将未完全初始化的实例先放入缓存中 防止出现循环引用
	Object sharedInstance = getSingleton(beanName);
	if (sharedInstance != null && args == null) {
		if (logger.isDebugEnabled()) {
			if (isSingletonCurrentlyInCreation(beanName)) {
				logger.debug("Returning eagerly cached instance of singleton bean '" 
           + beanName +
	 "' that is not fully initialized yet - a consequence of a circular reference");
			}
			else {
			logger.debug("Returning cached instance of singleton bean '" 
                   + beanName + "'");
	   }
	}
	  //根据获取到的bean实例 进一步分析bean实例是一个普通的bean
      //还是FactoryBean 普通的bean直接返回
	  //对于FactoryBean 则需要调用其getObejct()方法来获取bean实例
	  bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
	}

//3、缓存中没有对应的单例对象 需要手动创建

	else {
		//3.1、假设当前处于循环引用 如果是原型对象 则抛出异常
		if (isPrototypeCurrentlyInCreation(beanName)) {
			throw new BeanCurrentlyInCreationException(beanName);
		}
        //3.2、先交由父BeanFactory 获取bean实例
		//如果该BeanFactory有父BeanFactory 则获取其父BeanFactory
		//调用父BeanFactory的doGetBean()方法
		BeanFactory parentBeanFactory = getParentBeanFactory();
		//parentBeanFactory不是null 且当前beanFactory不包含beanName
        //则需要从父类进行容器工厂获取对应的bean实例
		if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
			//还是获取最初始的beaName (如果涉及到该类为FactoryBean 则初始名字添加“&”)
			String nameToLookup = originalBeanName(name);
			//父工厂对象是AbstractBeanFactory调用其doGetBean()方法以此类推。
			//根据获取到的参数不同 调用父类对应的不同方法
			if (parentBeanFactory instanceof AbstractBeanFactory) {
				return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
						nameToLookup, requiredType, args, typeCheckOnly);
			}
			else if (args != null) {
				return (T) parentBeanFactory.getBean(nameToLookup, args);
			}
			else {
				return parentBeanFactory.getBean(nameToLookup, requiredType);
			}
		}
        //3.3、没有父BeanFactory 则需要该BeanFactory来进行创建
        //这里进行创建前的准备功能 比如标记创建标识
        //标记该beanName对应的实例已经被创建
		if (!typeCheckOnly) {
			markBeanAsCreated(beanName);
		}
		try {
			//获取一个合并与其父辈BeanDefintion类合并后的一个MergedBeanDefintion
			final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
			//只是校验mbd是否抽象
			checkMergedBeanDefinition(mbd, beanName, args);
			//获取BeanDefinition的所有依赖
			String[] dependsOn = mbd.getDependsOn();
			if (dependsOn != null) {
				//遍历所有的依赖
				for (String dep : dependsOn) {
					//如果对应的dep已经存在在beanName对应的依赖中 则该dep不进行注册
					if (isDependent(beanName, dep)) {
						throw new BeanCreationException
                        (mbd.getResourceDescription(), beanName,
							"Circular depends-on relationship between '"
                             + beanName + "' and '" + dep + "'");
					}
					//注册beaName的所有依赖的bean实例
					//这里其实是在两份缓存中添加一份数据
					//dependentBeanMap中存放着当前Bean被引用的Bean的集合
					//dependenciesForBeanMap中存放的则是当前Bean有依赖的Bean的集合
					registerDependentBean(dep, beanName);
					try {
						//对beanName对应的依赖先进行获取 放入缓存中
						getBean(dep);
					}
					catch (NoSuchBeanDefinitionException ex) {
						throw new BeanCreationException(mbd.getResourceDescription()
					 }
			    }
			}
            //BeanDefintion 已经创建并合并完成 

 //4、接下来需要使用BeanDefintion来创建对象的时候了

			// 创建对象分两种类型 一种单例对象 一种原型对象
			//4.1、创建单例对象实例
			if (mbd.isSingleton()) {
				//创建单例对象
				sharedInstance = getSingleton(beanName, () -> {
					try {
						//具体的调用逻辑是调用ObjectFactory其匿名内部类
                        //getObject方法中createBean()方法
						return createBean(beanName, mbd, args);
					}
					catch (BeansException ex) {
						destroySingleton(beanName);
						throw ex;
					}
				});
				bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
			}
			//4.2、创建原型对象
			else if (mbd.isPrototype()) {
				// It's a prototype -> create a new instance.
				Object prototypeInstance = null;
				try {
					//原型对象创建之前的回调
					//主要功能是将创建的beanName 放入prototypesCurrentlyInCreation中
					beforePrototypeCreation(beanName);
					//创建原型对象的方式和创建单例对象的一样 这里不再详述
					prototypeInstance = createBean(beanName, mbd, args);
				}
				finally {
					//原型对象创建之前的回调
					//主要功能是将创建的beanName从prototypesCurrentlyInCreation移除
					afterPrototypeCreation(beanName);
				}
				bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
			}
			//4.3、非单例和原型对象的其他scope类型的创建实例
			else {
				//获取bean定义的scopeName 并从scope缓存中活scope实例对象
				String scopeName = mbd.getScope();
				final Scope scope = this.scopes.get(scopeName);
				if (scope == null) {
					throw new IllegalStateException();
				}
				try {
					//调用scope的get方法,具体的创建的操作是
                    //在其第二个匿名参数ObjectFactory里面也是调用createBean()
					Object scopedInstance = scope.get(beanName, () -> {
						beforePrototypeCreation(beanName);
						try {
							return createBean(beanName, mbd, args);
						}
						finally {
							afterPrototypeCreation(beanName);
						}
					});
					bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
				}
				catch (IllegalStateException ex) {
					throw new BeanCreationException(beanName ex);
				}
			}
		}
		catch (BeansException ex) {
			//创建实例失败  则将创建之前标记在alreadyCreated中的标识去除
			cleanupAfterBeanCreationFailure(beanName);
			throw ex;
		}
	}

//5、检查创建的实例是否和调用者传入的实例class是否一致 

    //如果不一致则需要使用TypeConverter
	//去进行将其转换为正确的类型。如果无法转换则抛出异常
	if (requiredType != null && !requiredType.isInstance(bean)) {
		try {
			T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
			if (convertedBean == null) {
				throw new BeanNotOfRequiredTypeException(name, requiredType,
                bean.getClass());
			}
			return convertedBean;
		}
		catch (TypeMismatchException ex) {
			//异常处理			}
	}
	return (T) bean;
}

   相信读者仔细阅读笔者添加注释的代码,能大概的了解到spring获取bean实例的大致流程。对于spring容器获取bean实例的主要逻辑如下。

   2.1、获取初始beanName

          因为两个原因我们需要获取最初的beanName

    1、因为spring的bean实例有两种类型: 一种是普通的bean,另一种是FactoryBean,对于factoryBean获取的时候需要添加&+beanName, 获取其创建的bean实例 则不需要使用“&”。

   2、spring支持bean的实例注册的时候注册别名,所以对于一个实例bean可能存在C别名指向B别名,B别名指向A别名的情况,所以需要获取最初始的A 已其为唯一标识获取bean实例

  2.2、从缓存中获取bean实例

      单例对象只会在spring容器中创建一次,创建完成后会被缓存,下次获取直接从缓存中获取,对于原型对象是不会缓存,先从缓存中获取肯定为null则会继续向下走也是适用的,缓存还有一个作用是便于我们解决settter类型的循环依赖。说道循环依赖这里笔者要插几句:循环依赖是两个实例都互相持久对方比如实例beanA 有一个beanB的属性,实例beanB有一个实例beanA的属性,循环依赖有三种类型 :构造函数循环依赖、setter方法循环依赖,原型对象循环依赖。有关循环依赖的详细内容读者可以参考笔者的这篇博文 spring源码分析值循环依赖

    补充:  spring对于循环依赖的解决正是通过缓存来解决的,spring会将已经实例化但是并未完全初始化的bean包装成ObjectFactory对象放入缓存中,将其提前暴露出来一旦其他bean需要引用他则可以直接使用ObjectFactory从而避免了循环依赖的死等情况。后面再具体的循环依赖解决再进行详细讲解。

      获取到的缓存bean后需要调用getObjectForBeanInstance()方法进行bean实例的转换,有关该方法因为不论是缓存中获取还是手动创建单例/原型对象都会调用该方法进行操作,所以后面会单独统一介绍介绍

3、对于原型对象的循环依赖检查

//如果当前处于循环引用 如果是原型对象 则抛出异常
if (isPrototypeCurrentlyInCreation(beanName)) {
	throw new BeanCurrentlyInCreationException(beanName);
}

//spring对于原型对象
protected boolean isPrototypeCurrentlyInCreation(String beanName) {
    //获取当前beanFactory中正在创建的原型对象,
    //如果只有一个prototypesCurrentlyInCreation 获取到的就是该object
    //如果有多个则会存放在set<?> 中
	Object curVal = this.prototypesCurrentlyInCreation.get();
    //如果有正在创建的原型对象 且原型对象中包含 beanName对应的原型返回true 
    //否则返回false
	return (curVal != null &&
		(curVal.equals(beanName) || 
			(curVal instanceof Set && ((Set<?>) curVal).contains(beanName)
	  )));
	}

 通过看上面的代码很好理解,因为在创建原型对象之前,会在prototypesCurrentlyInCreation中存放正在创建的实例的beanName。如果发现正在创建原型对象中已经存在beanName 则返回true,从而抛出异常。

如果遇到BeanA 持有属性BeanB,BeanB持有属性BeanB 则两者都是原型对象的这种情况,则我们按照spring创建实例的过程分析一下 :创建BeanA对应的实例过程中,添加该beanA到prototypesCurrentlyInCreation标明其正在创建,发现有依赖属性beanB,则先实例化属性beanB,添加该beanB到prototypesCurrentlyInCreation标明其正在创建, 我擦因为是原型对象紧接着又去创建beanA,这不就傻逼了,你猜是先StackOverflow还是OutOfMemory?。针对这种情况在第二次创建beanA的时候,在prototypesCurrentlyInCreation发现该beanA已经正在被创建则说明原型对象创建遇到了循环依赖,针对这种情况spring直接抛出异常 。

 

4、从父BeanFactory中获取bean实例

       如果缓存中没有对应的实例,则需要我们手动创建bean实例,如果当前BeanFactory有父类对象,且当前BeanFactory中不包含beanName对应的beanDefintion.会尝试调用父BeanFactory的getBean()方法来获取bean实例并返回,调用流程和我们目前分析的一致。

5、合并BeanDefinition

                对于之前xml配置解析后会生成对应的BeanDefinition实例对象具体的是GernericBeanDefinition,需要调用getMergedLocalBeanDefinition()方法根据将GernericBenanDefinition转换为RootBeanDefintion,但是对于具有继承关系的bean实例 。   比如如下的xml中:

<bean id="son" class="com.xiu.autoeire.Son" parent="parent" />

对于xml解析可能会生成两个对应的BeanDefintion实例,一个parent 对应的BeanDefintion,一个是son对应的BeanDefintion,这里会将这两个bean进行合并,对于所有有继承关系的bean实例会生成一个合并的RootBeanDefinition实例,并放入缓存中便于下次获取beanDefintion的时候直接从缓存中获取而不用进行合并操作。下面是对代码的分析。

//将对应的BeanDefinition和其父类对应的BeanDefinition合并为一个RootBeanDefinition对象
protected RootBeanDefinition getMergedBeanDefinition(
		String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
		throws BeanDefinitionStoreException {
	synchronized (this.mergedBeanDefinitions) {
		RootBeanDefinition mbd = null;
			//从mergedBeanDefinitions缓存中获取BeanDefinition实例
		if (containingBd == null) {
			mbd = this.mergedBeanDefinitions.get(beanName);
		}
        //如果缓存中没有
		if (mbd == null) {
			//判断bd是否继承父类 如果没有 则将其包装成RootBeanDefintion 返回
			if (bd.getParentName() == null) {
				// Use copy of given root bean definition.
				if (bd instanceof RootBeanDefinition) {
					mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
				}
				else {
					mbd = new RootBeanDefinition(bd);
				}
			}
			else {
				//有父类BeanDefinition,根据父类的parentBeanName获取父类合并后的 
                //MergedBeanDefinttion实例
				BeanDefinition pbd;
				try {
					//这里有两种情况 正常情况 beanName与parentBeanName不相等
                    //调用该BeanFactory本身的
					//getMergedBeanDefinition() 以parentName为参数 
                    //查询合并后的BeanDefinition
					String parentBeanName = transformedBeanName(bd.getParentName());
					if (!beanName.equals(parentBeanName)) {
						pbd = getMergedBeanDefinition(parentBeanName);
					}
					else {
					//如果beanName 与parentBeanName 则两者肯定不在一个工厂对象中
					//获取其父对象工厂并且要确保BeanFactory是onfigurableBeanFactory实例
						BeanFactory parent = getParentBeanFactory();
						if (parent instanceof ConfigurableBeanFactory) {
							pbd = ((ConfigurableBeanFactory) 
                    parent).getMergedBeanDefinition(parentBeanName);
						}
						else {
							throw new NoSuchBeanDefinitionException(parentBeanName);
						}
					}
				}
				catch (NoSuchBeanDefinitionException ex) {
					throw new BeanDefinitionStoreException(ex);
				}
				// 将获取到的RootBeanDefinition 与bd进行合并
				mbd = new RootBeanDefinition(pbd);
				mbd.overrideFrom(bd);
			}
			//如果mbd没有配置scope则先设置默认的scope为单例对象
			if (!StringUtils.hasLength(mbd.getScope())) {
				mbd.setScope(SCOPE_SINGLETON);
			}
			//非单例的bean 本身不能包含非单例的bean如果被包含的bean 
            //containingBd不是单例 而包含他的bean则一定不是单例
			//需要与被包含的bean containingBd的scope保持一致
			if (containingBd != null && !containingBd.isSingleton()
                    && mbd.isSingleton()) {
				mbd.setScope(containingBd.getScope());
			}
			//暂时缓存合并的bean定义,它仍然可能在以后重新合并,以获取元数据更改
			if (containingBd == null && isCacheBeanMetadata()) {
				this.mergedBeanDefinitions.put(beanName, mbd);
			}
		}
		return mbd;
	}
}

对于获取的bean需要调用 checkMergedBeanDefinition(mbd, beanName, args)  来判断合区到的beanDefintion是否为抽象实例如果是抽象则抛出异常不进行bean实例的获取。

6、对于bean的依赖对象的注册

       对于bean实例有depends-on属性的依赖对象,需要获取其所有的依赖对象并将其所有的依赖对象进行实例化和初始化,被依赖的bean要先于依赖于它的bean实例初始化。

<!--depends-on属性:depends-on是指相对于ref强关联关系  关联关系不强的两者属性依赖使用的depends-on
比如系统需要启动多个服务 用户服务,订单服务等 只有多个服务启动成功后,才启动系统 这个产品可以使用该属性.
同时指定Bean初始化及销毁时的顺序,使用depends-on属性指定的Bean要先初始化完毕后才初始化当前Bean,
由于只有"singleton"Bean才能被Spring管理销毁,所以当指定的Bean都是"singleton"时,
使用depends-on属性指定的Bean要在指定的Bean之后销毁。衍生出如下的实例初始化init-method属性 和销毁调用 destroy-method属性
-->
  <!-- 用户服务 -->
    <bean id="userService" class="com.xiu.service.dependson.UserService"/>
    <!-- 订单服务 -->
    <bean id="orderService" class="com.xiu.service.dependson.OrderService" />

    <bean id="system" class="com.xiu.service.dependson.MySystem" depends-on="orderService,userService" />

7、不同scope属性的对象的实例化和初始化

      在缓存中没有对应实例bean的条件下,我们需要进行bean实例的手动创建,前面我们我们已经做了一些bean实例化和初始化准备操作比如获取beanDefinition,注册bean的依赖实例,下面需要着手进行bean的实例化创建了。bean实例化创建不同的scope由不同的实例化流程,主要分成3大类。

  • 单例模式下的对象实例化
  • 原型模式下的对象实例化
  • 其他scope范围的对象实例化 ,比如 request,session,global session等scope(非常不常用)

 spring对于其对象实例化和初始化的操作用了大量的篇幅。为了博文的可读性,具体的实例化细节操作可以参考博主的

spring 不同scope的对象实例化和初始化

8、类型转换

  对于外部调用如果传递了requiredType (特定参数class类型),意味着调用方需要获取符合该requiredType的class属性的实例对象这时候需要调用TypeConverter 来将bean转换为requiredType对应bean实例,用户可以根据自己的需要进行扩展符合自己需要的类型转换器。

 

二、bean的转换操作

1、bean的获取操作

  从缓存中获取bean实例是一种类似原始状态的bean,或者单例对象原型对象以及其他scope作用范围的对象创建出来的bean只是bean的原始状态,需要做一些转换操作比如:根据获取到的bean实例 进一步分析bean实例是一个普通的bean还是FactoryBean,所以此处需要调用getObjectForBeanInstance()方法

  1. 普通的bean直接返回不做处理,
  2.  如果是FactoryBean 则获取实例可能有两种情况

       2.1、 一种是FactoryBean实例本身,说明获取实例bean的beanName有前缀“&” (spring对于FactoryBean实例本身获取需要添加前缀“&”)

       2.2、另一种获取FactoryBean中的factory-method方法获取的bean实例,getObjectForBeanInstance()主要也是做这部分的转换。

//该方法主要是为了验证我们创建的beanInstance(原始状态)是否为FactoryBean
//如果是FactoryBean 且用户需要FactoryBean创建的对象
// 调用FactoryBean的getObject()方法来获取
//如果是普通的bean或者用户想到FactoryBean本身的实例对象(传入的beanName 带有"&")

protected Object getObjectForBeanInstance(
	Object beanInstance, String name, String beanName,
   @Nullable RootBeanDefinition mbd) {
	// 如果name带有“&” 但是却不是FactoryBean 实例说明beanInstance验证错误抛出异常
	// NullBean 空对象除外
	if (BeanFactoryUtils.isFactoryDereference(name)) {
		if (beanInstance instanceof NullBean) {
			return beanInstance;
		}
		if (!(beanInstance instanceof FactoryBean)) {
			throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
		}
	}

   //对于bean实例 如果是普通的bean或者需要获取FactoryBean 实例对象本身name包含“&”前缀 
   //则返回实例对象,这时的实例对象可能是普通的bean
   if (!(beanInstance instanceof FactoryBean) || 
             BeanFactoryUtils.isFactoryDereference(name)) {
			return beanInstance;
   }
   //程序执行到这里我们应该知道了该beanName对应的实例bean 是一个FactoryBean
   //后面的代码都是为了调用该Factorybean的getObject()获取bean实例
	Object object = null;
	if (mbd == null) {
		//先从存储FactoryBean的缓存中获取
		object = getCachedObjectForFactoryBean(beanName);
	}
	//如果缓存中没有
	if (object == null) {
	  //手动调用方法创建
      FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
	  //如果mdb不存在 我们从mergedBeanDefinitions 缓存中
      //获取对应的RootBeanDefinition对象
	  //该RootBeanDefinition对象是spring解析ean.xml解析完成后将bean标签对应的实例
	  //放在该mergedBeanDefinitions 中的
	  if (mbd == null && containsBeanDefinition(beanName)) {
		//将父类和子类的BeanDefintion 都合并为一个BeanDeFinition 
		mbd = getMergedLocalBeanDefinition(beanName);
	  }
	  //判断mdb 是否为synthetic 合成的bean false 开发人员自定义的bean,
      //true 应用程序本身合成的bean
	  boolean synthetic = (mbd != null && mbd.isSynthetic());
	  //对于应用程序内部的BeanDefintion 是需要应用后置处理器进行处理的(合成加工)
	  //这里具体来执行FactoryBean 的getObject()获取实例对象
	  object = getObjectFromFactoryBean(factory, beanName, !synthetic);
	  }
	return object;
}

     先验证用户bean实例是普通bean还是factoryBean,对于用户获取的是普通的bean或者FactoryBean本身实例对象则直接返回,对于获取Factorybean工厂的getObject()获取bean实例。

    通过工厂对象的getObject()方法获取bean逻辑如下:

     先从缓存着Factorybean的getObject()方法创建的bean 的集合获取bean,如果缓存中没有则需要手动创建bean,同样的先获取合并后的BeanDefiniton实例,具体的创建交由getObjectFromFactoryBean()方法

2、getObjectFromFactoryBean()方法

    该方法的主要逻辑是:

  1.  从缓存中获取bean实例
  2.  没有调用FactoryBean的getObejct() 获取bean实例
  3.  根据是 (1)程序内部合成的bean 应用后置处理器 (2)自定义的bean则不使用后置处理器
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
	//单例模式走 该方法
	if (factory.isSingleton() && containsSingleton(beanName)) {
		synchronized (getSingletonMutex()) {
		//先从factoryBean 的缓存中尝试获取FactoryBean getObject()方法获取的实例
		Object object = this.factoryBeanObjectCache.get(beanName);
		if (object == null) {
	    	//调用FacoryBean的getObejct()方法获取bean实例对象
			object = doGetObjectFromFactoryBean(factory, beanName);
           //为了在创建单例对象中保证其单例对象唯一性 防止因为循环引用导致的bean提早暴露
			// 在创建object成功后 还从缓存中获取了bean实例
            // 如果存在则用获取到的bean实例进行替换 返回
			//说明该bean实例 在创建的时候 已经通过别的方式 存储了
			Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
			if (alreadyThere != null) {
				object = alreadyThere;
			}
			else {
				//程序需要自己内部合成的bean
				if (shouldPostProcess) {
					if (isSingletonCurrentlyInCreation(beanName)) {
						// bean在应用后置处理器时候 发现已经在创建了 
                        // 直接返回未应用后置处理器的bean实例
						return object;
					}
					//单例对象创建之前的回调 默认实现是将其添加到正在创建的列表中
					//表明该对象正在被创建 单例对象 防止多次创建
					beforeSingletonCreation(beanName);
					try {
						//对object 应用后置处理器 创建出来的对象可能为一个代理对象
						object = postProcessObjectFromFactoryBean(object, beanName);
					}
					catch (Throwable ex) {
						throw new BeanCreationException(beanName)
					}
					finally {
						//单例对象创建之前的回调 默认实现将正在创建的该bean标识
                        //从正在创建bean的列表中移除
						afterSingletonCreation(beanName);
					}
				}
				if (containsSingleton(beanName)) {
					//将创建的单例对象放入缓存
					this.factoryBeanObjectCache.put(beanName, object);
				}
			}
		}
		return object;
	}
}
	//原型模式下 走该方法
	else {
		Object object = doGetObjectFromFactoryBean(factory, beanName);
		if (shouldPostProcess) {
			try {
                         //应用后置处理器
    			object = postProcessObjectFromFactoryBean(object, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(ex);
				}
			}
			return object;
		}
	}

看了上面的代码我们发现还没有看到最终FactoryBean的getObject()方法,其实这个方法的调用是在doGetObjectFromFactoryBean()方法。

3、doGetObjectFromFactoryBean()方法

//最终调用FactoryBean的getObject() 获取实例对象
private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
		throws BeanCreationException {
	//一个带有权限验证 一个非权限验证  单都是调用其 factory.getObject() 来获取实例
	Object object;
	try {
		if (System.getSecurityManager() != null) {
			AccessControlContext acc = getAccessControlContext();
			try {
				object = 
           AccessController.doPrivileged((PrivilegedExceptionAction<Object>)
    factory::getObject, acc);
			}
			catch (PrivilegedActionException pae) {
				throw pae.getException();
			}
		}
		else {			
			object = factory.getObject();
		}
	}
	catch (FactoryBeanNotInitializedException ex) {
	}
}

通过层层的扒开代码,我们最终看到了最终调用getObject(),同时关于类的转换操作也就完成了,我们也比较的清晰的了解了该bean的转换操作方法。

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值