在上一篇博客内容中,我们已经看了解析 import.alias的源码了,接下来就是bean的这块了:
processBeanDefinition(ele, delegate):
从第一个方法开始看过来,parseBeanDefinitionElement的具体实现:
1.先获取id与name属性,将name按照分隔符切割为数组,因为我们name可以用逗号分隔来指示多个别名,然后将这个数组添加进一个新创建的集合中,如果id属性为空的话,创建的name集合又不为空,那么将以第一个name为这个bean的id
2.checkNameUniqueness(beanName.aloases,ele):该方法的目的是校验这个id,是否存在所有的bean的id集合中,该集合为一个Set集合,因为要保证id的强一致性(即使A bean的id 与B bean 的name有相同也是不行的,因为bean的name属性也会被添加进这个集合中,如果有定义了多个name,那么第一个值,必须是唯一的,如果在name的数组中还找到了相同的,同样会提示Error)
接着上图往下看:
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean): 解析bean定义本身,而不考虑名称或别名
AbstractBeanDefinition :具体的BeanDefinition类的基类,分解出GenericBeanDefinition,RootBeanDefinition和ChildBeanDefinition的公共属性
this.parseState = ParseState对象
ParseState:基于简单LinkedList的结构,用于跟踪解析过程中的逻辑位置
Entry:在解析阶段的每一点都以特定于读取器的方式添加到LinkedList中。用于ParseState条目的标记接口
BeanEntry:表示bean定义的ParseState条目
接下来来看第二部分:
bd.setResource(this.readerContext.getResource());
bd.setSource(extractSource(ele));
return bd; (这里是补充)
这里我们来详细看下怎么设置property属性的吧,其他的地方都比较简单,property属性我们也使用的最多了,所以看下实现原理也是有必要滴
parsePropertyElements(ele, bd):
public void parsePropertyElements(Element beanEle, BeanDefinition bd) {
NodeList nl = beanEle.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (isCandidateElement(node) && nodeNameEquals(node, PROPERTY_ELEMENT)) { //property
parsePropertyElement((Element) node, bd);
}
}
}
如果是property标签则进入parsePropertyElement方法:
public void parsePropertyElement(Element ele, BeanDefinition bd) {
String propertyName = ele.getAttribute(NAME_ATTRIBUTE); // name
if (!StringUtils.hasLength(propertyName)) {
error("Tag 'property' must have a 'name' attribute", ele);
return;
}
// 添加propertyName条目
this.parseState.push(new PropertyEntry(propertyName));
try {
//校验该peoperty是否已存在
if (bd.getPropertyValues().contains(propertyName)) {
error("Multiple 'property' definitions for property '" + propertyName + "'", ele);
return;
}
// 获取属性元素的值 (具体怎么做的在下面可以看得到)
Object val = parsePropertyValue(ele, bd, propertyName);
// 属性值对象
PropertyValue pv = new PropertyValue(propertyName, val);
// 判断是否存在meta标签,有则设置进pv中,因为我们在写配置文件的时候其实是可以往property标签中插入meta标签的
parseMetaElements(ele, pv);
// 这里啥也没干
pv.setSource(extractSource(ele));
// 添加进BeanDefinition中
bd.getPropertyValues().addPropertyValue(pv);
} finally {
// 这里就不用说了,要不然就显得太罗嗦了
this.parseState.pop();
}
}
Object val = parsePropertyValue(ele, bd, propertyName):获取属性值
1.首先是property的子元素是否只有一个
2.直接贴代码
boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE); //ref
boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE); //value
// ref和value属性不能一起出现在一个property标签中
if ((hasRefAttribute && hasValueAttribute) || ((hasRefAttribute || hasValueAttribute) && subElement != null)) {
error(elementName + " is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele);
}
if (hasRefAttribute) {
String refName = ele.getAttribute(REF_ATTRIBUTE);
if (!StringUtils.hasText(refName)) {
error(elementName + " contains empty 'ref' attribute", ele);
}
// RuntimeBeanReference :不可变占位符类,当属性值对象引用工厂中的另一个bean时,用于在运行时解析它
RuntimeBeanReference ref = new RuntimeBeanReference(refName);
// 啥也不干
ref.setSource(extractSource(ele));
return ref;
}else if (hasValueAttribute) {
// TypedStringValue:Spring类型字符串值的Holder。可以添加到bean定义中,以便显式地指定字符串值的目标类型,例如集合元素
// 这个holder只存储字符串值和目标类型。实际的转换将由bean工厂执行。
TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE));
// 这里也是啥都不干
valueHolder.setSource(extractSource(ele));
return valueHolder;
}
PropertyValue:对象来保存单个bean属性的信息和值。在这里使用一个对象,而不是仅仅将所有属性存储在一个按属性名键控的映射中, 这允许更大的灵活性,以及以优化的方式处理索引属性等。
MutablePropertyValues:PropertyValues接口的默认实现,允许对属性进行简单的操作,并提供构造函数来支持映射的深度复制和构造。
然后就没有然后了。就直接返回了,再回到parseBeanDefinitionElement方法中可以发现,下面还有一些对于bean的id为空的情况下的处理,这里我就不说了(时间原因,其实看源码看到这里,接下来的东西也就没啥难度了)
那么就回到parseBeanDefinitionElement方法的最后这一点 :
String[] aliasesArray = StringUtils.toStringArray(aliases);
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
BeanDefinitionHolder:包含名称和别名的bean定义的Holder。可以注册为内部bean的占位符。注册RootBeanDefinition或ChildBeanDefinition就足够了
最后返回的是BeanDefinitionHolder对象.
这里习惯性做个总结吧:
1.如果name属性为空,别名集合不为空,那么将以第一个别名设置为该bean的id
2.验证指定的bean名称和别名在当前bean元素嵌套级别中尚未使用
3.创建GenericBeanDefinition,并且为 GenericBeanDefinition 设置parentName,className
4.设置前置属性(singleton,scope,abstract,default-lazy-init,autowire,depend-on,autowire-candidate,primary,init-method,destroy-method...)
5.判断是否有description标签,如果有则返回
6.判断是否是meta标签,如果存在设置进BeanDefintion
7.判断是否是lookup-method标签,如果存在则添加进覆盖方法列表
8.判断是否是replaced-method标签,如果存在则添加进替换方法列表
9.解析给定bean元素的构造 constructor-arg子元素
10.解析属性元素
11:解析qualifier元素
12:设置source为XmlBeanDefinitionReader
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
//BeanDefinitionHolder :包含名称和别名的bean定义的Holder。可以注册为内部bean的占位符。
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); // 这里咱们就看完了,接着往下看
if (bdHolder != null) {
// 解析我们自定义的属性
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance. // 注册最后修饰后的实例。
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
} catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event. getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder):
public BeanDefinitionHolder decorateBeanDefinitionIfRequired( Element ele, BeanDefinitionHolder definitionHolder, @Nullable BeanDefinition containingBd) {
BeanDefinitionHolder finalDefinition = definitionHolder;
// 首先基于自定义属性进行装饰
NamedNodeMap attributes = ele.getAttributes();
for (int i = 0; i < attributes.getLength(); i++) {
Node node = attributes.item(i);
finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
}
// 基于自定义嵌套元素的装饰
NodeList children = ele.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node node = children.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
}
}
return finalDefinition;
}
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()) : 注册最后修饰后的实例,将给定的bean定义注册到给定的bean工厂
getReaderContext().getRegistry() 等同于 XmlBeanDefinitionReader.getRegistry() 返回DefaultListableBeanFactory
public static void registerBeanDefinition( BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
// Register bean definition under primary name.
String beanName = definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); // 我们主要来看看这个方法是怎么实现的
// Register aliases for bean name, if any.
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases){
registry.registerAlias(beanName, alias);
}
}
}
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()):
1.首先是对beanDefinition进行校验(存在覆盖方法并且工厂方法不为空(创建该Bean的工厂方法就不能被覆盖,校验该beanClass是否为Class实例)
2.然后在BeanDefinition缓存中找,目的是为了知道该beanName的beanDefinition是否已经存在,如果存在做另外一种处理,这里我们就不看了
3.判断该beanName是否已经创建过(AbstractBeanFactory中的alreadyCreated:至少创建过一次的bean的名称),如果不为空的话,首先是先把咱们的beanName与BeanDefinition添加进 beanName -> BeanDefinition的缓存中,然后从新初始化bean定义名称列表(beanDefinitionNames集合,也是DefaultListableBeanFactory中的属性,一个List集合),初始化的目的就是为了将我们的beanName添加进集合中,接着如果beanName存在与手动注册的单例程序的名称列表(DefaultListableBeanFactoty中的属性,一个Set集合)中的话,也是从新初始化该集合,不同的是这里是从集合中删除该beanName(如果是存在集合中的话), 初始化(copy-on-write)
4.那就是第三步的else部分了,这里比第三步就直接多了,beanName与BeanDefinition添加进 beanName -> BeanDefinition的缓存中,beanName添加进bean定义名称列表,删除手动注册的单例程序的名称列表中的该beanName
5.最后一步,判断beanDefintion是否存在或者是否已经存在与我们的缓存映射中,如果满足条件则开始清理,我们来把清理的过程和内容记录一下
1.缓存对象的bean的名字:bean名称到bean实例中删除beanName DefaultSingletonBeanRegistry.singletonObjects
2.单例工厂的缓存:对象工厂的bean名称中删除beanName DefaultSingletonBeanRegistry.singletonFactories
3.早期:单例对象缓存的bean bean实例的名字中删除beanName DefaultSingletonBeanRegistry.earlySingletonObjects
4.注册的单例集合,按注册顺序包含bean名称中删除beanName DefaultSingletonBeanRegistry.registeredSingletons
5.手动注册的单例程序的名称列表,按注册顺序排列(再特么删一次) DefaultListableBeanFactory.manualSingletonNames
6.清空单例和非单例bean名称的映射,按依赖项类型键控 DefaultListableBeanFactory.allBeanNamesByType
7.清空单一bean名称的映射,按依赖项类型键控 DefaultListableBeanFactory.singletonBeanNamesByType
到这里registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition())就已经结束了,这一步的话其实主要就是将beanName与创建好的BeanDefinition放在缓存中管理起来,回到registerBeanDefinition方法中我们继续往下看
// 为bean名称注册别名(如果有的话)
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
registry.registerAlias(beanName, alias): 这个地方我就直接把代码贴上这样方便看,内容也挺简单的,所以就不记录下来了
public void registerAlias(String name, String alias) {
Assert.hasText(name, "'name' must not be empty");
Assert.hasText(alias, "'alias' must not be empty");
synchronized (this.aliasMap) {
if (alias.equals(name)) {
this.aliasMap.remove(alias);
if (logger.isDebugEnabled()) {
logger.debug("Alias definition '" + alias + "' ignored since it points to same name");
}
}else{
String registeredName = this.aliasMap.get(alias);
if (registeredName != null) {
if (registeredName.equals(name)) {
return;
}
if (!allowAliasOverriding()) { // 是否允许别名覆盖。默认值是true;
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); // 检查给定名称是否已经指向另一个方向的给定别名作为别名
this.aliasMap.put(alias, name); // 添加进id与alias的映射
if (logger.isTraceEnabled()) {
logger.trace("Alias definition '" + alias + "' registered for name '" + name + "'");
}
}
}
}
ok了,BeanDefintion跟Aliases都注册了,那么registerBeanDefinition这个方法就完了,就是这样啦,哈哈哈哈,不管里头有多复杂,反正就是特么的两件事,注册我们根据
那我们再回到processBeanDefinition方法中,还有最后一个方法:,其实最后这个地方都可以不用说了,因为这里其实也还是啥都没干(反正调ReaderContext中那三个属性的方法都是没干活的,哈哈哈哈哈)
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder))
那这里就完了.....就没了,真的没了,然后我们再回到最初的doRegisterBeanDefinitions方法中,我们再看看parseBeanDefinitions(root, this.delegate);下面还有没有其他的方法需要进去看看
parseBeanDefinitions(root, this.delegate); //这个已经看完了
postProcessXml(root); // 这里不用看,因为下面的实现是空的
this.delegate = parent;
this.delegate = parent: 这里我想我大概弄懂为啥要这样子再赋值一下的意义了,在进入方法的第一步时就把这个delegate 赋值给了parent对象,最后再赋值回来,这说明它想保存当时的状态,但是为啥要这样子搞,我还不清楚
回到parseDefaultElement方法中,目前我们已经把解析import,alias,bean都说了,还有最后一个
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)){
// 检查节点名称是否等于beans // recurse
doRegisterBeanDefinitions(ele);
}
这就不用看了,因为还不是回着头再搞一次,我们本来就是通过doRegisterBeanDefinitions方法进入的嘛 ==
接着再回到AbstractRefreshableApplicationContext:
再回到这个最初的方法:
这个地方那就是返回我们上面创建的DefaultListableBeanFactory了
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); 到这里这个方法就算是结束了,做个总结:
1.new DefaultListableBeanFactory,AbstractBeanFactory中设置parentBeanFactory为ApplicationContext,factoryBean设置唯一标识
2.对ioc容器进行定制化,如设置启动参数,开启注解的自动装配等
3.解析
4.AbstractAutowireCapableBeanFactory的忽略依赖关系接口集合属性中添加了 BeanNameAware,BeanFactoryAware,BeanClassLoaderAware
5.AbstractBeanDefinitionReader中设置resourceLoader 为PathMatchingResourcePatternResolver
6.AbstractBeanDefinitionReader中设置environment 为StandardEnvironment
7.设置XmlBeanDefinitionReader的Environment属性为AbstractApplicationContext中的StandardEnvironment (在我们之前super(parent)这一步的时候给new的)
8.设置XmlBeanDefinitionReader的ResourceLoader为AbstractXmlApplicationContext
9.设置XmlBeanDefinitionReader的EntityResolver为ResourceEntityResolver
10.设置AbstractRefreshableApplicationContext的beanFactory属性为DefaultListableBeanFactory
11.返回DefaultListableBeanFactory
3.prepareBeanFactory(beanFactory):
一个一个来,先从第一个开始
这里我们应该是没有给DefaultResourcceLoader设置过属性的(反正我印象中是没有 ==),那我们就直接看ClassUtils.getDefaultClassLoader()这个方法吧
这个方法很简单吧,先记起来这里是从当前线程中获取classLoader
下一步 :beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
先来说说这两个类是啥类:
StandardBeanExpressionResolver:BeanExpressionResolver 接口的标准实现, 使用Spring的表达式模块解析和评估Spring EL
SpelParserConfiguration : SpEL表达式解析器的配置对象
SpelExpressionParser : SpEL 分析器。实例是可重用和线程安全的。
其实这种我们在之前的步骤中也有类似的,只不过在处理这块没这么高大上而已,哈哈哈哈,这里我就不细说是哪个地方了,大家可以自己再从头对着源码看一遍 >_<
我们来写个Demo看看这到底是干嘛的吧,光说的话太不清晰了
有意思的事情就这么发生了
这个可能还不怎么明显,我们再来一种玩法
注意配置文件给换了哦~
我再把这个User类给贴上就知道啥意思了 ==
这下子清晰了吧 == !
我就不介绍太多了,给大家推荐两个地址吧,哈哈哈
http://www.cnblogs.com/longronglang/p/6180023.html
https://docs.spring.io/spring/docs/4.0.x/spring-framework-reference/html/expressions.html
下一个:
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment())); //属性编辑器
自定义属性编辑器或注册表以应用于此工厂的bean。
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)):
ApplicationContextAwareProcessor:该类是BeanPostProcessor接口的实现它是用来处理和回调Aware接口的Bean,不知道大家有没有这样子使用过:
写一个接口继承ApplicationContextAware接口,重写setApplicationContext方法,然后某个实现类,就可以获取到ApplicationContext对象,具体怎么玩,我们还是来写个Demo吧
写个测试接口继承ApplicationContextAware接口
呐~就是这样了
我们来看看这个方法里头是怎么做的:
考虑到安全问题,所以直接是使用CopyOnWriteArrayList这个对象 (不得不说看Spring源码,真的是学到了很多东西)
CopyOnWriteArrayList这个类的介绍给大家推荐一个很不错的地方去看:http://ifeve.com/java-copy-on-write/
1.首先是从集合中删除掉这个对象,这里要说一点注意的就是后置处理器是按照注册的顺序提交的,所以添加的这个元素得是唯一的
2.判断是否是InstantiationAwareBeanPostProcessor接口的实例(InstantiationAwareBeanPostPressor接口可以返回代理对象,例如在创建Bean时,并不都是通过反射来为我们的bean来直接new一个对象的,很多时候都是通过cglib来生成一个代理类,这样做的好处就是更方便Spring来管理这些Bean,例如在Aop的时候,代理类就发挥了很大的作用,这里我们先不细讲,到后面自然就明白了),我们在这里穿的是一个ApplicationContextAwareProcessor对象,所以这里不管
3.判断是否是DestructionAwareBeanPostProcessor接口的实例,这里也不管,因为这里也是走false(eanPostProcessor的子接口,它添加了一个before-destruction回调,销毁bean后置处理器)
4.最后把穿入的beanPostProcessor添加进后置处理器集合中。
来简单看看这个BeanPostProcessor接口吧,看看实现它的作用在哪里.
BeanPostProcessor :
ApplicationContext会自动找到我们实现了BeanPostProcessor接口的所有类,然后把这些类都注册为后置处理器
先贴一张图 == (我写的这篇可能图片,代码贴的比较多,可能不符合很多人的阅读习惯,这里先说声不好意思了,因为我觉得贴图比较亲切 ==。)
直接来写个Demo看看这个实现了这个接口到底能干嘛吧 ==
这里我可是给user设置了name的
这里我可没有设置哟 =_=
呐,就是这样
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
这里大家应该不陌生,因为在看obtainFreshBeanFactory()该方法的源码时,也做过这种事情 == ,就是往AbstractAutowireCapableBeanFactory中的ignoreDependencyInterfaces Set集合中添加忽略依赖关系类型
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this):
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this):
beanFactory.registerResolvableDependency(ApplicationContext.class, this):
注册具有相应自动获取值的特殊依赖项类型,添加进Default'List'ableBeanFactory的resolvableDependencies集合中
先记下这里是干了这件事
来看看DefaultListableBeanFactory的体系吧
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this)):
检测实现ApplicationListener接口的bean
接着往下:
老规矩一个方法一个个来
先从transformedBeanName(name);这个方法开始
判断我们传递的name是不是以“&”开头的,要是的需要去掉再返回 ,另外我们在配置Bean时,我们是可以配置这个bean的name属性的也就是这个Bean的别名,在canonicalName方法中,我么就是通过别名来找到这个bean的ID,下面就会说到为啥要获取到Bean 的ID
if (containsSingleton(beanName) || containsBeanDefinition(beanName)) {
return (!BeanFactoryUtils.isFactoryDereference(name) || isFactoryBean(name));
}
1.首先是在DefaultSingletonBeanRegistry中判断该name是否存在singletonObjects Map属性中(singletonObjects: 缓存对象的bean的名字:bean名称到bean实例)
2.containsBeanDefinition该方法是一个抽象方法,在子类DefaultListableBeanFactory中可以找到该方法实现,该判断是判断在DefaultListableBeanFactory的be'an'DefinitionMap属性中是否存在(beanDefinitionMap: beanName与BeanDefinition对象的映射)
BeanFactory parentBeanFactory = getParentBeanFactory();
return (parentBeanFactory !=null && parentBeanFactory.containsBean(originalBeanName(name)));
我们在看obtainFreshBeanFactory()方法的源码时,在实现中已经给AbstractBeanFactory的parentBeanFactory属性设置了值,而这个值就是一开始我们传入的ApplicationContext,但是ApplicationContext并没有赋值,所以它依然还是null,那么这个方法的返回就是false
总结: beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME) : 检测 loadTimeWeaver是否存在bean实例或BeanDefinition对象
下一个:
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
transformedBeanName这个方法上面已经说了,就不重复了,就直接看看下面是干嘛的吧
(containsSingleton(beanName) || containsBeanDefinition(beanName)) &&
(!BeanFactoryUtils.isFactoryDereference(name) || isFactoryBean(beanName))
这里也是直接走的false因为初始化时这个bean是既没有实例也没有BeanDefinition的,所以这里我们就快速走完吧,其他的也不细讲了,等源码看到一定程度后,再回过头来把这些看一下写一下,效果可能会更好一点(其实我压根没看过这里的代码),既然上面已经走完了,但是我们在条件里取反,所以来看看如果不存在的情况下是对这个Bean做了什么处理吧
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
直接贴实现,哈哈哈哈,我越来越爱直接贴了
这里显示判断是否存在该bean 的实例,不存在则添加,存在则报错,单例嘛
那我们再来看看这个添加的方法
1.该bean添加实例
2. 删除该Bean对应的对象工厂
3.删除该Bean的早期单例对象
4.添加进注册的Bean集合
这里我们来看看假如这里不是空的会发生什么:
synchronized (this.beanDefinitionMap) {
if (!this.beanDefinitionMap.containsKey(beanName)) {
Set updatedSingletons =new LinkedHashSet<>(this.manualSingletonNames.size() +1);
updatedSingletons.addAll(this.manualSingletonNames);
updatedSingletons.add(beanName);
this.manualSingletonNames = updatedSingletons;
}
}else {
if (!this.beanDefinitionMap.containsKey(beanName)) {
this.manualSingletonNames.add(beanName); // 手动注册的单例程序的名称列表
}
}
最后还有一个clearByTypeCache()
getEnvironment()这个就不用说了吧,不用想也知道这是什么飞机,我们最开始就new了一个StandardEnvironment == ,下面两个也不说了,其实都一样了(夜深了,该睡了 == )
到这里prepareBeanFactory方法就算是完了,我们来总结一下吧:
1.从当前Thread中获取类加载器并且设置进beanFactory
2.设置表达式的解析策略
3.设置属性编辑器
4.设置后置处理器
5.添加忽略自动连接的给定依赖接口
6.从依赖项类型映射到相应的对象
BeanFactory -> DefaultListableBeanFactory
ResourceLoader -> AbstractApplicationContext
ApplicationEventPublisher -> AbstractApplicationContext
ApplicationContext -> AbstractApplicationContext
7.检测实现ApplicationListener接口的bean
8.检测 loadTimeWeaver是否存在bean实例或BeanDefinition对象
9.检测是否存在 environment/systemProperties/systemEnvironment 的Bean实例与BeanDefinition对象,不存在则添加
还有这么多没写 == 卧槽
感觉已经写的很多很罗嗦了,还是不要都写一块比较好,不过我会尽快把剩下的写完的,哈哈哈哈,感谢大家的阅览!(不早了,该睡了,明天还得上班呢,晚安)
包含名称和别名的bean定义的Holder。可以注册为内部bean的占位符。