本篇文章给大家谈谈公司注册网站源码分享,以及公司网站申请注册对应的知识点,文章可能有点长,但是希望大家可以阅读完,增长自己的知识,最重要的是希望对各位有所帮助,可以解决了您的问题,不要忘了收藏本站喔。
前言
上篇文章我们对BeanDefinition进行了讨论,BeanDefinition是对Bean的定义,其保存了Bean的各种信息,如属性、构造方法参数、是否单例、是否延迟加载等。这里的注册Bean是指将Bean定义成BeanDefinition,之后放入Spring容器中,我们常说的容器其实就是Beanfactory中的一个Map,key是Bean的名称,value是Bean对应的BeanDefinition,这个注册Bean的方法由BeanFactory子类实现。
注:本篇文章使用的SpringBoot版本为2.0.3.RELEASE,其Spring版本为5.0.7.RELEASE
正文
在前面的《三、Spring源码之-ApplicationContext上下文启动准备》文章中说过,当前环境的BeanFactory实现类是DefaultListableBeanFactory,是一个具有注册功能的完整Bean工厂,注册Bean的方法是registerBeanDefinition,DefaultListableBeanFactory通过实现BeanDefinitionRegistry接口,重写该方法。
publicclassDefaultListableBeanFactoryextendsAbstractAutowireCapableBeanFactory\n\t\timplementsConfigurableListableBeanFactory,BeanDefinitionRegistry,Serializable{\n\nprivatefinalMap<String,BeanDefinition>beanDefinitionMap=newConcurrentHashMap<>(256);\n\n//…\n\n//ApplicationContext继承了BeanDefinitionRegistry,具有BeanDefinition的注册功能\n@Override\n\tpublicvoidregisterBeanDefinition(StringbeanName,BeanDefinitionbeanDefinition)\n\t\t\tthrowsBeanDefinitionStoreException{\n\t//…\nthis.beanDefinitionMap.put(beanName,beanDefinition);\n}\n//…\n}\n\n
讨论registerBeanDefinition方法之前,先来简单介绍BeanDefinitionRegistry接口。
1、BeanDefinitionRegistry简介
BeanDefinitionRegistry是一个接口,它定义了关于BeanDefinition的注册、移除、查询等一系列的操作。
publicinterfaceBeanDefinitionRegistryextendsAliasRegistry{\n\n\t//注册BeanDefinition\n\tvoidregisterBeanDefinition(StringbeanName,BeanDefinitionbeanDefinition)throwsBeanDefinitionStoreException;\n\n\t//移除BeanDefinition\n\tvoidremoveBeanDefinition(StringbeanName)throwsNoSuchBeanDefinitionException;\n\n\t//获取BeanDefinition\n\tBeanDefinitiongetBeanDefinition(StringbeanName)throwsNoSuchBeanDefinitionException;\n\n\t//根据beanName判断容器是否存在对应的BeanDefinition\n\tbooleancontainsBeanDefinition(StringbeanName);\n\n\t//获取所有的BeanDefinition\n\tString[]getBeanDefinitionNames();\n\n\t//获取BeanDefinition数量\n\tintgetBeanDefinitionCount();\n\n\t//判断beanName是否被占用\n\tbooleanisBeanNameInUse(StringbeanName);\n}\n\n
该接口有三个实现类:DefaultListableBeanFactory、GenericApplicationContext、SimpleBeanDefinitionRegistry,其中GenericApplicationContext底层调用的是DefaultListableBeanFactory中的实现方法,所以严格意义上来说,只有两个实现类。这里,我们主要讨论DefaultListableBeanFactory中的方法实现。
2、registerBeanDefinition方法注册Bean
前面说过registerBeanDefinition方法的主要实现类是DefaultListableBeanFactory:
publicclassDefaultListableBeanFactoryextendsAbstractAutowireCapableBeanFactoryimplementsConfigurableListableBeanFactory,BeanDefinitionRegistry,Serializable{\n\n//…\n\n//存储所有的BeanDefinition,key是Bean的名称。我们一直称呼的容器,底层就是这个Map\nprivatefinalMap<String,BeanDefinition>beanDefinitionMap=newConcurrentHashMap<>(256);\n//存储所有Bean名称\nprivatevolatileList<String>beanDefinitionNames=newArrayList<>(256);\n//存储手动注册的单例Bean名称\nprivatevolatileSet<String>manualSingletonNames=newLinkedHashSet<>(16);\n//存储冻结的BeanDefinition,留作后面缓存用\n\tprivatevolatileString[]frozenBeanDefinitionNames;\n\n…\n\n//方法的入参为Bean名称和对应的BeanDefinition\n@Override\n\tpublicvoidregisterBeanDefinition(StringbeanName,BeanDefinitionbeanDefinition)throwsBeanDefinitionStoreException{\n\n\t\tAssert.hasText(beanName,&34;);\n\t\tAssert.notNull(beanDefinition,&34;);\n\n//如果beanDefinition的实例为AbstractBeanDefinition,则进行验证\n\t\tif(beanDefinitioninstanceofAbstractBeanDefinition){\n\t\t\ttry{\n\t\t\t//验证:\n\t\t\t//如果有重写方法,但是是工厂方法,则抛出异常,因为重写方法需要代理,而工厂方法无法代理;\n\t\t\t//通过方法名称,判断Bean中该名称方法存在的数量,0:方法不存在,报错;1:方法非重载,overloaded属性设为false;\n\t\t\t\t((AbstractBeanDefinition)beanDefinition).validate();\n\t\t\t}\n\t\t\tcatch(BeanDefinitionValidationExceptionex){\n\t\t\t\tthrownewBeanDefinitionStoreException(beanDefinition.getResourceDescription(),beanName,\n\t\t\t\t\t\t&34;,ex);\n\t\t\t}\n\t\t}\n\n\t\tBeanDefinitionoldBeanDefinition;\n//先从beanDefinitionMap中尝试获取beanName对应BeanDefinition\n\t\toldBeanDefinition=this.beanDefinitionMap.get(beanName);\n\n\t\t//不为null,则beanName对应的BeanDefinition已经存在\n\t\tif(oldBeanDefinition!=null){\n\n\t\t\t//是否应允许覆盖BeanDefinition,不允许则抛异常\n\t\t\tif(!isAllowBeanDefinitionOverriding()){\n\t\t\t\tthrownewBeanDefinitionStoreException(beanDefinition.getResourceDescription(),beanName,\n\t\t\t\t\t\t&34;+beanDefinition+&39;&34;&34;+oldBeanDefinition+&34;);\n\t\t\t}\n\n\t\t\t/*****************************若允许覆盖*****************************/\n\n\t\t\t//判断Bean的角色大小:\n\t\t\t//0:用户定义的Bean、1:来源于配置文件的Bean、2:Spring内部的Bean;\n\t\t\t//当原BeanDefinition角色小于新的BeanDefinition角色时,输出一个warn日志,提示BeanDefinition被覆盖\n\t\t\telseif(oldBeanDefinition.getRole()<beanDefinition.getRole()){\n\t\t\t\t//e.g.wasROLE_APPLICATION,nowoverridingwithROLE_SUPPORTorROLE_INFRASTRUCTURE\n\t\t\t\tif(this.logger.isWarnEnabled()){\n\t\t\t\t\tthis.logger.warn(&39;&34;&34;+\n\t\t\t\t\t\t\toldBeanDefinition+&34;+beanDefinition+&34;);\n\t\t\t\t}\n\t\t\t}\n\t\t\t//当新BeanDefinition属性值不等于原BeanDefinition属性值时,输出info提示信息\n\t\t\telseif(!beanDefinition.equals(oldBeanDefinition)){\n\t\t\t\tif(this.logger.isInfoEnabled()){\n\t\t\t\t\tthis.logger.info(&39;&34;&34;+oldBeanDefinition+\n\t\t\t\t\t\t\t&34;+beanDefinition+&34;);\n\t\t\t\t}\n\t\t\t}\n\t\t\t//最后,输出debug日志信息:用等效的新BeanDefinition覆盖原BeanDefinition\n\t\t\telse{\n\t\t\t\tif(this.logger.isDebugEnabled()){\n\t\t\t\t\tthis.logger.debug(&39;&34;&34;+oldBeanDefinition+\n\t\t\t\t\t\t\t&34;+beanDefinition+&34;);\n\t\t\t\t}\n\t\t\t}\n\t\t\t//添加至BeanDefinition集合,并覆盖原BeanDefinition\n\t\t\tthis.beanDefinitionMap.put(beanName,beanDefinition);\n\t\t}\n\n\t\t//Map中无对应的BeanDefinition,则直接注册\n\t\telse{\n\t\t//已开始创建Bean\n\t\t\tif(hasBeanCreationStarted()){\n\t\t\t\tsynchronized(this.beanDefinitionMap){\n\t\t\t\t//将Bean对应的BeanDefinition放入beanDefinitionMap中\n\t\t\t\t\tthis.beanDefinitionMap.put(beanName,beanDefinition);\n\n\t//创建新的beanNames集合,并将已缓存的beanName和新的beanName加入该集合\n\t\t\t\t\tList<String>updatedDefinitions=newArrayList<>(this.beanDefinitionNames.size()+1);\n\t\t\t\t\tupdatedDefinitions.addAll(this.beanDefinitionNames);\n\t\t\t\t\tupdatedDefinitions.add(beanName);\n\t\t\t\t\tthis.beanDefinitionNames=updatedDefinitions;\n\n\t\t\t\t\t//在手动注册Bean的集合中,如果存在同名的beanName,则将集合中同名的beanName删除\n\t\t\t\t\tif(this.manualSingletonNames.contains(beanName)){\n\t\t\t\t\t\tSet<String>updatedSingletons=newLinkedHashSet<>(this.manualSingletonNames);\n\t\t\t\t\t\tupdatedSingletons.remove(beanName);\n\t\t\t\t\t\tthis.manualSingletonNames=updatedSingletons;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t//仍处于启动注册阶段\n\t\t\telse{\n\t\t\t\t//将当前Bean对应的BeanDefinition放入beanDefinitionMap中\n\t\t\t\tthis.beanDefinitionMap.put(beanName,beanDefinition);\n\t\t\t\t//将当前beanName放入beanDefinitionNames\n\t\t\t\tthis.beanDefinitionNames.add(beanName);\n\t\t\t\t//删除手动注册Bean集合中同名的beanName\n\t\t\t\tthis.manualSingletonNames.remove(beanName);\n\t\t\t}\n\n\t\t\t//将存储冻结BeanDefinition的Map置为null\n\t\t\tthis.frozenBeanDefinitionNames=null;\n\t\t}\n\n//当前注册的BeanDefinition已在beanDefinitionMap中存在,或者其实例已在存储单例Bean的Map中存在\n\t\tif(oldBeanDefinition!=null||containsSingleton(beanName)){\n\n\t\t\t//重置BeanDefinition,主要做一些清理工作\n\t\t\tresetBeanDefinition(beanName);\n\t\t}\n\t}\n}\n\n
执行完registerBeanDefinition方法后,Bean的名称和对应的BeanDefinition就被放入了容器中,后续获取Bean也是从这个容器中获取。
当然,DefaultListableBeanFactory还实现了BeanDefinitionRegistry接口的其它方法,如对BeanDefinition进行移除、判断是否存在、获取数量等操作,其实都是围绕beanDefinitionMap这个Map进行的,这里就不详细介绍。
需要注意的是registerBeanDefinition方法会在后面频繁被调用,后续会逐一提到。
最后
这篇文章主要对注册Bean的核心方法进行讨论,但其中涉及到了单例Bean实例注册,这和当前文章的注册Bean不同,当前保存的是任意Bean的信息,而后者,保存的是单例Bean的对象,我们将在下篇文章详细讨论。
文章到此结束,如果本次分享的公司注册网站源码分享和公司网站申请注册的问题解决了您的问题,那么我们由衷的感到高兴!