spring底层源码分析-IOC容器的初始化过程

1、IOC容器的初始化过程

完成初始化可以由以下几行代码完成:

ClassPathResource res = new ClassPathResource("beans.xml");     //找到xml配置文件
//DefaultListableBeanFactory是IOC容器的具体实现,内含currentHashMap,实现了BeanDefinitionRegistry接口。
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
//xml的解析器。
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
//解析xml,并将解析得到的bean对象注册到factory中
reader.loadBeanDefinitions(res);
//后面就可以:factory.getBean("user"); 了

1.1 定位

定位是找到xml配置文件。

定位功能主要是Resource接口,他的具体实现类都有定位功能。

1.2 解析和载入

从FileSystemXmlApplicationContext入手。

FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("beans.xml");

然后会调用refresh(),这个方法很重要,每个具体的applicationContext都会调用,refresh()是在父类AbstractApplicationContext实现的。

public void refresh() throws BeansException, IllegalStateException {
        synchronized(this.startupShutdownMonitor) {
            this.prepareRefresh();
            //obtainFreshBeanFactory()启动子类的refreshBeanFactory(),首先清除原有的IOC容器,然后创建DefaultListableBeanFactory容器,并进行Bean的定位、载入和解析。
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
            this.prepareBeanFactory(beanFactory);

            try {
                //空方法,由子类实现
                this.postProcessBeanFactory(beanFactory);
                //实例化并执行所有的BeanFactoryPostProcessors
                this.invokeBeanFactoryPostProcessors(beanFactory);
                //实例化并注册所有的BeanPostProcessors
                this.registerBeanPostProcessors(beanFactory);
                //国际化
                this.initMessageSource();
                //初始化事件广播器
                this.initApplicationEventMulticaster();
                //空方法,由子类实现
                this.onRefresh();
                //注册监听器
                this.registerListeners();
                //初始化剩余的非懒加载的单例对象
                this.finishBeanFactoryInitialization(beanFactory);
                this.finishRefresh();
            } catch (BeansException var9) {
                if (this.logger.isWarnEnabled()) {
                    this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
                }

                this.destroyBeans();
                this.cancelRefresh(var9);
                throw var9;
            } finally {
                this.resetCommonCaches();
            }

        }
    }

1.2.1 obtainFreshBeanFactory()方法:

定位及载入过程:

大致脑图,(具体过程看下面代码)解析过程看下一个篇章:

在这里插入图片描述

在这里插入图片描述

//AbstractApplicationContext的obtainFreshBeanFactory()
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
   this.refreshBeanFactory();
   return this.getBeanFactory();
}

//子类的AbstractRefreshableApplicationContext
protected final void refreshBeanFactory() throws BeansException {
    //判断是否已经有IOC容器了,有则清除容器
        if (this.hasBeanFactory()) {
            this.destroyBeans();
            this.closeBeanFactory();
        }

        try {
            //创建DefaultListableBeanFactory容器
            DefaultListableBeanFactory beanFactory = this.createBeanFactory();
            beanFactory.setSerializationId(this.getId());
            this.customizeBeanFactory(beanFactory);
  //进行Resource定位、XmlBeanDefinitionReader载入以及loadBeanDefinitions(XmlBeanDefinitionReader)解析,具体代码在下面:
            this.loadBeanDefinitions(beanFactory);
            this.beanFactory = beanFactory;
        } catch (IOException var2) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var2);
        }
    }

//子类AbstractXmlApplicationContext的loadBeanDefinitions
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) 
    throws BeansException, IOException {
    //这里使用了XmlBeanDefinitionReader,如果不是FileSystemXmlApplicationContext,则applicationcontext则会使用其他类型的BeanDefinitionReader。
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
        beanDefinitionReader.setEnvironment(this.getEnvironment());
    //为XmlBeanDefinitionReader配置ResourceLoader,因为该类的父类是DefaultResourceLoader,所以this可以直接使用
        beanDefinitionReader.setResourceLoader(this);
        beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
        this.initBeanDefinitionReader(beanDefinitionReader);
     //这里启动Bean的信息载入和解析,具体代码如下:
        this.loadBeanDefinitions(beanDefinitionReader);
    }

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
    //以Resource方式获得配置文件的资源位置
        Resource[] configResources = this.getConfigResources();
        if (configResources != null) {
            //具体代码在下面。
            reader.loadBeanDefinitions(configResources);
        }
	//以String形式获得配置文件的位置
        String[] configLocations = this.getConfigLocations();
        if (configLocations != null) {
            reader.loadBeanDefinitions(configLocations);
        }

    }

