Spring源码分析——Bean创建

  • 时间:
  • 来源:互联网
  • 文章标签:

文章目录

  • Spring源码分析——Bean创建
    • 一.示例代码
    • 二.步骤解析
      • 1.ClassPathXmlApplicationContext
      • 2.refresh()
      • 3.Bean加载
        • obtainFreshBeanFactory()
        • loadBeanDefinitions()
      • 4.单例Bean实例化
        • finishBeanFactoryInitialization
        • preInstantiateSingletons()
        • doGetBean()
        • getSingleton()

Spring源码分析——Bean创建

一.示例代码

spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="beanTest" class="com.sk.spring.BeanTest">
        <constructor-arg name="name" value="sk"/>
        <constructor-arg name="age" value="28"/>
    </bean>

    <bean class="com.sk.spring.AutowiredTest">
        <constructor-arg name="beanTest" ref="beanTest" />
    </bean>
</beans>

获取bean:

public static void main(String[] args) {
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
    AutowiredTest beanTest = context.getBean(AutowiredTest.class);
    beanTest.hello();
}

二.步骤解析

1.ClassPathXmlApplicationContext

读取spring配置使用ApplicationContext来进行读取创建,类关系图如下

在这里插入图片描述

这里我们从resource下读取xml配置,因此使用ClassPathXmlApplicationContext来读取配置文件spring.xml

public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
	this(new String[] {configLocation}, true, null);
}

public ClassPathXmlApplicationContext(
		String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
		throws BeansException {

	super(parent);
	setConfigLocations(configLocations);
	if (refresh) {
		refresh();
	}
}

调用构造函数ClassPathXmlApplicationContext(String configLocation) 时,调用重载的构造方法ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) ,并且设置参数:配置文件地址用字符串数组封装;设置refresh为true;parent为null。
于是在真正调用ClassPathXmlApplicationContext()构造方法时会执行setConfigLocations()和refresh()两个方法。

  • setConfigLocations():该方法调用其父类AbstractRefreshableConfigApplicationContext的setConfigLocations( String… locations),用于设置参数configLocations[]数组
  • refresh():该方法是读取配置并从配置装载bean的主要方法,主要用于解析配置和装载实例

2.refresh()

ClassPathXmlApplicationContext 中调用的refresh(),实际是调用其父类AbstractApplicationContext.refresh(),其代码如下

public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		// 准备此上下文刷新,主要用于数据初始化
		prepareRefresh();

		// 告诉子类刷新内部bean工厂,该方法包括创建beanFactory以及解析配置文件装载bean
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

		// 准备bean工厂以供在此上下文中使用
		prepareBeanFactory(beanFactory);

		try {
			// 允许子类对该上下文中的bean工厂进行后处理,方法为空
			postProcessBeanFactory(beanFactory);

			// 执行在上下文中注册的bean处理器
			invokeBeanFactoryPostProcessors(beanFactory);

			// 注册由拦截bean创建的bean处理器
			registerBeanPostProcessors(beanFactory);

			// 初始化此上下文的消息源
			initMessageSource();

			// 为此上下文初始化事件多主机
			initApplicationEventMulticaster();

			// 初始化子类中生命的其他特殊bean,该方法为空
			onRefresh();

			// 检查监听器bean并注册它们
			registerListeners();

			// 实例化所有剩余的(非延迟初始化)单例
			finishBeanFactoryInitialization(beanFactory);

			// 发布对应的事件
			finishRefresh();
		}

		catch (BeansException ex) {
			if (logger.isWarnEnabled()) {
				logger.warn("Exception encountered during context initialization - " +
						"cancelling refresh attempt: " + ex);
			}

			// Destroy already created singletons to avoid dangling resources.
			destroyBeans();

			// Reset 'active' flag.
			cancelRefresh(ex);

			// Propagate exception to caller.
			throw ex;
		}

		finally {
			// Reset common introspection caches in Spring's core, since we
			// might not ever need metadata for singleton beans anymore...
			resetCommonCaches();
		}
	}
}

3.Bean加载

obtainFreshBeanFactory()

在refresh()中首先通过obtainFreshBeanFactory 创建Bean工厂

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
	refreshBeanFactory();
	return getBeanFactory();
}

