- 前言
- BeanFactory
- BeanDefinition
- 1. prepareRefresh()
- 2. obtainFreshBeanFactory()
- `loadBeanDefinitions(beanFactory)`
- `loadBeanDefinitions(beanDefinitionReader)`
- `reader.loadBeanDefinitions(configLocations)`
- `loadBeanDefinitions(location)`
- `loadBeanDefinitions(resources)`
- `doLoadBeanDefinitions(inputSource, resource())`
- `registerBeanDefinitions(doc, createReaderContext(resource))`
- `parseBeanDefinitions(root, this.delegate)`
- `processBeanDefinition(ele, delegate)`
- `parseBeanDefinitionElement(ele)`
- `registerBeanDefinition(bdHolder, getReaderContext().getRegistry())`
- 总结
源码阅读传送门
- Spring IOC容器初始化源码剖析(一)
上一章我们了解了IOC容器的相关概念、如何通过代码实例化容器以及容器初始化的核心方法refresh(),本章开始初探refresh(),在阅读源码前,我们有必要先了解什么是BeanFactory以及BeanDefinition,这将有利于我们对接来下源码的理解。
BeanFactoryBeanFactory顾名思义,Bean的工厂,用于创建与管理Bean。
从上图我们可以看到ApplicationContext继承了两个BeanFactory的子接口:
- ListableBeanFactory:listable(可列举的),BeanFactory只能获取单个Bean,ListableBeanFactory可以获取多个Bean。
- HierarchicalBeanFactory:hierarchical(分层),可以通过配置的方式设置父类的bean工厂。
Spring IOC容器管理一个或多个Bean,这些bean使用提供给容器的配置元数据创建的(例如通过xml定义的形式)。在容器本身,这些Bean表示为BeanDefinition对象。
BeanDefinition主要包含哪些信息呢?
- 包限定名,通常是定义bean的具体实现类。
- bean行为配置元素,比如:范围、生命周期回调等。
- 对bean执行工作所需的其它bean引用(依赖)。
- 要在新创建对象中设置的其它配置,比如数据库连接池bean的连接数大小等。
源码如下:
public interface BeanDefinition extends AttributeAccessor, BeanmetadataElement {
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
int ROLE_APPLICATION = 0;
int ROLE_SUPPORT = 1;
int ROLE_INFRASTRUCTURE = 2;
// Modifiable attributes
void setParentName(@Nullable String parentName);
@Nullable
String getParentName();
void setBeanClassName(@Nullable String beanClassName);
@Nullable
String getBeanClassName();
void setScope(@Nullable String scope);
@Nullable
String getScope();
void setLazyInit(boolean lazyInit);
boolean isLazyInit();
void setDependsOn(@Nullable String... dependsOn);
@Nullable
String[] getDependsOn();
void setAutowireCandidate(boolean autowireCandidate);
boolean isAutowireCandidate();
void setPrimary(boolean primary);
boolean isPrimary();
void setFactoryBeanName(@Nullable String factoryBeanName);
@Nullable
String getFactoryBeanName();
void setFactoryMethodName(@Nullable String factoryMethodName);
@Nullable
String getFactoryMethodName();
ConstructorArgumentValues getConstructorArgumentValues();
default boolean hasConstructorArgumentValues() {
return !getConstructorArgumentValues().isEmpty();
}
MutablePropertyValues getPropertyValues();
default boolean hasPropertyValues() {
return !getPropertyValues().isEmpty();
}
void setInitMethodName(@Nullable String initMethodName);
@Nullable
String getInitMethodName();
void setDestroyMethodName(@Nullable String destroyMethodName);
@Nullable
String getDestroyMethodName();
void setRole(int role);
int getRole();
void setDescription(@Nullable String description);
@Nullable
String getDescription();
// Read-only attributes
ResolvableType getResolvableType();
boolean isSingleton();
boolean isPrototype();
boolean isAbstract();
@Nullable
String getResourceDescription();
@Nullable
BeanDefinition getOriginatingBeanDefinition();
}
1. prepareRefresh()
prepareRefresh()是refresh()的第一个方法,prepareRefresh()主要用于设置启动开始时间、活动标志位、初始化环境配置参数、校验参数等,来为初始化做好准备。
// AbstractApplicationContext#prepareRefresh()
protected void prepareRefresh() {
// 记录当前时间戳,切换活动状态
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
// 部分省略日志打印
// 初始化环境配置参数
// 当前类方法本身do nothing,
// 通过重写初始化环境属性信息。
initPropertySources();
// 获取initPropertySources中初始化的环境配置参数,
// 来进行验证标记为required的属性
getEnvironment().validateRequiredProperties();
// 载入预刷新应用程序监听
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new linkedHashSet<>(this.applicationListeners);
}
else {
// 将本地应用程序监听器重置为预刷新状态。
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// 允许早期应用事件收集,
// 当multicaster可用就会发布
this.earlyApplicationEvents = new linkedHashSet<>();
}
// AbstractApplicationContext#initPropertySources
protected void initPropertySources() {
// For subclasses: do nothing by default.
}
// AbstractPropertyResolver#validateRequiredProperties
@Override
public void validateRequiredProperties() {
MissingRequiredPropertiesException ex = new MissingRequiredPropertiesException();
for (String key : this.requiredProperties) {
// 判断必需的环境配置参数是否为空
if (this.getProperty(key) == null) {
ex.addMissingRequiredProperty(key);
}
}
if (!ex.getMissingRequiredProperties().isEmpty()) {
throw ex;
}
}
prepareRefresh()大致流程如下:
- 记录当前时间戳并设置活动状态。
- 初始环境配置参数,校验必需的配置参数。(校验未通过则抛出MissingRequiredPropertiesException: The following properties were declared as required but could not be resolved: [缺失的配置参数数组])
- 初始化或清除并载入应用程序监听(ApplicationListener)。
- 初始化事件(ApplicationEvent)。
obtain(获得)fresh(最新的)BeanFactory,该方法中会解析配置元数据,生成BeanDefinition,并注册到BeanFactory中。
该方法链路比较长,最好结合源码一起看,接下来进入正题。
//AbstractApplicationContext#ConfigurableListableBeanFactory()
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 配置加载
refreshBeanFactory();
// 获取BeanFactory并返回
return getBeanFactory();
}
// AbstractRefreshableApplicationContext#refreshBeanFactory()
@Override
protected final void refreshBeanFactory() throws BeansException {
// 判断BeanFactory是否已经创建
if (hasBeanFactory()) {
// 销毁所有已创建的bean
destroyBeans();
// 将BeanFactory置空
closeBeanFactory();
}
try {
// 默认实现创建DefaultListableBeanFactory,
// 并将容器的父级内部bean工厂作为父bean工厂
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
// 1.设置是否允许覆盖同名bean定义,自动替换前一个定义。
// 2.设置是否允许bean之间循环引用。
customizeBeanFactory(beanFactory);
// 加载配置转换为BeanDefinition注册到beanFactory
loadBeanDefinitions(beanFactory);
this.beanFactory = beanFactory;
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
通过如上refreshBeanFactory()源码,我们可以了解到大致流程:
-
判断BeanFactory是否已经创建,若已经创建则销毁所有已创建的bean、并把beanFactory置空。
// AbstractRefreshableApplicationContext#hasBeanFactory() protected final boolean hasBeanFactory() { return (this.beanFactory != null); } -
创建DefaultListableBeanFactory(该类为BeanFactory的一个默认实现),并将其设置为容器的parentBeanFactory。
-
customizeBeanFactory()设置是否允许覆盖bean定义及bean之间的循环引用。
// AbstractRefreshableApplicationContext#customizeBeanFactory protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) { // 设置是否允许同名bean定义覆盖,true:自动替换前一个定义。 if (this.allowBeanDefinitionOverriding != null) { beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding); } // 设置是否允许bean之间循环引用。 if (this.allowCircularReferences != null) { beanFactory.setAllowCircularReferences(this.allowCircularReferences); } } -
loadBeanDefinitions(beanFactory)读取配置元数据转换为BeanDefinition注册到beanFactory。
IOC容器管理了一个或多个Bean。在容器本身,这些bean表示为BeanDefinition对象,容器启动过程中,会将Bean解析为BeanDefinition注册到beanFactory中。
loadBeanDefinitions(beanFactory)开始套娃···
// AbstractXmlApplicationContext#loadBeanDefinitions
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// 配置beanDefinitionReader与context在同一环境中
beanDefinitionReader.setEnvironment(this.getEnvironment());
// 使用当前上下文对象作为beanDefinitionReader的ResourceLoader
beanDefinitionReader.setResourceLoader(this);
// 设置用于解析的SAX实体解析器,比如解析dtd、xsd文件
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// 初始化beanDefinitionReader
// 默认开启XML验证
initBeanDefinitionReader(beanDefinitionReader);
// 通过beanDefinitionReader加载BeanDefinition
// 加载配置转换为BeanDefinition注册到beanFactory
loadBeanDefinitions(beanDefinitionReader);
}
loadBeanDefinitions(beanFactory)大致步骤:
- 实例化XmlBeanDefinitionReader(读取通过Xml文件中配置Bean定义的工具类)、属性配置。
- 加载配置转换为BeanDefinition注册到beanFactory。
// AbstractXmlApplicationContext#loadBeanDefinitions
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
// 可以通过子类重写getConfigResources的方式指定配置文件数组,
// getConfigResources()默认返回null
Resource[] configResources = getConfigResources();
if (configResources != null) {
// 从指定配置资源中加载Bean
reader.loadBeanDefinitions(configResources);
}
// 获取本地配置文件
String[] configLocations = getConfigLocations();
if (configLocations != null) {
// 从指定配置文件中加载Bean
reader.loadBeanDefinitions(configLocations);
}
}
loadBeanDefinitions(beanDefinitionReader)大致步骤如下:
- 在子类重写getConfigResources()方法的前提下,通过重写方法指定逻辑获取配置文件数组(默认返回null),从指定配置文件中加载Bean。
// AbstractXmlApplicationContext#getConfigResources @Nullable protected Resource[] getConfigResources() { return null; } - 获取本地配置文件,从指定配置文件中解析并加载Bean。
// AbstractBeanDefinitionReader#loadBeanDefinitions
// 返回所有注册BeanDefinition的个数
@Override
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
Assert.notNull(locations, "Location array must not be null");
int count = 0;
for (String location : locations) {
count += loadBeanDefinitions(location);
}
return count;
}
继续朝下追踪loadBeanDefinitions(location)的内部处理逻辑。
loadBeanDefinitions(location)// AbstractBeanDefinitionReader#loadBeanDefinitions
@Override
public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
return loadBeanDefinitions(location, null);
}
// AbstractBeanDefinitionReader#loadBeanDefinitions public int loadBeanDefinitions(String location, @Nullable SetactualResources) throws BeanDefinitionStoreException { // 获取资源加载器 ResourceLoader resourceLoader = getResourceLoader(); // 部分省略 if (resourceLoader instanceof ResourcePatternResolver) { try { // 使用资源解析器根据资源文件路径解析并加载 Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location); // 解析当前资源中的bean定义, // 并返回注册BeanDefinition个数 int count = loadBeanDefinitions(resources); // 若actualResources不为null,则把文件资源添加到集合中 if (actualResources != null) { Collections.addAll(actualResources, resources); } // 部分省略 // 返回注册个数 return count; } catch (IOException ex) { throw new BeanDefinitionStoreException("Could not resolve bean definition resource pattern [" + location + "]", ex); } } else { Resource resource = resourceLoader.getResource(location); int count = loadBeanDefinitions(resource); if (actualResources != null) { actualResources.add(resource); } // 部分省略 return count; } }
loadBeanDefinitions(location, null)大致流程如下:
-
getResourceLoader()获得资源加载器。
@Override @Nullable public ResourceLoader getResourceLoader() { // this.resourceLoader即AbstractXmlApplicationContext。 // 前面源码中有讲解, // 没有印象的可以再去回顾AbstractXmlApplicationContext#loadBeanDefinitions return this.resourceLoader; } -
loader instanceof ResourcePatternResolver = true
-
通过资源解析器根据资源文件路径解析并加载(该节点以下的源码,感兴趣可以看看,不感兴趣可以直接跳过)。
// PathMatchingResourcePatternResolver#getResources // 根据指定配置文件路径获取文件资源数组 @Override public Resource[] getResources(String locationPattern) throws IOException { // 部分省略 // 判断文件路径是否以‘classpath*’开头 // CLASSPATH_ALL_URL_PREFIX:classpath*: // “classpath*:”代表:该工程有多个classpath,同时寻找并加载多个classpath路径下的文件 // “classpath:” 代表: 与上反之 if (locationPattern.startsWith(CLASSPATH_ALL_URL_PREFIX)) { // 判断截取“classpath*:”后的文件路径是否包含“*”或“?”或“{”或“}” // 例如:配置为:“classpath*:config") + 1 : locationPattern.indexOf(':') + 1); // 判断是否包含特殊字符 if (getPathMatcher().isPattern(locationPattern.substring(prefixEnd))) { return findPathMatchingResources(locationPattern); } else { // 单文件根据名称加载 // 我们的demo中直接走这个分支 return new Resource[] {getResourceLoader().getResource(locationPattern)}; } } }具体查找文件的方法就不继续延伸了,有兴趣的可以展开阅读。
-
loadBeanDefinitions(resources)解析资源所有的bean定义,并返回注册成功BeanDefinition个数。
我们继续追踪loadBeanDefinitions(resources)的内部处理逻辑。
// AbstractBeanDefinitionReader#loadBeanDefinitions
@Override
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
Assert.notNull(resources, "Resource array must not be null");
int count = 0;
for (Resource resource : resources) {
count += loadBeanDefinitions(resource);
}
return count;
}
// XmlBeanDefinitionReader#loadBeanDefinitions
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
return loadBeanDefinitions(new EncodedResource(resource));
}
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
// 部分省略
Set currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
// 获取资源文件字节流
try (InputStream inputStream = encodedResource.getResource().getInputStream()) {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
// 从XML资源中加载BeanDefinitions
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();
}
}
}
如上代码大致流程如下:
- 获取当前文件字节流,实例化InputSource。
// InputSource public InputSource (InputStream byteStream){ setByteStream(byteStream); } public void setByteStream (InputStream byteStream){ this.byteStream = byteStream; } - 设置资源编码格式,真正开始执行XML解析动作。
做了这么多准备动作,终于开始进入实际的加载,我们继续。
doLoadBeanDefinitions(inputSource, resource())// XmlBeanDefinitionReader#doLoadBeanDefinitions
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
// 转换为document对象
document doc = doLoaddocument(inputSource, resource);
// 获取注册成功的BeanDefinition
int count = registerBeanDefinitions(doc, resource);
// 部分省略
return count;
}
// 部分省略
}
如何完成注册呢?
// XmlBeanDefinitionReader#registerBeanDefinitions
public int registerBeanDefinitions(document doc, Resource resource) throws BeanDefinitionStoreException {
// 通过反射实例化并返回BeanDefinitiondocumentReader对象,
// 该对象用于解析xml格式的bean定义
BeanDefinitiondocumentReader documentReader = createBeanDefinitiondocumentReader();
// 获取当前已经注册的BeanDefinition个数
int countBefore = getRegistry().getBeanDefinitionCount();
// 注册BeanDefinition
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
// 返回当前注册成功的BeanDefinition个数
return getRegistry().getBeanDefinitionCount() - countBefore;
}
以上流程大致如下:
- 通过反射实例化并返回用于解析xml格式的bean定义BeanDefinitiondocumentReader对象。
- 注册BeanDefinition。
- 返回当前注册成功的BeanDefinition个数。
接下来我们来简单看看xml配置元数据的解析步骤。
// DefaultBeanDefinitiondocumentReader#registerBeanDefinitions
@Override
public void registerBeanDefinitions(document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
doRegisterBeanDefinitions(doc.getdocumentElement());
}
// DefaultBeanDefinitiondocumentReader#doRegisterBeanDefinitions
@SuppressWarnings("deprecation") // for Environment.acceptsProfiles(String...)
protected void doRegisterBeanDefinitions(Element root) {
// 任何的元素都会在此方法递归。
// 若当前parent为空则创建子delegate,并引用父delegate
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(getReaderContext(), root, parent);
// 确定给定的节点是否表明默认命名空间。
// 也就是我们配置文件的 的xmlns属性“http://www.springframework.org/schema/beans”
if (this.delegate.isDefaultNamespace(root)) {
// 获取当前 的profile属性名
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
// 判空
if (StringUtils.hasText(profileSpec)) {
// MULTI_VALUE_ATTRIBUTE_DELIMITERS=“,; ”
// 按照","或";"或" "作为分隔符分割
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
// 获取spring.profiles.active属性值,判断specifiedProfiles是否包含,false则return
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
// 部分省略
return;
}
}
}
// 空方法,可以通过重写的方式前置处理
preProcessXml(root);
// 开始解析
parseBeanDefinitions(root, this.delegate);
// 空方法,通过重写后置处理
postProcessXml(root);
this.delegate = parent;
}
大致步骤如下:
-
创建BeanDefinitionParserDelegate,它是用于解析资源文件的委托类。
-
isDefaultNamespace(root)检查被定义的命名空间是否是默认命名空间。
// BeanDefinitionParserDelegate public boolean isDefaultNamespace(Node node) { return isDefaultNamespace(getNamespaceURI(node)); } // 这边获取到的就是的xmlns属性,xmlns:命名空间 @Nullable public String getNamespaceURI(Node node) { return node.getNamespaceURI(); } // BEANS_NAMESPACE_URI = "http://www.springframework.org/schema/beans" public boolean isDefaultNamespace(@Nullable String namespaceUri) { return !StringUtils.hasLength(namespaceUri) || BEANS_NAMESPACE_URI.equals(namespaceUri); } -
第二步若为true则获取
的profile属性值,若该属性值不为空,进行检查当前节点是否满足环境配置。profile用于指定当前运行环境的启用配置。 示例:
public class XmlTest { static ApplicationContext context; static { context = new ClassPathXmlApplicationContext("classpath*:config @Nullable public AbstractBeanDefinition parseBeanDefinitionElement( Element ele, String beanName, @Nullable BeanDefinition containingBean) { this.parseState.push(new BeanEntry(beanName)); String className = null; // 判断是否存在class属性 if (ele.hasAttribute(CLASS_ATTRIBUTE)) { className = ele.getAttribute(CLASS_ATTRIBUTE).trim(); } String parent = null; // 判断是否存在parent属性。 if (ele.hasAttribute(PARENT_ATTRIBUTE)) { parent = ele.getAttribute(PARENT_ATTRIBUTE); } try { // 创建AbstractBeanDefinition AbstractBeanDefinition bd = createBeanDefinition(className, parent); // 将上定义的属性set到bd对象 parseBeanDefinitionAttributes(ele, beanName, containingBean, bd); bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DEscriptION_ELEMENT)); // 解析 parsemetaElements(ele, bd); // 解析 parseLookupOverrideSubElements(ele, bd.getMethodOverrides()); // 解析 parseReplacedMethodSubElements(ele, bd.getMethodOverrides()); // 解析 parseConstructorArgElements(ele, bd); // 解析 parsePropertyElements(ele, bd); // 解析 parseQualifierElements(ele, bd); // 设置对应配置文件Resource bd.setResource(this.readerContext.getResource()); bd.setSource(extractSource(ele)); return bd; } // 部分省略 finally { this.parseState.pop(); } return null; } 我们先回顾一下
标签的属性及子标签: 标签属性 id 设置在容器中的唯一标识 name bean的名称定义 class 类全限定名 scope singleton:默认单例;prototype:多例 init-method 类初始化方法 destory-method 类销毁方法 parent 指代“父bean”,不指代父类。 primary 是否注入优先,默认:false abstract 声明为抽象bean depends-on 声明该bean与其它bean的依赖关系 factory-bean 指定bean工厂 factory-method 指定bean工厂方法 autowire 自动装配模式(1)no:默认值;(2)byName:根据bean名称自动装配;(3)byType:按照类型进行装配;(4)constructor:通过构造器自动装配;(5)default:使用 的default-autowire属性配置。 autowire-candidate 默认为true,表示允许自动装配注入到其它bean lazy-init 默认为false,表示在IOC容器启动的时候进行实例化;true,则代表使用的时候进行实例化。 标签的子标签 源数据设置 bean成员变量属性设置 构造方法参数设置 描述信息 方法注入 指定注入bean名称 方法替换 大致流程如下:
- 创建AbstractBeanDefinition。
- 解析
属性。 // BeanDefinitionParserDelegate#parseBeanDefinitionAttributes public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName, @Nullable BeanDefinition containingBean, AbstractBeanDefinition bd) { // 判断是否存在single属性配置 if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) { error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele); } // 是否存在scope属性 else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) { bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE)); } else if (containingBean != null) { // Take default from containing bean in case of an inner bean definition. bd.setScope(containingBean.getScope()); } // 是否存在abstract属性 if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) { bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE))); } // 设置lazt-init属性,默认false String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE); if (isDefaultValue(lazyInit)) { lazyInit = this.defaults.getLazyInit(); } bd.setLazyInit(TRUE_VALUE.equals(lazyInit)); // 设置自动装配模式默认为0及默认自动装配 String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE); bd.setAutowireMode(getAutowireMode(autowire)); // 是否存在depends-on属性 if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) { String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE); bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS)); } // 是否存在autowire-candidate属性,默认为true String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE); if (isDefaultValue(autowireCandidate)) { String candidatePattern = this.defaults.getAutowireCandidates(); if (candidatePattern != null) { String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern); bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName)); } } else { bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate)); } // 是否存在primary属性 if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) { bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE))); } // 是否存在init-method属性 if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) { String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE); bd.setInitMethodName(initMethodName); } else if (this.defaults.getInitMethod() != null) { bd.setInitMethodName(this.defaults.getInitMethod()); bd.setEnforceInitMethod(false); } // 是否存在destroy-method属性 if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) { String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE); bd.setDestroyMethodName(destroyMethodName); } else if (this.defaults.getDestroyMethod() != null) { bd.setDestroyMethodName(this.defaults.getDestroyMethod()); bd.setEnforceDestroyMethod(false); } // 是否存在factory-method属性 if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) { bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE)); } // 是否存在factory-bean属性 if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) { bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE)); } return bd; } - 解析
子标签(源码就不在这里贴了,可以自行查看)。 - 返回解析并组装完毕后的AbstractBeanDefinition。
BeanDefinition已经获取到了,接下来就进行到注册这一步了,接下来我们来查看它的处理逻辑。
registerBeanDefinition(bdHolder, getReaderContext().getRegistry())// BeanDefinitionParserDelegate#registerBeanDefinition public static void registerBeanDefinition( BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException { // 使用beanName注册BeanDefinition String beanName = definitionHolder.getBeanName(); registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); // 别名注册 String[] aliases = definitionHolder.getAliases(); if (aliases != null) { for (String alias : aliases) { registry.registerAlias(beanName, alias); } } }跟进查看注册逻辑:
// DefaultListableBeanFactory#registerBeanDefinition @Override 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 { // beanDefinition校验 ((AbstractBeanDefinition) beanDefinition).validate(); } // 部分省略 } // 按beanName从beanDefinitionMap获取beanDefinition BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName); if (existingDefinition != null) { // 若根据beanName可以获取到beanDefinition, // 则判断该beanDefinition是否允许覆盖 if (!isAllowBeanDefinitionOverriding()) { throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition); } // 部分省略 // 允许覆盖的前提下,将当前beanDefinition放到beanDefinitionMap中 this.beanDefinitionMap.put(beanName, beanDefinition); } else { // 检查是否存在被标记为已创建状态的bean if (hasBeanCreationStarted()) { // Cannot modify startup-time collection elements anymore (for stable iteration) synchronized (this.beanDefinitionMap) { this.beanDefinitionMap.put(beanName, beanDefinition); ListupdatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1); updatedDefinitions.addAll(this.beanDefinitionNames); updatedDefinitions.add(beanName); this.beanDefinitionNames = updatedDefinitions; removeManualSingletonName(beanName); } } else { // 进入启动注册阶段 // key:beanName,value:BeanDefinition,将当前beanDefinition放到beanDefinitionMap中 this.beanDefinitionMap.put(beanName, beanDefinition); // 将BeanDefinition的名称add到beanDefinitionNames中(for) this.beanDefinitionNames.add(beanName); // 处理environment、systemProperties、systemEnvironment、applicationStartup等bean removeManualSingletonName(beanName); } this.frozenBeanDefinitionNames = null; } if (existingDefinition != null || containsSingleton(beanName)) { // 重置当前beanName的所有bean定义 resetBeanDefinition(beanName); } else if (isConfigurationFrozen()) { clearByTypeCache(); } } 至此我们也终于大致阅读完obtainFreshBeanFactory()的源码,其它具体细节有兴趣可以自行阅读。
总结至此,我们已经了解了refresh()核心方法的前两个prepareRefresh()和obtainFreshBeanFactory()方法,从初始化并校验环境配置,初始化应用监听与事件,到解析资源配置文件,将文件中关于bean定义加载到beanFactory并返回beanFactory的过程。