//AbstractBeanDefinitionReader类,是XmlBeanDefinitionReader的父类
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
    //如果Resource为null,停止载入
		Assert.notNull(resources, "Resource array must not be null");
    //用于计数:成功载入多少个配置文件。
		int count = 0;
		for (Resource resource : resources) {
            //loadBeanDefinitions(resource)是载入配置文件,具体代码在下面。
			count += loadBeanDefinitions(resource);
		}
		return count;
	}

//XmlBeanDefinitionReader类
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
    //具体代码在下面。
		return loadBeanDefinitions(new EncodedResource(resource));
	}

//这里是载入xml形式的BeanDefinition的地方
public int loadBeanDefinitions(EncodedResource encodedResource) 
    throws BeanDefinitionStoreException {
		Assert.notNull(encodedResource, "EncodedResource must not be null");
		if (logger.isTraceEnabled()) {
			logger.trace("Loading XML bean definitions from " + encodedResource);
		}

		Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();

		if (!currentResources.add(encodedResource)) {
			throw new BeanDefinitionStoreException(
					"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
		}
	//这里得到XML文件,使用InputStream准备读取
		try (InputStream inputStream = encodedResource.getResource().getInputStream()) {
			InputSource inputSource = new InputSource(inputStream);
			if (encodedResource.getEncoding() != null) {
				inputSource.setEncoding(encodedResource.getEncoding());
			}
            //具体的读取过程在这个函数,具体代码在后面。
			return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException(
					"IOException parsing XML document from " + encodedResource.getResource(), ex);
		}
		finally {
			currentResources.remove(encodedResource);
			if (currentResources.isEmpty()) {
				this.resourcesCurrentlyBeingLoaded.remove();
			}
		}
	}

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
			throws BeanDefinitionStoreException {

		try {
            //这里取得XML文件的Document对象,这是通用的解析过程,这些document对象没有按照Spring的Bean规则进行解析
			Document doc = doLoadDocument(inputSource, resource);
            //registerBeanDefinitions是解析过程,会使用到Spring的Bean配置规则,具体请看下面的解析篇章。
            //registerBeanDefinitions对载入的Bean的数量进行了统计。
			int count = registerBeanDefinitions(doc, resource);
			if (logger.isDebugEnabled()) {
				logger.debug("Loaded " + count + " bean definitions from " + resource);
			}
			return count;
		}
		catch (BeanDefinitionStoreException ex) {
			throw ex;
		}
		catch (SAXParseException ex) {
			throw new XmlBeanDefinitionStoreException(resource.getDescription(),
					"Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
		}
		catch (SAXException ex) {
			throw new XmlBeanDefinitionStoreException(resource.getDescription(),
					"XML document from " + resource + " is invalid", ex);
		}
		catch (ParserConfigurationException ex) {
			throw new BeanDefinitionStoreException(resource.getDescription(),
					"Parser configuration exception parsing XML from " + resource, ex);
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException(resource.getDescription(),
					"IOException parsing XML document from " + resource, ex);
		}
		catch (Throwable ex) {
			throw new BeanDefinitionStoreException(resource.getDescription(),
					"Unexpected exception parsing XML document from " + resource, ex);
		}
	}

解析过程:

所谓bean的解析就是将我们的xml文件中的bean解析出来。

大致脑图:(具体看代码)

在这里插入图片描述
在这里插入图片描述

registerBeanDefinitions(Document doc, Resource resource)方法:

public int registerBeanDefinitions(Document doc, Resource resource) 
    throws BeanDefinitionStoreException {
    //BeanDefinitionDocumentReader来对xml的BeanDefination进行解析
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
    //获得之前已经解析了的Bean的数量.
		int countBefore = getRegistry().getBeanDefinitionCount();
    //具体解析过程在这个registerBeanDefinitions中完成,具体代码如下。
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}

//DefaultBeanDefinitionDocumentReader类的方法
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
	this.readerContext = readerContext;
	doRegisterBeanDefinitions(doc.getDocumentElement());
}

protected void doRegisterBeanDefinitions(Element root) {
		BeanDefinitionParserDelegate parent = this.delegate;
		this.delegate = createDelegate(getReaderContext(), root, parent);
	//这些if与else不知道干什么的,直接看后面。
		if (this.delegate.isDefaultNamespace(root)) {
			String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
			if (StringUtils.hasText(profileSpec)) {
				String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
						profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
				// We cannot use Profiles.of(...) since profile expressions are not supported
				// in XML config. See SPR-12458 for details.
				if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
					if (logger.isDebugEnabled()) {
						logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec +
								"] not matching: " + getReaderContext().getResource());
					}
					return;
				}
			}
		}
	//空方法。
		preProcessXml(root);
    //这个是重点方法,内有processBeanDefinition方法,分析xml配置文件,将Document封装成为BeanDefinitionHolder(这个是BeanDefinition的实现类,用来装一个个的Bean以及对应属性),然后把BeanDefinitionHolder装入到DefaultListableBeanFactory的currentHashMap上,同时也有键值对(别名,实际名称)装入到别名树(也是currentHashMap)。delegate是个委托类,具体的处理委托给了delegate(BeanDefinitionParserDelegate类),主要在processBeanDefinition方法中操作。
    //具体代码在下面
		parseBeanDefinitions(root, this.delegate);
		postProcessXml(root);

		this.delegate = parent;
	}