obtainFreshBeanFactory 中会先通过refreshBeanFactory 创建bean工厂,再通过getBeanFactory 返回创建的Bean工厂,所以重点关注refreshBeanFactory方法。debug代码最终调用其子类AbstractRefreshableApplicationContext的refreshBeanFactory方法

protected final void refreshBeanFactory() throws BeansException {
	if (hasBeanFactory()) {
		destroyBeans();
		closeBeanFactory();
	}
	try {
		DefaultListableBeanFactory beanFactory = createBeanFactory();
		beanFactory.setSerializationId(getId());
		customizeBeanFactory(beanFactory);
		loadBeanDefinitions(beanFactory);
		synchronized (this.beanFactoryMonitor) {
			this.beanFactory = beanFactory;
		}
	}
	catch (IOException ex) {
		throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
	}
}

refreshBeanFactory() 做了一下几件事:

  1. 判断是否已经创建了Bean工厂,如果已经创建了,删除并销毁该Bean工厂,重新创建
  2. 创建Bean工厂,实际创建类型为DefaultListableBeanFactory
  3. 序列化新的Bean工厂,并设置自定义属性(是否允许Bean覆盖和是否允许循环依赖)
  4. 加载Bean到该Bean工厂,在xml文件中定义的Bean加载都是在该方法中进行的

loadBeanDefinitions()

loadBeanDefinitionsAbstractRefreshableApplicationContext子类进行具体实现,实现该方法的子类有:AbstractXmlApplicationContextAnnotationConfigReactiveWebApplicationContextAnnotationConfigWebApplicationContextGroovyWebApplicationContextXmlWebApplicationContext

在这里插入图片描述

从ApplicationContext继承关系图可以看到,由于使用ClassPathXmlApplicationContext创建,并且ClassPathXmlApplicationContext类中并没有重写loadBeanDefinitions方法,因此调用其父类AbstractXmlApplicationContext.loadBeanDefinitions()。

在AbstractXmlApplicationContext.loadBeanDefinitions()中,会创建一个xml bean读取器XmlBeanDefinitionReader然后设置初始化后,调用类中loadBeanDefinitions(beanDefinitionReader)进行读取

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
	// Create a new XmlBeanDefinitionReader for the given BeanFactory.
	XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

	// Configure the bean definition reader with this context's
	// resource loading environment.
	beanDefinitionReader.setEnvironment(this.getEnvironment());
	beanDefinitionReader.setResourceLoader(this);
	beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

	// Allow a subclass to provide custom initialization of the reader,
	// then proceed with actually loading the bean definitions.
	initBeanDefinitionReader(beanDefinitionReader);
	loadBeanDefinitions(beanDefinitionReader);
}

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
	Resource[] configResources = getConfigResources();
	if (configResources != null) {
		reader.loadBeanDefinitions(configResources);
	}
	String[] configLocations = getConfigLocations();
	if (configLocations != null) {
		reader.loadBeanDefinitions(configLocations);
	}
}

从reader.loadBeanDefinitions(configLocations);这句可以看出,真正的解析bean是通过Bean读取器从对应的配置文件地址中进行读取的

在这里插入图片描述

层层进入loadBeanDefinitions后可以发现,将设置的字符串类型的配置文件地址location封装成Resource对象再通过XmlBeanDefinitionReader.loadBeanDefinitions(Resource resource)调用,最后调用XmlBeanDefinitionReader.loadBeanDefinitions(EncodedResource encodedResource)开始真正的加载。

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 == null) {
		currentResources = new HashSet<>(4);
		this.resourcesCurrentlyBeingLoaded.set(currentResources);
	}
	if (!currentResources.add(encodedResource)) {
		throw new BeanDefinitionStoreException(
				"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
	}
	try {
		InputStream inputStream = encodedResource.getResource().getInputStream();
		try {
			InputSource inputSource = new InputSource(inputStream);
			if (encodedResource.getEncoding() != null) {
				inputSource.setEncoding(encodedResource.getEncoding());
			}
			return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
		}
		finally {
			inputStream.close();
		}
	}
	catch (IOException ex) {
		throw new BeanDefinitionStoreException(
				"IOException parsing XML document from " + encodedResource.getResource(), ex);
	}
	finally {
		currentResources.remove(encodedResource);
		if (currentResources.isEmpty()) {
			this.resourcesCurrentlyBeingLoaded.remove();
		}
	}
}

