后续的Spring内容在我的公众号《魔法师和ta的南瓜小屋》或简书其他文章详细介绍。
Spring中最重要的函数实现refresh()函数,Spring中两项核心——控制反转(IoC)和面向切面编程(AOP)——就是在这里实现完成的。BeanFactory和BeanDefinition在Spring和Spring Boot中作用是完全相同的。下面源代码选自Spring 5.2.2.RELEASE版本,以Spring xml文件配置Bean为示例(Spring Boot依赖注解)。由于目前Spring Boot已经逐渐取代原来基于xml配置的Spring,渐渐成为各大互联网或软件公司的主力框架。为了贴合实际应用,会插入Spring Boot区别的地方。
BeanFactory
BeanFactory顾名思义就是“生成Bean的工厂”,Spring通过BeanFactory对Bean进行创建。
refresh()函数中调用obtainFreshBeanFactory()获取BeanFactory实例。
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
return getBeanFactory();
}
抽象类AbstractRefreshableApplicationContext具体实现refreshBeanFactory()函数,默认的BeanFactory对象为DefaultListableBeanFactory类。
//Spring
@Override
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);
}
}
而在Spring Boot中虽然也经过了函数obtainFreshBeanFactory(),但是调用的是类GenericApplicationContext refreshBeanFactory()函数。此时BeanFactory对象实际已经创建完成,仅仅设置SerializationId。BeanFactory对象的创建在GenericApplicationContext的无参数构造函数中。
//Spring Boot
@Override
protected final void refreshBeanFactory() throws IllegalStateException {
if (!this.refreshed.compareAndSet(false, true)) {
throw new IllegalStateException(
"GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
}
this.beanFactory.setSerializationId(getId());
}
这是Spring Boot相较于Spring的一个改动,Spring Boot将BeanFactory对象的创建提前到了上下文创建时。相同的是默认的BeanFactory对象都是DefaultListableBeanFactory类。
BeanDefinition
BeanDefinition是“Bean在Spring中的描述”。Spring解析配置文件、注解等获取需要注入的Bean信息,使用BeanDefinition结构存储这些Bean的信息,包括Bean的名字,是否是单例,属性值,构造方法等等。之后从这些BeanDefinition获取需要的信息对Bean进行实例化。
Spring在函数obtainFreshBeanFactory()中完成xml配置信息向BeanDefinition转化。
调用AbstractApplicationContext类中的函数obtainFreshBeanFactory()。
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
return getBeanFactory();
}
类AbstractRefreshableApplicationContext中的refreshBeanFactory()函数。
@Override
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);
}
}
从loadBeanDefinitions()函数开始,按照如下路径找到类XmlBeanDefinitionReader中的函数doLoadBeanDefinitions()。
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;
}
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);
}
}
获取Document实例,注册BeanDefinition信息。
Document doc = doLoadDocument(inputSource, resource);
int count = registerBeanDefinitions(doc, resource);
走到类XmlBeanDefinitionReader中的函数registerBeanDefinitions()。
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;
}
然后类DefaultBeanDefinitionDocumentReader中的registerBeanDefinitions()。
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
doRegisterBeanDefinitions(doc.getDocumentElement());
}
类DefaultBeanDefinitionDocumentReader中的doRegisterBeanDefinitions()。创建delegate对象是用于解析xml文件中Bean的定义,parseBeanDefinitions()函数具体执行xml配置到BeanDefinition结构的转换。
protected void doRegisterBeanDefinitions(Element root) {
// Any nested <beans> elements will cause recursion in this method. In
// order to propagate and preserve <beans> default-* attributes correctly,
// keep track of the current (parent) delegate, which may be null. Create
// the new (child) delegate with a reference to the parent for fallback purposes,
// then ultimately reset this.delegate back to its original (parent) reference.
// this behavior emulates a stack of delegates without actually necessitating one.
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;
}
类DefaultBeanDefinitionDocumentReader中函数parseBeanDefinitions(),由于是默认标签,之后调用parseDefaultElement()方法。自定义标签则调用delegate.parseCustomElement()。
在parseDefaultElement()方法中依据标签的不同注册为对应的BeanDefinition结构。
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);
}
}
Spring Boot中,BeanDefinition的注册是在函数invokeBeanFactoryPostProcessors()中完成的。公众号中其他文章会详细介绍Spring Boot的invokeBeanFactoryPostProcessors()函数以及Spring Boot。
//Spring Boot
//Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);