//直接看processBeanDefinition方法
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
		if (delegate.isDefaultNamespace(root)) {
			NodeList nl = root.getChildNodes();
			for (int i = 0; i < nl.getLength(); i++) {
				Node node = nl.item(i);
				if (node instanceof Element) {
					Element ele = (Element) node;
					if (delegate.isDefaultNamespace(ele)) {
                        //processBeanDefinition方法在这里,直接看这个就行了。
						parseDefaultElement(ele, delegate);
					}
					else {
						delegate.parseCustomElement(ele);
					}
				}
			}
		}
		else {
			delegate.parseCustomElement(root);
		}
	}

	private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
        //IMPORT_ELEMENT对应xml中的<import>
		if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
			importBeanDefinitionResource(ele);
		}
        //ALIAS_ELEMENT对应xml中的alias,也就是别名
		else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
            //别名注册
			processAliasRegistration(ele);
		}
        //BEAN_ELEMENT对应xml中的bean。
		else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
            //bean对象注册,具体代码在后面。
			processBeanDefinition(ele, delegate);
		}
        //NESTED_BEANS_ELEMENT对应xml中的beans。
		else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
			doRegisterBeanDefinitions(ele);
		}
	}

//这里就是处理BeanDefinition的地方,具体处理委托给BeanDefinitionParserDelegate类。Element对应xml中的元素
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
    //获得BeanDefinition的实现类BeanDefinitionHolder,里面有Bean对象以及别名以及属性等。得到这个BeanDefinitionHolder说明对xml元素的解析是按照Spring Bean规则的。
    //想看xml元素的解析可以自行去看parseBeanDefinitionElement这个方法。
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
			//这里是向DefaultListableBeanFactory的currentHashMap注册bean,也就是向IOC容器注册。
				BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error("Failed to register bean definition with name '" +
						bdHolder.getBeanName() + "'", ele, ex);
			}
			//在IOC容器注册完后,发送信息,现在暂时不理解为什么。
			getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
		}
	}

**总结:**BeanDefinitionHolder持有bean对象以及别名集合以及其他属性(多例单例,是否懒加载属性等),BeanDefinitionHolder的生成是通过Document文档树的内容进行解析得到的,这个解析过程是由BeanDefinitionParserDelegate来实现(具体在parseBeanDefinitionElement方法中实现),最后把BeanDefinitionHolder注册到DefaultListableBeanFactory这个IOC容器中。

现在在IOC容器中存在的还只是一些静态的配置信息,严格来说,这个时候的容器还没有完全起作用,要完全发挥容器的作用,还需完成数据向容器的注册。

1.3 IOC容器的注册

前面已经分析过BeanDefinition在IOC容器中载入和解析过程。在这些动作完成后,用户定义的BeanDefinition信息已经在IOC容器内建立起了自己的数据结构已经相应的数据表示,但这些数据还不能提供IOC容器直接使用,需要在IOC容器中对这些BeanDefinition数据进行注册

在IOC容器的DefaultListableBeanFactory中是通过一个HashMap来持有载入的BeanDefinition的。在DefaultListableBeanFactory定义可以看到,如下:

private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