从源码中可以看到最终通过doLoadBeanDefinitions(inputSource, encodedResource.getResource())开始真正的解析Bean过程

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
		throws BeanDefinitionStoreException {
	try {
		Document doc = doLoadDocument(inputSource, resource);
		int count = registerBeanDefinitions(doc, resource);
		if (logger.isDebugEnabled()) {
			logger.debug("Loaded " + count + " bean definitions from " + resource);
		}
		return count;
	}
	
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
	BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
	int countBefore = getRegistry().getBeanDefinitionCount();
	documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
	return getRegistry().getBeanDefinitionCount() - countBefore;
}
  1. 通过doLoadDocument()将xml文件解析成Document对象
  2. 创建BeanDefinitionDocumentReader对象,并调用该对象的registerBeanDefinitions方法从Document对象中解析并注册bean

在BeanDefinitionDocumentReader中调用doRegisterBeanDefinitions方法进行真正的解析xml

doRegisterBeanDefinitions:

protected void doRegisterBeanDefinitions(Element root) {
	BeanDefinitionParserDelegate parent = this.delegate;
	this.delegate = createDelegate(getReaderContext(), root, parent);

	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);
	parseBeanDefinitions(root, this.delegate);
	postProcessXml(root);

	this.delegate = parent;
}

方法中,首先创建委托对象来对Bean进行解析,并且在调用parseBeanDefinitions时使用了模板方法设计模式(preProcessXml(root)、postProcessXml(root)方法内为空,以后可用子类进行扩展),最终在parseDefaultElement中对在xml定义的不同类型标签进行解析,并将bean标签对应的结果封装到BeanDefinitionHolder对象中,再通过BeanDefinitionReaderUtils.registerBeanDefinition将BeanDefinitionHolder中的Bean注册到Bean工厂中,即调用DefaultListableBeanFactory.registerBeanDefinition并放入beanDefinitionMap对象中

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
	if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
		importBeanDefinitionResource(ele);
	}
	else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
		processAliasRegistration(ele);
	}
	else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
		processBeanDefinition(ele, delegate);
	}
	else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
		// recurse
		doRegisterBeanDefinitions(ele);
	}
}

至此,从配置文件解析Bean过程完成,并已将bean和对应的BeanDefinition存入Bean工厂中

AbstractApplicationContext.refresh()
->AbstractApplicationContext.obtainFreshBeanFactory()
-->AbstractRefreshableApplicationContext.refreshBeanFactory()
--->AbstractXmlApplicationContext.loadBeanDefinitions()
---->AbstractBeanDefinitionReader.loadBeanDefinitions()
----->XmlBeanDefinitionReader.loadBeanDefinitions()
------>XmlBeanDefinitionReader.doLoadBeanDefinitions()
------->XmlBeanDefinitionReader.registerBeanDefinitions()
-------->DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions()
--------->DefaultBeanDefinitionDocumentReader.parseBeanDefinitions()
---------->DefaultBeanDefinitionDocumentReader.parseDefaultElement()
----------->DefaultBeanDefinitionDocumentReader.processBeanDefinition()
------------>BeanDefinitionReaderUtils.registerBeanDefinition()
------------->DefaultListableBeanFactory.registerBeanDefinition()

在执行完obtainFreshBeanFactory()之后,得到beanFactory对象,可以看到在beanFactory对象的singletonObjects参数中并没有User对象的单例实例,在配置User的bean时默认时单例的,也就是说执行obtainFreshBeanFactory()并不会实例化单例对象

在这里插入图片描述

4.单例Bean实例化

finishBeanFactoryInitialization

实例化bean是放在finishBeanFactoryInitialization(beanFactory)方法中的。finishBeanFactoryInitialization方法中执行beanFactory.preInstantiateSingletons(),用于实例化所有非懒加载的单例bean

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
	// Initialize conversion service for this context.
	if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
			beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
		beanFactory.setConversionService(
				beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
	}

	// Register a default embedded value resolver if no bean post-processor
	// (such as a PropertyPlaceholderConfigurer bean) registered any before:
	// at this point, primarily for resolution in annotation attribute values.
	if (!beanFactory.hasEmbeddedValueResolver()) {
		beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
	}

	// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
	String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
	for (String weaverAwareName : weaverAwareNames) {
		getBean(weaverAwareName);
	}

	// Stop using the temporary ClassLoader for type matching.
	beanFactory.setTempClassLoader(null);

	// Allow for caching all bean definition metadata, not expecting further changes.
	beanFactory.freezeConfiguration();

	// Instantiate all remaining (non-lazy-init) singletons.
	beanFactory.preInstantiateSingletons();
}

