Spring-5.1.5源码解析【IOC】(二)
接着上一篇没写完的咱们继续,由于实在太长了,我自己看都感觉有点写的太多了,所以就打算分开来写 ==,由于写的比较细,有些地方写点Demo出来也更好了解,所以才导致那么长,由于我也才刚开始看Spring 的源码,写关于Spring源码的初衷并不是说让别人看,而后别人看了之后能学到什么能学到多少,其实更多的是我想把自己看源码的过程给记录下来,一是加深自己的印象,这样更容易了解,一直点方法看的话可能看到主流程就不记得之前是干了啥了,二是方便以后可以重复浏览,当然,假如能给大家看源码带来帮助那是最好不过的事情了,好了,屁话也不多说了直接入正题:
在上一篇博客内容中,我们已经看理解析 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这个方法就完了,就是这样啦,哈哈哈哈,不论里头有多复杂,反正就是特么的两件事,注册我们根据<bean> 创立的BeanDefintion,注册该Bean的别名
那我们再回到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.解析<bean>并且注册BeanDefinition
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的占位符。
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » Spring-5.1.5源码解析【IOC】(二)