将解析得到的BeanDefinition向IOC容器中的beanDefinitionMap注册的过程是在载入BeanDefinition完成后进行的,注册的调用过程图下:
在这里插入图片描述

在DefaultListableBeanFactory中实现了BeanDefinitionRegistry接口,这个接口实现完成BeanDefinition向容器的注册。这个注册不复杂,就是把解析得到的BeanDefinition设置到HashMap中去。

//这个方法是在DefaultListableBeanFactory中
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
	throws BeanDefinitionStoreException {

	Assert.hasText(beanName, "Bean name must not be empty");
	Assert.notNull(beanDefinition, "BeanDefinition must not be null");

	if (beanDefinition instanceof AbstractBeanDefinition) {
		try {
			((AbstractBeanDefinition) beanDefinition).validate();
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,"Validation of bean definition failed", ex);
		}
	}
	//获得beanDefinitionMap的key为beanName的对象
	BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
	if (existingDefinition != null) {  //如果不为空,说明之前已经创建了key为beanName的BeanDefinition
		if (!isAllowBeanDefinitionOverriding()) {   //如果不允许覆盖,抛出异常。
			throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
		}
		else if (existingDefinition.getRole() < beanDefinition.getRole()) {
			// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
			if (logger.isInfoEnabled()) {
				logger.info("Overriding user-defined bean definition for bean '" + beanName +
						"' with a framework-generated bean definition: replacing [" +
						existingDefinition + "] with [" + beanDefinition + "]");
			}
		}
		else if (!beanDefinition.equals(existingDefinition)) {
			if (logger.isDebugEnabled()) {
				logger.debug("Overriding bean definition for bean '" + beanName +
						"' with a different definition: replacing [" + existingDefinition +
						"] with [" + beanDefinition + "]");
			}
		}
		else {
			if (logger.isTraceEnabled()) {
				logger.trace("Overriding bean definition for bean '" + beanName +
						"' with an equivalent definition: replacing [" + existingDefinition +
						"] with [" + beanDefinition + "]");
			}
		}
        //将原来的BeanDefinition覆盖掉
		this.beanDefinitionMap.put(beanName, beanDefinition);
	}
	else {   //如果为空
		if (hasBeanCreationStarted()) {  //如果已经启动,我的理解:就是这个IOC容器已经投入使用了。
			synchronized (this.beanDefinitionMap) {  
                //我的意思:因为IOC容器已经投入使用了,使用期间可以有多个线程添加新的BeanDefinition对象,所以要在使用期间添加新的BeanDefinition对象需要加锁,updatedDefinitions是ArrayList类,是线程不安全。防止多个线程添加造成数据不一致。
				this.beanDefinitionMap.put(beanName, beanDefinition);
				List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
				updatedDefinitions.addAll(this.beanDefinitionNames);
				updatedDefinitions.add(beanName);
				this.beanDefinitionNames = updatedDefinitions;
				removeManualSingletonName(beanName);
			}
		}
		else {  //如果IOC容器仍在注册阶段。我的意思:只有单线程,所以不需要加锁。
			this.beanDefinitionMap.put(beanName, beanDefinition);
			this.beanDefinitionNames.add(beanName);
			removeManualSingletonName(beanName);
		}
		this.frozenBeanDefinitionNames = null;
	}

	if (existingDefinition != null || containsSingleton(beanName)) {
		resetBeanDefinition(beanName);
	}
	else if (isConfigurationFrozen()) {
		clearByTypeCache();
	}
}

通过注册阶段,把BeanDefinition加入到DefaultListableBeanFactory的beanDefinitionMap中。IOC容器建立整个Bean的配置信息,容器的作用就是对zhe’x信息进行处理和维护。这些信息是容器建立依赖反转的基础,所以下面将介绍依赖注入。

1.4 IOC容器的依赖注入

假设当前IOD容器已经载入了用户定义的信息,开始分析依赖注入原理。

单例对象存放的地方:
DefaultSingletonBeanRegistry类中:

private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

因为DefaultListableBeanFactory类继承AbstractBeanFactory,而AbstractBeanFactory继承DefaultSingletonBeanRegistry。所以DefaultListableBeanFactory有singletonObjects这个HashMap。

非懒加载的单例对象的依赖注入的过程是创建IOC容器并初始化对象时触发。
在BeanDefinition信息中通过控制 lazy-init 属性为true,则初始化对象在用户第一次向IOC容器索要的触发(同理,依赖注入也是在这个时候)。

