Spring 源码系列-BeanDefinition
Bean的定义主要由 BeanDefinition 来描述的。作为Spring中用于包装Bean的数据结构,今天就来看看它的面纱下的真容吧
BeanDefinition 类定义
首先就是BeanDefinition的类定义:
1 | public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement |
对,没错,这货是个接口,而不是类,是不是有点莫名奇妙呢?我们都知道在JAVA中,接口是不能用来new出新的对象的,那么在Spring中,到底将XML解析出来的Bean包装成了什么呢?(这个密等下揭开)
先来看看BeanDefinition一个继承结构吧(均是与BeanDefinition有直接关联的类或者接口)!
从类图中可以看出,BeanDefinition继承了AttributeAccessor和BeanMetadataElement两个接口;一个一个看。
AttributeAccessor
AttributeAccessor 接口定义了最基本的对任意对象的元数据的修改或者获取,主要方法有:
1 | //将name定义的属性设置为提供的value值。如果value的值为null,则该属性为{@link #removeAttribute removed}。 |
BeanMetadataElement
BeanMetadataElement 接口提供了一个 getResource() 方法,用来传输一个可配置的源对象。
1 | //返回此元数据元素的配置源对象(可能为null)。 |
BeanDifinition 源码分析
一个BeanDefinition描述了一个bean的实例,包括属性值,构造方法参数值和继承自它的类的更多信息。BeanDefinition仅仅是一个最简单的接口,主要功能是允许BeanFactoryPostProcessor 例如PropertyPlaceHolderConfigure 能够检索并修改属性值和别的bean的元数据(译注)。
1 | //标准单例作用域的作用域标识符:“singleton”。 |
上面是BeanDifinition的一些基本属性信息,一个就是标识下当前Bean的作用域,另外就是标识一下这个Bean是内部的还是外部的。下面来看这个接口为其子类都提供了哪些具体的行为方法:
1 | //如果父类存在,设置这个bean定义的父定义的名称。 |
从上面的属性和方法分析可以看出,BeanDefinition 对于一个Bean的描述做了较为完整的一套约束。这为后续的子类提供的最基本的职责和属性。
beanFactory 创建
Spring的Ioc容器其实就是一个bean的关系网,依赖于core,bean,context三个组件来构建的。在spring中最核心的就是对于bean的管理。而bean又依托于我们的容器。本文将从顶层分析一下spring中beanFactory的具体创建过程,为后续的bean的生命周期提供一个基础。
BeanFactory的继承体系
从上图可以看到,BeanFactory有三个子类:
- ListableBeanFactory
- HierarchicalBeanFactory
- AutowireCapableBeanFactory
(上述三个类的子类体系小伙伴们可以自己对着源码看下,实在太多)
看下上图中最底层的DefaultListableBeanFactory类的定义:
1 | public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory |
这个其实就是BeanFactory的默认实现类,它直接或者间接的实现了所有的接口。其实在看spring源码的时候都会遇到类似的设计模式,对于某一个具体的功能,通常都会定义很多层的接口,层层包装,层层委托。这种做法的好处就是,对于不同的场合都会有特定的接口;这样一来就可以在spring内部对对象的传递和转化操作都会有一些访问限制。
例如ListableBeanFactory接口表示这些Bean是可列表的,而HierarchicalBeanFactory表示的是这些Bean是有继承关系的,也就是每个Bean有可能有父Bean。AutowireCapableBeanFactory接口定义Bean的自动装配规则。这四个接口共同定义了Bean的集合、Bean之间的关系、以及Bean行为。
BeanFactory的创建
在之前的文章中说过了容器的刷新过程。BeanFactory的创建也在wac.refresh()方法中。具体看下到底是通过哪些子类来完成的:
1 | // 通知子类刷新内部的bean工厂。 |
1.AbstractApplicationContext中的obtainFreshBeanFactory
下面是obtainFreshBeanFactory的方法逻辑:
1 | protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { |
refreshBeanFactory并未有具体的实现逻辑,这个方法主要是通过委托给子类的refreshBeanFactory方法来实现,在AbstractApplicationContext中refreshBeanFactory是一个抽象模板方法:
1 | protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException; |
2.refreshBeanFactory方法(AbstractRefreshableApplicationContext类中):
下面只注释与beanFactory创建相关的代码
1 | protected final void refreshBeanFactory() throws BeansException { |
这个方法是实现执行这个上下文的底层bean工厂的实际刷新,如果有的话之前有BeanFactory存在,则关闭以前的bean工厂。并为上下文生命周期的下一个阶段初始化一个新鲜的bean工厂。
3.createBeanFactory(AbstractRefreshableApplicationContext类中)
1 | protected DefaultListableBeanFactory createBeanFactory() { |
这个方法就是为当前上下文创建一个内部的bean工厂。每次调用refresh()方法是都会创建尝试创建。默认实现是创建一个DefaultListableBeanFactory。并通过getInternalParentBeanFactory()获取内部bean工厂来作为父级bean工厂。可以在子类中重写,例如自定义DefaultListableBeanFactory的设置。
getInternalParentBeanFactory(AbstractApplicationContext类中)
1 | protected BeanFactory getInternalParentBeanFactory() { |
4.DefaultListableBeanFactory的构造函数
1 | /** |
super(parentBeanFactory)调用的是AbstractAutowireCapableBeanFactory的构造函数
1 | /** |
this(),还是AbstractAutowireCapableBeanFactory的构造函数:
1 | /** |
super() ; AbstractBeanFactory的构造函数
1 | /** |
BeanDefinition 载入(上)
继上一篇BeanFactory的创建之后,其实就是BeanDefinition载入了。同样也是在AbstractRefreshableApplicationContext类的refreshBeanFactory方法中完成:
//创建默认的DefaultListableBeanFactory工厂
DefaultListableBeanFactory beanFactory = createBeanFactory();
//设置Id
beanFactory.setSerializationId(getId());
//这个方法其实就是设置了allowBeanDefinitionOverriding和allowCircularReferences两个属性
customizeBeanFactory(beanFactory);
//调用子类的加载bean定义方法,这里会调用XmlWebApplicationContext子类的复写方法
loadBeanDefinitions(beanFactory);
这里的loadBeanDefinitions也是一个抽象方法,AbstractRefreshableApplicationContext类中并没有给出具体的实现,二是通过子类XmlWebApplicationContext的loadBeanDefinitions完成具体实现。
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)
throws BeansException, IOException {
//创建XmlBeanDefinitionReader,并通过回调设置到BeanFactory中
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
//为XmlBeanDefinitionReader配置Environment
beanDefinitionReader.setEnvironment(getEnvironment());
//为XmlBeanDefinitionReader配置ResourceLoader,
//因为DefaultResourceLoader是父类,所以this可以直接被使用
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// 允许子类提供reader的自定义初始化,然后继续实际加载bean定义。
initBeanDefinitionReader(beanDefinitionReader);
loadBeanDefinitions(beanDefinitionReader);
}
initBeanDefinitionReader初始化用于加载此上下文的bean定义的bean定义读取器;默认实现是空的。然后下面通过重载的loadBeanDefinitions来做具体的bean解析(这里用到的是XmlBeanDefinitionReader这个解析器);使用给定的XmlBeanDefinitionReader加载bean definitions。
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {
String[] configLocations = getConfigLocations();
//遍历xml文件
if (configLocations != null) {
for (String configLocation : configLocations) {
reader.loadBeanDefinitions(configLocation);
}
}
}
此时会将我们的applicationContext.xml读入(当然如何还有其他的spring配置文件,同样会一块拿到路径),如下图所示:
然后继续通过loadBeanDefinitions的重载方法继续委托调用。最后交给AbstractBeanDefinitionReader的loadBeanDefinitions来完成;这个代码比较长,拆开一步一步来说,先看下整体的:
public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {
//获取ResourceLoader资源定位器
ResourceLoader resourceLoader = getResourceLoader();
//如果定位器为null,则抛出异常
if (resourceLoader == null) {
throw new BeanDefinitionStoreException(
"Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
}
//是否是ResourcePatternResolver类型的定位器
if (resourceLoader instanceof ResourcePatternResolver) {
// Resource pattern matching available.
try {
Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
int loadCount = loadBeanDefinitions(resources);
if (actualResources != null) {
for (Resource resource : resources) {
actualResources.add(resource);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
}
return loadCount;
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"Could not resolve bean definition resource pattern [" + location + "]", ex);
}
}
//非ResourcePatternResolver类型的
else {
// Can only load single resources by absolute URL.
Resource resource = resourceLoader.getResource(location);
int loadCount = loadBeanDefinitions(resource);
if (actualResources != null) {
actualResources.add(resource);
}
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
}
return loadCount;
}
}
上面的代码中需要说明下为什么要判断当前resourceLoader是否是ResourcePatternResolver类型的,因为ResourceLoader只是提供了对classpath前缀的支持。而ResourcePatternResolver提供了对classpath*前缀的支持。也就是说ResourceLoader提供classpath下单资源文件的载入,而ResourcePatternResolver提供多资源文件的载入。
先看下假如是ResourcePatternResolver类型的(略去了部分log代码):
try {
//先得到我们的resources
Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
//解析并返回beanDefinition的数量
int loadCount = loadBeanDefinitions(resources);
//加载过程中已经被解析过的实际的Resource的填充集合
if (actualResources != null) {
for (Resource resource : resources) {
actualResources.add(resource);
}
}
return loadCount;
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"Could not resolve bean definition resource pattern [" + location + "]", ex);
}
非ResourcePatternResolver类型情况:
// Can only load single resources by absolute URL.
//只能通过绝对URL加载单个资源
Resource resource = resourceLoader.getResource(location);
//解析并返回beanDefinition的数量
int loadCount = loadBeanDefinitions(resource);
if (actualResources != null) {
actualResources.add(resource);
}
return loadCount;
然后继续通过重载方法loadBeanDefinitions(Resource… resources)来解析(AbstractBeanDefinitionReader类中)
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
Assert.notNull(resources, "Resource array must not be null");
//初始化beanDefiniton个数
int counter = 0;
//遍历当前资源数组
for (Resource resource : resources) {
//解析具体resource中的bean
counter += loadBeanDefinitions(resource);
}
return counter;
}
然后交给子类XmlBeanDefinitionReader中的loadBeanDefinitions(Resource resource)方法:
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
return loadBeanDefinitions(new EncodedResource(resource));
}
继续通过重载方法loadBeanDefinitions(EncodedResource encodedResource)执行,这个方法我们只关注最核心的代码:
//获取输入流
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
//资源读取inputSource
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
//委托给doLoadBeanDefinitions来完成
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
inputStream.close();
}
doLoadBeanDefinitions是XmlBeanDefinitionReader中的方法,来看核心代码:
//解析成符合w3c标准的Document
Document doc = doLoadDocument(inputSource, resource);
//继续交给registerBeanDefinitions来处理
return registerBeanDefinitions(doc, resource);
这个时候已经将loadBeanDefinitions换成registerBeanDefinitions了,也就是载入并注册;registerBeanDefinitions同样也是XmlBeanDefinitionReader中的方法:
public int registerBeanDefinitions(Document doc, Resource resource) throws
BeanDefinitionStoreException {
//得到documentReader用来读取document文档
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
//注册之前的bean个数
int countBefore = getRegistry().getBeanDefinitionCount();
//解析并注册bean
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
仍然没有处理,继续交给BeanDefinitionDocumentReader
的registerBeanDefinitions方法来完成:
//这个实现根据“spring-beans”XSD(或DTD)解析bean定义。
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
logger.debug("Loading bean definitions");
Element root = doc.getDocumentElement();
doRegisterBeanDefinitions(root);
}
还是没处理,又细化一步,交给DefaultBeanDefinitionDocumentReader
的doRegisterBeanDefinitions(Element root)方法:
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);
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if (logger.isInfoEnabled()) {
logger.info("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;
}
任何嵌套的<beans>元素都将导致此方法的递归。 为了正确传播和保存<beans> default- *属性,请跟踪当前(父)委托,该委托可能为null。 为了回退的目的,创建一个引用父对象的新(子)委托,然后最终重置this.delegate回到它的原始(父)引用。这个行为模仿了一堆委托,而实际上并不需要一个委托。(翻译的有点蹩脚,大概意思就是这)
所以说DefaultBeanDefinitionDocumentReader
自己也没干这事,又给了BeanDefinitionParserDelegate
,然后就是preProcessXml()、parseBeanDefinitions()、postProcessXml()方法;其中preProcessXml()和postProcessXml()默认是空方法,自己没有实现。具体解析在parseBeanDefinitions(root, this.delegate)中完成。
BeanDefinitionParserDelegate
用于将 Document
的内容转成 BeanDefinition
实例;BeanDefinitionDocumentReader
本身不具备该功能而是交给了该类来完成。
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)) {
parseDefaultElement(ele, delegate);
}
else {
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
这个方法就是解析文档中根目录下的元素:“import”,“alias”,“bean”。
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
//解析一个“import”元素,并将给定资源的bean定义加载到bean工厂中。
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
//处理给定的别名元素,向注册表注册别名。
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
//处理给定的bean元素,解析bean定义并将其注册到注册表中。
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
//在给定的根<beans />元素内注册每个bean定义。
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
先来看processBeanDefinition
这个方法;
BeanDefinitionHolder是一个BeanDefinition的持有者,其定义了一下变量,并对以下变量提供get和set操作。这个在后面的说道BeanDefinition体系的时候再聊。
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
//获取一个BeanDefinitionHolder
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
//首先根据自定义属性进行装饰。
//基于自定义嵌套元素进行装饰。
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// 注册最终装饰的实例。
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder,
getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// 发送注册事件。
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
接着看registerBeanDefinition
这个方法:通过给定的bean工厂注册给定的bean definition 。
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// 在主名称下注册bean定义。
String beanName = definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// 如果有的话,注册bean名称的别名,
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
registerBeanDefinition
里面又通过调用BeanDefinitionRegistry
接口的实现DefaultListableBeanFactory
来完成具体的注册过程。
BeanDefinition载入(中)
上面对于一些细节问题没有进行细究,比如说元素属性值的处理,构造函数的处理等等。本篇就学习记录一下相关点。
首先来看下是在哪个地方具体生成BeanDefinitiond的。下面是方法请求的顺序。
- DefaultBeanDefinitionDocumentReader.parseDefaultElement
- DefaultBeanDefinitionDocumentReader.processBeanDefinition
- BeanDefinitionParserDelegate.parseBeanDefinitionElement
关于元素的解析绝大多数都是在 BeanDefinitionParserDelegate 及其子类中完成的。OK,来看下 parseBeanDefinitionElement 这个方法:
1 | public AbstractBeanDefinition parseBeanDefinitionElement( |
此处我们以解析property为例,看下具体的处理细节:
1 | //解析给定bean元素的属性子元素。 |
接着是执行具体property,在parsePropertyElement中完成:
1 | //解析一个property元素。 |
在parsePropertyValue中,是对所有的property子元素进行具体解析的。我们知道property中除了单值之外,还会包括如:list,set,map,prop等集合元素;这些都会被封装成对应的Managerd对象。比如:ManagedList等。不同的集合类型页同样对应一种解析方法,比如解析list的是使用parseListElement。这些解析都是在BeanDefinitionParserDelegate类中完成的。这个后面我会抽一篇来学习BeanDefinitionParserDelegate这个类。
Bean的载入过程就是这样通过层层解析来完成的,但是对于目前的Ioc容器来说,仅仅是完成了对Bean对象管理的一些数据准备工作,也就是初始化工作,目前的BeanDefginiton中包含的就是一些静态的配置信息,Bean的实例化还没有进行,这个实例化的过程是在依赖注入时候完成的。
BeanDefinition载入(下)
在BeanDefinition载入(上)中已经大概捋了一下解析过程,本篇将记录一下bean的注册过程。
bean的注册就是DefaultListableBeanFactory中registerBeanDefinition方法来完成的。那我就来看registerBeanDefinition这个方法的具体逻辑。
1、beanDefinition类型判断和验证
这里的验证主要是验证不能将静态工厂方法与方法重写相结合(静态工厂方法必须创建实例);
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(),
beanName,"Validation of bean definition failed", ex);
}
}
2、尝试从beanDefinitionMap中获取老的bean
这里就是先根据beanName从beanDefinitionMap去取BeanDefinition,并将结果给oldBeanDefinition。
BeanDefinition oldBeanDefinition;
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
3、beanDefinitionMap中已经存在名为beanName的Beandefinition
如果当前beanDefinitionMap中已经存在名为beanName的Beandefinition了(即检查是否有相同名称的beanDefinition已经在Ioc容器中注册过了)。,如果有,则进行以下具体策略:
- 如果不允许bean被覆盖,则直接抛出不能重新注册,bean已经存在这样的异常信息
- 使用框架生成的Bean来代替用户自定义的bean
- 覆盖原有的Beandefinition
if (oldBeanDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
//省略异常代码
}
else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
//省略异常代码
}
else if (!beanDefinition.equals(oldBeanDefinition)) {
//提示覆盖log信息
}
else {
//提示覆盖log信息
}
//覆盖原有的Beandefinition
this.beanDefinitionMap.put(beanName, beanDefinition);
}
4、beanDefinitionMap不存在名为beanName的Beandefinition
//检查bean的创建阶段是否已经开始,也就是说是否已经创建了
if (hasBeanCreationStarted()) {
//Cannot modify startup-time collection elements anymore (for stable iteration)
// 无法修改启动时间收集元素(用于稳定迭代)(译注)
//注册过程需要保证数据的一致性,所有需要加锁同步
synchronized (this.beanDefinitionMap) {
//注册到beanDefinitionMap中
this.beanDefinitionMap.put(beanName, beanDefinition);
//下面就是将当前beanName存放到beanDefinitionNames中
List<String> updatedDefinitions = new ArrayList<String>(
this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
//如果单例模式的bean名单中有该bean的name,那么移除掉它。
//也就是说着,将一个原本是单例模式的bean重新注册成一个普通的bean
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new
LinkedHashSet<String>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
// 仍处于启动阶段,bean还没有开始注册
else {
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
5、执行缓存清除
1:oldBeanDefinition如果存在,且执行到了这里也没有抛出异常,说明该BeanDefinition已经被覆盖,缓存需要更新。
2:如果是单例模式的bean对象则Set中包含该beanName,执行到这里说明该BeanDefinition已经从一个单例模式的bean变为了一个普通的bean,所以缓存也需要更新。
if (oldBeanDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
OK,我们来看下resetBeanDefinition这个方法:
这个方法的作用就是重置给定bean的所有bean定义缓存,包括从它派生的bean的缓存。
protected void resetBeanDefinition(String beanName) {
// 如果已经创建,则删除给定bean的合并bean定义。
clearMergedBeanDefinition(beanName);
// 如果有的话,从singleton 高速缓存中删除相应的bean。
//但是这也不是必须的,而只是为了覆盖上下文的默认bean
//(就是从manualSingletonNames中移除)
destroySingleton(beanName);
//递归的方式来 重置具有给定bean作为父项的所有bean定义。
for (String bdName : this.beanDefinitionNames) {
if (!beanName.equals(bdName)) {
BeanDefinition bd = this.beanDefinitionMap.get(bdName);
if (beanName.equals(bd.getParentName())) {
resetBeanDefinition(bdName);
}
}
}
}
Bean的注册就到这里了
Spring 源码系列-BeanDefinition
http://www.glmapper.com/2018/02/07/spring/spring-ioc-bean-definition/