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

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

程序员文章站 2022-05-23 14:16:24
...

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()方法:

定位及载入过程:

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

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

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

//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解析出来。

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

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

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完成后进行的,注册的调用过程图下:
spring底层源码分析-IOC容器的初始化过程

在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生产的对象。