在IOC容器的BeanFactory中,有一个getBean的接口定义,这个接口的实现就是触发依赖注入发生的地方。

太过复杂,以后需要慢慢琢磨。笔记还不会做…

1.5 IOC容器的三级缓存

DefaultSingletonBeanRegistry类中:

private final Map<String, Object> singletonObjects = new ConcurrentHashMap(256);   //一级缓存
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap(16);   //三级缓存
private final Map<String, Object> earlySingletonObjects = new HashMap(16);      //二级缓存

区别:

singletonObjects 存的是完整对象;earlySingletonObjects存的是实例化但还未初始化的对象;singletonFactories存的是 ObjectFactory<?>对象,也就是lambd表达式,程序在从三级缓存获取对象时会执行这个表达式从而产生对象。

三级缓存解决循环依赖:

假设类A的对象a,类B的对象b,a和b之间循环依赖,那么三级缓存解决循环依赖的步骤如下:

  1. 先从一级缓冲获取A单例,A单例不存在一级缓存且不在构造中(不在构造中也就是未开始实例化),则实例化a对象,然后将a对象存入三级缓存(实际存入三级缓存的是lambd表达式,这里为了易于理解所以描述为a对象),然后依赖注入a对象里的属性时,发现属性里的引用B是引用类型。
  2. 通过引用B这个属性,去一级缓存获取B单例,B单例不存在且不在构造中,则开始实例化b对象,然后将b对象存入三级缓存(也是lambd表达式),然后依赖注入b对象里的属性时,发现属性里的引用A时应用类型。
  3. 通过引用A这个属性,去一级缓存获取A单例(也就是a对象),A单例不存在但在构造中,则去二级缓存获取A单例,也不存在,则去三级缓存获取A单例,存在,则将a对象加入到二级缓存(这个不是lambd表达式,a对象是实例化但还没初始化的a对象)并把三级缓存中的a对象(lambd表达式)去除掉,然后拿a对象注入到b对象属性里的引用A,然后接着b对象的所有属性注入完成,将b对象放入一级缓存,然后将b对象返回。
  4. 因为以上是个递归调用过程,所以函数返回到第1步的a对象引用B属性依赖注入b对象,这时因为第3三步的返回结果获得b对象,然后执行依赖注入,接着依赖注入a对象的其他属性,完成后将a对象放入一级缓存,然后在二级缓存和三级缓存中移除a对象。

为什么需要三级缓存而不是二级缓存:
如果不考虑AOP,那么二级缓存就足够;如果二级缓存考虑AOP,那么 实例化但未初始化的对象 将存放于二级缓存,其代理对象也将如此,那么可能造成在 对象实例化但未初始化且还没产生代理对象的,某个程序可能拿到了这个对象,然后 这个对象产生了代理对象,另外其他程序就拿到这个代理对象,导致两个程序拿到的是不同对象。

三级缓存在AOP的运用:
第三级缓存存放的是lambd表达式,用来产生所对应的对象,而如果有配置AOP,那么所对应的代理对象就是在这个表达式产生的。在这个表达式中会判断这个对象有没有继承AbstractAutoProxyCreator(AbstractAutoProxyCreator是BeanPostProcessor的子类,AOP就是这样实现的),有则产生代理对象。这样在三级缓存中,每个程序拿到的都是这个lambd表达式,所以产生的都是同样的代理对象。

1.6 FactoryBean与BeanFactory

BeanFactory就是我们平时所说的IOC容器了。

FactoryBean是生产Bean的产品,继承了FactoryBean的对象要实现getObjectType()以及getObject()方法以及isSingleton()方法,getObjectType()这个方法是返回要生产对象的类型,getObject()这个方法返回的对象就是生产的Bean对象,isSingleton()这个方法返回这个要生产的对象是否单例。调用这个getObject()方法是在getBean(Class requiredType)这个方法中,参数requiredType是class类,在getBean中,首先判断IOC容器是否有这个requiredType类型的对象,如果没有,则从继承了FactoryBean的类查找,首先使用getObjectType()判断是否是自己要寻找的类型,若是则调用getObject()生成对象(getObject()因为是自己实现了,所以可以自定义一些操作),然后通过isSingleton()来判断这个对象是否是单例从而执行对应的操作,这样getBean(Class requiredType)方法就能获取到FactoryBean生产的对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值