SpringIOC 源码解析 注册Bean
- 整体查看
- demo
- XmlBeanDefinitionReader 的loadBeanDefinitions(Resource resource)方法
- 调用 loadBeanDefinitions(EncodedResource encodedResource) 方法,执行真正的逻辑实现(省略非关键代码)。
- 获取 XML Document 实例。
- 获取 XML Document 实例--->getEntityResolver()返回指定的解析器,如果没有指定,则构造一个默认解析器。
- 获取 XML Document 实例--->getValidationModeForResource(Resource resource) 方法,获取指定资源(xml)的验证模式,保证xml文件的正确性。
- 获取 XML Document 实例--->getValidationModeForResource(Resource resource) ->detectValidationMode(resource) 方法,自动获取xml验证模式。
- 获取 XML Document 实例->委托给DocumentLoader.loadDocument去加载document。
- 获取 XML Document 实例->委托给DocumentLoader 去加载documentcreateDocumentBuilderFactory(validationMode,namespaceAware)创建DocumentBuilderFactory
- 获取 XML Document 实例->委托给DocumentLoader 去加载document->createDocumentBuilder(factory, entityResolver, errorHandler);创建 DocumentBuilder
- 最后解析 XML InputSource 返回 Document 对象
- 根据 Document 实例,注册 Bean 信息
- 注册 Bean 信息方法委托给BeanDefinitionDocumentReader类处理
- BeanDefinitionDocumentReader.doRegisterBeanDefinitions()注册bean
- 关于BeanDefinitionParserDelegate类
- parseBeanDefinitions(root, this.delegate);执行注册和解析
- parseDefaultElement(ele, delegate);执行默认解析
- 本文章在ioc阶段只写默认解析关于自定义解析会在后续AOP源码文章中讲解
- importBeanDefinitionResource(ele);import属性解析
- processAliasRegistration(ele)alais属性解析
- processBeanDefinition(ele, delegate);``Bean解析
- BeanDefinitionHolder可以理解为bean的持有者
- 委托给BeanDefinitionParserDelegate 元素进行解析返回BeanDefinitionHolder
- 解析属性,构造 AbstractBeanDefinition 对象
- 创建用于承载属性的 AbstractBeanDefinition 实例 实际上创建的是GenericBeanDefinition对象
- 解析默认 bean 的各种属性 存放当前GenericBeanDefinition 中
- 进行 BeanDefinition 的注册委托给BeanDefinitionReaderUtils
- BeanDefinitionReaderUtils又把注册任务交给了DefaultListableBeanFactory
- 关于 BeanDefinitionRegistry
整体查看
ResourceLoader : 定义资源加载器 主要应用于根据给定的资源文件地址返回对应的Resources
BeanDefinitionReader: 定义资源文件读取并转换为BeanDefinition的各个功能
EnvironmentCapable: 定义获取Environment的方法
DocumentLoader: 定义资源文件加载到转换为Document的功能
AbstractBeanDefinitReader:对EnvironmentCapable、BeanDefinitionReader类定义的功能进行实现
BeanDefinitionDocumentReader: 定义读取Document并注册BeanDefinition对象
BeanDefinitionParserDelegate 定义解析Element的一些方法
XMLBeanDefinitionReader整个XML配置文件读取的大致流程
1,通过继承自AbstractBeanDefinitReader中的方法,来使用ResourceLoader将资源文件路径转化为对应的Resource
2,通过DocumentLoader对Resource文件进行转换,将Resource文件转化为Document文件
3,通过实现接口BeanDefinitionDocumentReader的DefaultBeanDefinitionDocumentReader类进行解析并委托给BeanDefinitionParserDelegate 进行Element解析
demo
ClassPathResource resource = new ClassPathResource("bean.xml");
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(resource);
资源文件的加载将围绕此demo进行完成。
XmlBeanDefinitionReader 的loadBeanDefinitions(Resource resource)方法
从指定的xml配置文件中加载BeanDefinition。
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
return loadBeanDefinitions(new EncodedResource(resource));
}
将 Resource 封装成 EncodedResource ,EncodedResource类的构造器如下主要是为了对 Resource 进行编码,保证内容读取的正确性。
private EncodedResource(Resource resource, @Nullable String encoding, @Nullable Charset charset) {
super();
Assert.notNull(resource, "Resource must not be null");
this.resource = resource;
this.encoding = encoding;
this.charset = charset;
}
继续向下执行重载方法(省略非关键代码)。
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
try {
// 从 EncodedResource 获取封装的 Resource ,并从 Resource 中获取其中的 InputStream
InputStream inputStream = encodedResource.getResource().getInputStream();
// 获取inputSource SAX 解析器将使用InputSource 对象来确定如何读取XML 输入
InputSource inputSource = new InputSource(inputStream);
// 核心逻辑部分,执行加载 BeanDefinition
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
} catch (IOException ex) {
throw new BeanDefinitionStoreException("IOException parsing XML document from "
+ encodedResource.getResource(), ex);
}
}
调用 loadBeanDefinitions(EncodedResource encodedResource) 方法,执行真正的逻辑实现(省略非关键代码)。
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {
// 获取 XML Document 实例
Document doc = doLoadDocument(inputSource, resource);
// 根据 Document 实例,注册 Bean 信息
int count = registerBeanDefinitions(doc, resource);
return count;
}
获取 XML Document 实例。
/**
* DocumentLoader 对象,用于加载 Document 对象
*/
private DocumentLoader documentLoader = new DefaultDocumentLoader();
protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
//获取 XML Document 实例。 委托给DocumentLoader 去加载document
return this.documentLoader.loadDocument(
inputSource,
// 返回指定的解析器,如果没有指定,则构造一个未指定的默认解析器。
getEntityResolver(),
this.errorHandler,
//调用 #getValidationModeForResource(Resource resource) 方法,获取指定资源(xml)的验证模式。
getValidationModeForResource(resource),
isNamespaceAware()
);
}
获取 XML Document 实例—>getEntityResolver()返回指定的解析器,如果没有指定,则构造一个默认解析器。
(1)何为EntityResolver?
EntityResolver的作用项目本身就可以提供一个如何寻找DTD方法的声明即由程序来寻找DTD声明的过程,比如我们将DTD文件放到项目的某处实现时直接将此文档读取并返回给SAX即可,这样就避免了从网络上来寻找相应的声明(默认方式)。
(2)EntityResolver类图如下。
1、BeansDtdResolver Spring Bean dtd 解码器,用来从 classpath 或者 jar 文件中加载 dtd 。
2 、ResourceEntityResolver继承自 DelegatingEntityResolver 类,通过 ResourceLoader 来解析实体的引用。
读取 classpath 下的所有 “META-INF/spring.schemas” 行成一个 namespaceURI 与 Schema 文件地址的 map
3、DelegatingEntityResolver 该 Resolver 委托给默认的 BeansDtdResolver 和 PluggableSchemaResolver 。
分别代理 dtd 的 BeansDtdResolver 和 xml schemas 的 PluggableSchemaResolver 。
(3) getEntityResolver()方法。
protected EntityResolver getEntityResolver() {
if (this.entityResolver == null) {
// 如果 ResourceLoader 不为 null,则根据指定的 ResourceLoader 创建一个 ResourceEntityResolver 对象。
ResourceLoader resourceLoader = getResourceLoader();
if (resourceLoader != null) {
this.entityResolver = new ResourceEntityResolver(resourceLoader);
} else {
// 如果 ResourceLoader 为 null ,则创建 一个 DelegatingEntityResolver 对象。该 Resolver 委托给默认的 BeansDtdResolver 和 PluggableSchemaResolver 。
this.entityResolver = new DelegatingEntityResolver(getBeanClassLoader());
}
}
return this.entityResolver;
}
获取 XML Document 实例—>getValidationModeForResource(Resource resource) 方法,获取指定资源(xml)的验证模式,保证xml文件的正确性。
protected int getValidationModeForResource(Resource resource) {
// 获取指定的验证模式 设置的验证模式 返回 public static final int VALIDATION_AUTO = 1;
int validationModeToUse = getValidationMode();
// 首先,如果手动指定 默认为自动指定不等于则为手动指定,则直接返回
if (validationModeToUse != VALIDATION_AUTO) {
return validationModeToUse;
}
// 其次,自动获取验证模式
int detectedMode = detectValidationMode(resource);
if (detectedMode != VALIDATION_AUTO) {
return detectedMode;
}
// 最后,使用 VALIDATION_XSD 做为默认
return VALIDATION_XSD;
}
获取 XML Document 实例—>getValidationModeForResource(Resource resource) ->detectValidationMode(resource) 方法,自动获取xml验证模式。
protected int detectValidationMode(Resource resource) {
// XML 验证模式探测器 获取相应的验证模式 委托给 XmlValidationModeDetector
this.validationModeDetector.detectValidationMode(inputStream);
}
public int detectValidationMode(InputStream inputStream) throws IOException {
// BufferedReader 获取字符缓冲流
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
try {
// 是否为 DTD 校验模式。默认为,非 DTD 模式,即 XSD 模式
boolean isDtdValidated = false;
String content;
// 循环,逐行读取 XML 文件的内容 主要是通过读取 XML 文件的内容,来进行自动判断。
while ((content = reader.readLine()) != null) {
content = consumeCommentTokens(content);
// 跳过,如果是注释,或者 如果值是,null, "" 忽略此次继续执行
if (this.inComment || !StringUtils.hasText(content)) {
continue;
}
// 包含 DOCTYPE 为 DTD 模式 hasDoctype(String content) 方法,判断内容中如果包含有 "DOCTYPE“ ,则为 DTD 验证模式。
if (hasDoctype(content)) {
isDtdValidated = true;
break;
}
// hasOpeningTag 方法会校验,如果这一行有 < ,并且 < 后面跟着的是字母,则返回 true 。
if (hasOpeningTag(content)) {
break;
}
}
// 返回 VALIDATION_DTD or VALIDATION_XSD 模式 public static final int VALIDATION_DTD = 2; public static final int VALIDATION_XSD = 3;
return (isDtdValidated ? VALIDATION_DTD : VALIDATION_XSD);
} catch (CharConversionException ex) {
// 返回 自动模式 模式
return VALIDATION_AUTO;
} finally {
reader.close();
}
}
获取 XML Document 实例->委托给DocumentLoader.loadDocument去加载document。
@Override
public Document loadDocument(InputSource inputSource, EntityResolver entityResolver, ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {
// 创建 DocumentBuilderFactory
DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);
// 创建 DocumentBuilder
DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);
// 解析 XML InputSource 返回 Document 对象
return builder.parse(inputSource);
}
获取 XML Document 实例->委托给DocumentLoader 去加载documentcreateDocumentBuilderFactory(validationMode,namespaceAware)创建DocumentBuilderFactory
protected DocumentBuilderFactory createDocumentBuilderFactory(int validationMode, boolean namespaceAware)
throws ParserConfigurationException {
// 创建 DocumentBuilderFactory
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// 设置命名空间支持
factory.setNamespaceAware(namespaceAware);
/*如果当前验证模式不等于 禁用验证模式*/
if (validationMode != XmlValidationModeDetector.VALIDATION_NONE) {
/*开启验证模式*/
factory.setValidating(true);
// XSD 模式下,设置 factory 的属性
if (validationMode == XmlValidationModeDetector.VALIDATION_XSD) {
// XSD 模式下,强制设置命名空间支持
factory.setNamespaceAware(true);
// 设置 SCHEMA_LANGUAGE_ATTRIBUTE
factory.setAttribute(SCHEMA_LANGUAGE_ATTRIBUTE, XSD_SCHEMA_LANGUAGE);
}
}
获取 XML Document 实例->委托给DocumentLoader 去加载document->createDocumentBuilder(factory, entityResolver, errorHandler);创建 DocumentBuilder
protected DocumentBuilder createDocumentBuilder(DocumentBuilderFactory factory,
@Nullable EntityResolver entityResolver, @Nullable ErrorHandler errorHandler)
throws ParserConfigurationException {
// 创建 DocumentBuilder 对象
DocumentBuilder docBuilder = factory.newDocumentBuilder();
// 设置 EntityResolver 属性
if (entityResolver != null) {
docBuilder.setEntityResolver(entityResolver);
}
// 设置 ErrorHandler 属性
if (errorHandler != null) {
docBuilder.setErrorHandler(errorHandler);
}
return docBuilder;
}
最后解析 XML InputSource 返回 Document 对象
return builder.parse(inputSource);
根据 Document 实例,注册 Bean 信息
关于createReaderContext(resource)构建XmlReaderContext可知这是一个全局配置类
关于BeanDefinitionDocumentReader类
注册 Bean 信息方法委托给BeanDefinitionDocumentReader类处理
BeanDefinitionDocumentReader.doRegisterBeanDefinitions()注册bean
tips: 有没有发现真正干活的永远是do开头的方法
关于BeanDefinitionParserDelegate类
parseBeanDefinitions(root, this.delegate);执行注册和解析
parseDefaultElement(ele, delegate);执行默认解析
本文章在ioc阶段只写默认解析关于自定义解析会在后续AOP源码文章中讲解
importBeanDefinitionResource(ele);import属性解析
流程如下:
1, 如果是绝对路径,则调递归调用 Bean 的解析过程,进行另一次的解析
2, 相对路径 如果是相对路径,则先计算出绝对路径得到 Resource,然后调递归调用 Bean 的解析过程,进行另一次的解析。
protected void importBeanDefinitionResource(Element ele) {
// <1> 获取 resource 的属性值
String location = ele.getAttribute(RESOURCE_ATTRIBUTE);
// 为空,直接退出
if (!StringUtils.hasText(location)) {
// 使用 problemReporter 报错
getReaderContext().error("Resource location must not be empty", ele);
return;
}
// <2> 解析系统属性,格式如 :"${user.dir}"
location = getReaderContext().getEnvironment().resolveRequiredPlaceholders(location);
// 实际 Resource 集合,即 import 的地址,有哪些 Resource 资源
Set<Resource> actualResources = new LinkedHashSet<>(4);
// <3> 判断 location 是相对路径还是绝对路径
boolean absoluteLocation = false;
try {
absoluteLocation =
// <1> 以 classpath*: 或者 classpath: 开头的为绝对路径。
// <1> 能够通过该 location 构建出 java.net.URL 为绝对路径。
ResourcePatternUtils.isUrl(location)
// <2> 根据 location 构造 java.net.URI 判断调用 #isAbsolute() 方法,判断是否为绝对路径。
|| ResourceUtils.toURI(location).isAbsolute();
} catch (URISyntaxException ex) {
}
// Absolute or relative?
// <4> 绝对路径 如果是绝对路径,则调递归调用 Bean 的解析过程,进行另一次的解析
if (absoluteLocation) {
try {
// 添加配置文件地址的 Resource 到 actualResources 中,并加载相应的 BeanDefinition 们
int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources);
} catch (BeanDefinitionStoreException ex) {
getReaderContext().error(
"Failed to import bean definitions from URL location [" + location + "]", ele, ex);
}
// <5> 相对路径 如果是相对路径,则先计算出绝对路径得到 Resource,然后进行解析。
} else {
// No URL -> considering resource location as relative to the current file.
try {
int importCount;
// 创建相对地址的 Resource
Resource relativeResource = getReaderContext().getResource().createRelative(location);
// 存在
if (relativeResource.exists()) {
// 加载 relativeResource 中的 BeanDefinition 们
importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource);
// 添加到 actualResources 中
actualResources.add(relativeResource);
// 不存在
} else {
// 获得根路径地址
String baseLocation = getReaderContext().getResource().getURL().toString();
// 添加配置文件地址的 Resource 到 actualResources 中,并加载相应的 BeanDefinition 们
importCount = getReaderContext().getReader().loadBeanDefinitions(
//计算相对路径
StringUtils.applyRelativePath(baseLocation, location)
, actualResources);
}
} catch (IOException ex) {
getReaderContext().error("Failed to resolve current resource location", ele, ex);
} catch (BeanDefinitionStoreException ex) {
getReaderContext().error(
"Failed to import bean definitions from relative location [" + location + "]", ele, ex);
}
}
// 解析成功后,进行监听器激活处理
Resource[] actResArray = actualResources.toArray(new Resource[0]);
getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele));
}
processAliasRegistration(ele)alais属性解析
先解析出名称和属性在委派为SimpleAliasRegistry去注册
真正的注册别名逻辑
@Override
public void registerAlias(String name, String alias) {
// 校验 name 、 alias
Assert.hasText(name, "'name' must not be empty");
Assert.hasText(alias, "'alias' must not be empty");
synchronized (this.aliasMap) {
// name == alias 则去掉alias
if (alias.equals(name)) {
this.aliasMap.remove(alias);
if (logger.isDebugEnabled()) {
logger.debug("Alias definition '" + alias + "' ignored since it points to same name");
}
} else {
// 获取 alias 已注册的 beanName
String registeredName = this.aliasMap.get(alias);
// 已存在
if (registeredName != null) {
// 相同,则 return ,无需重复注册
if (registeredName.equals(name)) {
// An existing alias - no need to re-register
return;
}
// 不允许覆盖,则抛出 IllegalStateException 异常
if (!allowAliasOverriding()) {
throw new IllegalStateException("Cannot define alias '" + alias + "' for name '" +
name + "': It is already registered for name '" + registeredName + "'.");
}
if (logger.isDebugEnabled()) {
logger.debug("Overriding alias '" + alias + "' definition for registered name '" +
registeredName + "' with new target name '" + name + "'");
}
}
// 校验,是否存在循环指向
checkForAliasCircle(name, alias);
// 注册 alias
this.aliasMap.put(alias, name);
if (logger.isTraceEnabled()) {
logger.trace("Alias definition '" + alias + "' registered for name '" + name + "'");
}
}
}
}
processBeanDefinition(ele, delegate);``Bean解析
BeanDefinitionHolder可以理解为bean的持有者
/******************************* 其定义了以下变量,并对以下变量提供get和set操作。 *****/
/**
* BeanDefinition 对象
*/
private final BeanDefinition beanDefinition;
/**
* Bean 名字
*/
private final String beanName;
/**
* 别名集合
*/
@Nullable
private final String[] aliases;
委托给BeanDefinitionParserDelegate 元素进行解析返回BeanDefinitionHolder
/**
* 解析Element为BeanDefinition 并创建BeanDefinitionHolder对象
*/
@Nullable
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
// <1> 解析 id 和 name 属性
String id = ele.getAttribute(ID_ATTRIBUTE);
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
// <1> 计算别名集合
List<String> aliases = new ArrayList<>();
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}
// <3.1> 如果 id 不为空,则 beanName = id 。
String beanName = id;
// <3.2> 处,如果 id 为空,但是 aliases 不空,则 beanName 为 aliases 的第一个元素
if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
beanName = aliases.remove(0); // 移除出别名集合
}
// <2> 检查 beanName 的唯一性
if (containingBean == null) {
checkNameUniqueness(beanName, aliases, ele);
}
// <4> 解析属性,构造 AbstractBeanDefinition 对象
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
// <3.3> 处,如果两者都为空,则根据默认规则来设置 beanName 。因为默认规则不是本文的重点。
if (!StringUtils.hasText(beanName)) {
try {
if (containingBean != null) {
// <3.3> 生成唯一的 beanName
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
} else {
// <3.3> 生成唯一的 beanName
beanName = this.readerContext.generateBeanName(beanDefinition);
// Register an alias for the plain bean class name, if still possible,
// if the generator returned the class name plus a suffix.
// This is expected for Spring 1.2/2.0 backwards compatibility.
String beanClassName = beanDefinition.getBeanClassName();
if (beanClassName != null &&
beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
aliases.add(beanClassName);
}
}
} catch (Exception ex) {
error(ex.getMessage(), ele);
return null;
}
}
// <5> 创建 BeanDefinitionHolder 对象
String[] aliasesArray = StringUtils.toStringArray(aliases);
// 封装了 BeanDefinition 对象 返回
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
return null;
}
解析属性,构造 AbstractBeanDefinition 对象
/**
* 对属性进行解析并封装成 AbstractBeanDefinition
*/
@Nullable
public AbstractBeanDefinition parseBeanDefinitionElement(
Element ele, String beanName, @Nullable BeanDefinition containingBean) {
this.parseState.push(new BeanEntry(beanName));
// 解析 class 属性
String className = null;
if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
}
// 解析 parent 属性
String parent = null;
if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
parent = ele.getAttribute(PARENT_ATTRIBUTE);
}
try {
// 创建用于承载属性的 AbstractBeanDefinition 实例 实际上创建的是GenericBeanDefinition对象
AbstractBeanDefinition bd = createBeanDefinition(className, parent);
// 解析默认 bean 的各种属性 存放当前db中
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
// 提取 description
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
// tips:
// 下面的一堆是解析 <bean>......</bean> 内部的子元素,
// 解析出来以后的信息都放到 bd 的属性中
// 解析元数据 <meta />
parseMetaElements(ele, bd);
// 解析 lookup-method 属性 <lookup-method />
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
// 解析 replaced-method 属性 <replaced-method />
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
// 解析构造函数参数 <constructor-arg />
parseConstructorArgElements(ele, bd);
// 解析 property 子元素 <property />
parsePropertyElements(ele, bd);
// 解析 qualifier 子元素 <qualifier />
parseQualifierElements(ele, bd);
bd.setResource(this.readerContext.getResource());
bd.setSource(extractSource(ele));
return bd;
} catch (ClassNotFoundException ex) {
error("Bean class [" + className + "] not found", ele, ex);
} catch (NoClassDefFoundError err) {
error("Class that bean class [" + className + "] depends on not found", ele, err);
} catch (Throwable ex) {
error("Unexpected failure during bean definition parsing", ele, ex);
} finally {
this.parseState.pop();
}
return null;
}
创建用于承载属性的 AbstractBeanDefinition 实例 实际上创建的是GenericBeanDefinition对象
public static AbstractBeanDefinition createBeanDefinition(
@Nullable String parentName, @Nullable String className, @Nullable ClassLoader classLoader) throws ClassNotFoundException {
// 创建 GenericBeanDefinition 对象,并设置 parentName、className、beanClass 属性。
GenericBeanDefinition bd = new GenericBeanDefinition();
// 设置 parentName
bd.setParentName(parentName);
if (className != null) {
// 设置 beanClass
if (classLoader != null) {
bd.setBeanClass(ClassUtils.forName(className, classLoader));
// 设置 beanClassName
} else {
bd.setBeanClassName(className);
}
}
return bd;
}
解析默认 bean 的各种属性 存放当前GenericBeanDefinition 中
/**
、 该方法将创建好的 GenericBeanDefinition 实例当做参数,对 bean 标签的所有属性进行解析
*/
public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
@Nullable BeanDefinition containingBean, AbstractBeanDefinition bd) {
// 解析 scope 属性
if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
} 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)));
}
// 解析 lazy-init 属性
String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
if (DEFAULT_VALUE.equals(lazyInit)) {
lazyInit = this.defaults.getLazyInit();
}
bd.setLazyInit(TRUE_VALUE.equals(lazyInit));
// 解析 autowire 属性
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 属性
String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE);
if ("".equals(autowireCandidate) || DEFAULT_VALUE.equals(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));
}
if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
}
return bd;
}
到了这一步我们的我们的bean解析完毕并且存放到了BeanDefinitionHolder中
进行 BeanDefinition 的注册委托给BeanDefinitionReaderUtils
/**
* 注册BeanDefinition
*/
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
// 注册 通过beanName注册BeanDefinition
String beanName = definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// 注册 通过beanName注册alias
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
BeanDefinitionReaderUtils又把注册任务交给了DefaultListableBeanFactory
主要是把当前bean的定义信息放到缓存中DefaultListableBeanFactory 实现了BeanDefinitionRegistry它就像一个数据库一样存放bean的定义信息
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
// <1> 校验 BeanDefinition 。
// 这是注册前的最后一次校验了,主要是对属性 methodOverrides 进行校验。
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
} catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
// <2> 从缓存中获取指定 beanName 的 BeanDefinition
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
// <3> 如果已经存在
if (existingDefinition != null) {
// 如果存在但是不允许覆盖,抛出异常
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
// 允许覆盖,直接覆盖原有的 BeanDefinition 到 beanDefinitionMap 中。
this.beanDefinitionMap.put(beanName, beanDefinition);
// <4> 如果未存在
} else {
// 检测创建 Bean 阶段是否已经开启,如果开启了则需要对 beanDefinitionMap 进行并发控制
if (hasBeanCreationStarted()) {
// beanDefinitionMap 为全局变量,避免并发情况
synchronized (this.beanDefinitionMap) {
// 添加到 BeanDefinition 到 beanDefinitionMap 中。
this.beanDefinitionMap.put(beanName, beanDefinition);
// 添加 beanName 到 beanDefinitionNames 中
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
// 从 manualSingletonNames 移除 beanName
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
} else {
// 添加到 BeanDefinition 到 beanDefinitionMap 中。
this.beanDefinitionMap.put(beanName, beanDefinition);
// 添加 beanName 到 beanDefinitionNames 中
this.beanDefinitionNames.add(beanName);
// 从 manualSingletonNames 移除 beanName
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
}
// <5> 重新设置 beanName 对应的缓存
if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
关于 BeanDefinitionRegistry
package org.springframework.beans.factory.support;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.core.AliasRegistry;
/**
BeanDefinitionRegistry ,该类的作用主要是向注册表中注册 BeanDefinition 实例,完成 注册的过程 就像是java中的数据库 这里面存放的是BeanDefinition
*/
public interface BeanDefinitionRegistry extends AliasRegistry {
/**
* 往注册表中注册一个新的 BeanDefinition 实例
*/
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException;
/**
* 移除注册表中已注册的 BeanDefinition 实例
*/
void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
/**
* 从注册中取得指定的 BeanDefinition 实例
*/
BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
/**
* 判断 BeanDefinition 实例是否在注册表中(是否注册)
*/
boolean containsBeanDefinition(String beanName);
/**
* 取得注册表中所有 BeanDefinition 实例的 beanName(标识)
*/
String[] getBeanDefinitionNames();
/**
* 返回注册表中 BeanDefinition 实例的数量
*/
int getBeanDefinitionCount();
/**
* beanName(标识)是否被占用
*/
boolean isBeanNameInUse(String beanName);
}
到此文件就结束了请关注后续文章BEAN的获取以及Aop源码分析 在阅读源码过程中主要是参考芋道源码的博客进行学习只学习了主要的流程后续的文章也是如此,希望文章中错误的地方可以进行指出,毕竟本人是个菜鸟 希望大佬们多多提意见,欢迎评论,或者有不懂的地方也可以问在评论下提问后续会把源码公开,源码主要是在芋道源码分析的基础之上减少了部分校验逻辑与日志打印与自己的见解