preInstantiateSingletons()

在preInstantiateSingletons依次取出从xml解析的beanName,根据beanName从mergedBeanDefinitions获取该beanName对应的BeanDefinition,再判断该bean是否是抽象类对象、是否是单例对象、是否是懒加载,如果是懒加载则跳过实例化,在后面获取bean的时候再进行实例化,再判断该bean是否是FactoryBean工厂bean,由于User类不是工厂类,因此直接调用getBean(beanName),再调用AbstractBeanFactory.doGetBean()方法完成真正的获取bean对象过程

@Override
public void preInstantiateSingletons() throws BeansException {
	if (logger.isTraceEnabled()) {
		logger.trace("Pre-instantiating singletons in " + this);
	}

	// Iterate over a copy to allow for init methods which in turn register new bean definitions.
	// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
	List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

	// Trigger initialization of all non-lazy singleton beans...
	for (String beanName : beanNames) {
		RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
		if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
		……
		}
	}
}

doGetBean()

在doGetBean()中会经过一系列判断最终来到是否单例判断这里,在方法内调用了getSingleton()方法,并在获取单例对象前通过createBean()创建了bean并进行初始化赋值

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
		@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
	// Create bean instance.
	if (mbd.isSingleton()) {
		sharedInstance = getSingleton(beanName, () -> {
			try {
				return createBean(beanName, mbd, args);
			}
			catch (BeansException ex) {
				// Explicitly remove instance from singleton cache: It might have been put there
				// eagerly by the creation process, to allow for circular reference resolution.
				// Also remove any beans that received a temporary reference to the bean.
				destroySingleton(beanName);
				throw ex;
			}
		});
		bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
	}
}

getSingleton()

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
	Assert.notNull(beanName, "Bean name must not be null");
	synchronized (this.singletonObjects) {
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null) {
			if (this.singletonsCurrentlyInDestruction) {
				throw new BeanCreationNotAllowedException(beanName,
						"Singleton bean creation not allowed while singletons of this factory are in destruction " +
						"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
			}
			if (logger.isDebugEnabled()) {
				logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
			}
			beforeSingletonCreation(beanName);
			boolean newSingleton = false;
			boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
			if (recordSuppressedExceptions) {
				this.suppressedExceptions = new LinkedHashSet<>();
			}
			try {
				singletonObject = singletonFactory.getObject();
				newSingleton = true;
			}
			catch (IllegalStateException ex) {
				// Has the singleton object implicitly appeared in the meantime ->
				// if yes, proceed with it since the exception indicates that state.
				singletonObject = this.singletonObjects.get(beanName);
				if (singletonObject == null) {
					throw ex;
				}
			}
			catch (BeanCreationException ex) {
				if (recordSuppressedExceptions) {
					for (Exception suppressedException : this.suppressedExceptions) {
						ex.addRelatedCause(suppressedException);
					}
				}
				throw ex;
			}
			finally {
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = null;
				}
				afterSingletonCreation(beanName);
			}
			if (newSingleton) {
				addSingleton(beanName, singletonObject);
			}
		}
		return singletonObject;
	}
}
  1. 先从beanFactory的singletonObjects中获取,如果结果不为空,返回结果,如果为空向下执行
  2. 执行singletonObject = singletonFactory.getObject()获取bean实例化对象,并将newSingleton设置为true表示新创建的单例对象
  3. 最后根据newSingleton标志位将新的单例对象添加进beanFactory的singletonObjects和registeredSingletons中
protected void addSingleton(String beanName, Object singletonObject) {
	synchronized (this.singletonObjects) {
		this.singletonObjects.put(beanName, singletonObject);
		this.singletonFactories.remove(beanName);
		this.earlySingletonObjects.remove(beanName);
		this.registeredSingletons.add(beanName);
	}
}

本文链接http://www.taodudu.cc/news/show-83004.html