SpringMVC通过一个配置文件描述Bean以及Bean之间的依赖关系,利用java的反射机制实例化Bean并建立Bean之间的依赖关系。IOC容器在完成这些底层工作的基础还提供了Bean的实例缓、生命周期、Bean实例代理等。BeanFacory是SpringMVC框架最核心的接口,他提供了最高级IOC的配置机制。ApplicationContext由BeanFactory派生而来,这也说明了 SpringMVC容器中运行的主体对象是 Bean,另外 ApplicationContext 继承了 ResourceLoader 接口,使得 ApplicationContext 可以访问到任何外部资源,提供了更多面向实际应用的功能。SpringMVC初始化时在什么时候读取配置我们配置好的bean的文件,怎么解析和注册Bean?接下来我们带着问题来分析。
上一篇,我们在介绍DispatcherServlet初始化的介绍时,父类FrameworkServlet在创建上下文时,调用了一个重启上下文时,并初始化Bean。如图所示:
ConfigurableWebApplicationContext wac;调用了wac.refresh();方法,完成了对ApplicationContext的初始化,注册啊,封装bean的工作,由ConfigurableWebApplicationContext 的子类AbstractApplicationContext实现了bean初始化。我们来了解一下上下文(容器)整个继承关系。这边的箭头表示继承或者实现的,如图所示:
从上图我们可以看出,ApplicationContext也是继承BeanFactory,ApplicationContext 也继承了 ResourceLoader 接口,使得 ApplicationContext 可以访问到任何外部资源,提供了更多面向实际应用的功能,我们通过refresh为入口点,分析Bean整个初始化过程,并了解ApplicationContext的子类AbstractApplicationContext做了哪些工作并了解父类实现了哪些功能?每个接口都有他使用的场合,它主要是为了区分在 SpringMVC内部在操作过程中对象的传递和转化过程中,对对象的数据访问所做的限制。我们现在先头脑中有这个继承的关系图,以后深度的了解,比较不会那么晕,这样思路就比较清晰,我们以refresh为入口点,带着这些问题进行解析。
refresh方法的源代码如下:
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 准备对上下文进行刷新
prepareRefresh();
// 初始化beanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 为BeanFactory配置容器特性,例如类加载器、事件处理器等
prepareBeanFactory(beanFactory);
try {
// 为容器的某些子类指定特殊的BeanPost事件处理器
postProcessBeanFactory(beanFactory);
// 调用beanFactory处理器
invokeBeanFactoryPostProcessors(beanFactory);
// 注册beanFactory处理器
registerBeanPostProcessors(beanFactory);
// 初始化消息源
initMessageSource();
// 初始化上下文事件广播.
initApplicationEventMulticaster();
// 初始化其它特殊bean,由子类来实现
onRefresh();
// 注册事件监听器.
registerListeners();
// 初始化所有单实例的bean,使用懒加载除外
finishBeanFactoryInitialization(beanFactory);
// 完成刷新并发布容器刷新事件
finishRefresh();
}catch (BeansException ex) {
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
}
}
这个方法做了很多事情,主要有初始化
beanFactory 、注册
BeanFactory处理器等工作。我们接下来对里面重要的功能进行解析,它怎么读取我们配置文件并解析文件和注册配置文件里的bean。
初始化beanFactory工厂时,就对读取我们配置文件并解析文件和注册配置文件里的Bean,是由AbstractApplicationContext.obtainFreshBeanFactory方法实现的,源代码如下:
**
* Tell the subclass to refresh the internal bean factory.
* @return the fresh BeanFactory instance
* @see #refreshBeanFactory()
* @see #getBeanFactory()
*/
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
@Override
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
第一步:
refreshBeanFactory 先销毁所有Bean,关闭BeanFactory,然后重新创建一个BeanFactory,并将其赋给BeanFactory实例变量。我们先看一下它怎么创建BeanFactory?
createBeanFactory这个方法是创建新的BeanBeanFactory ,而BeanFactory 的原始对象是 DefaultListableBeanFactory,这个非常关键,因为他设计到后面对这个对象的多种操作,DefaultListableBeanFactory是整个Bean加载的核心部分,是SpringMVC注册及加载Bean的默认实现。
protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}
初始化BeanFactory时,判断是否有父BeanFactory,如果有设置,如果没有就为null。
protected BeanFactory getInternalParentBeanFactory() {
return (getParent() instanceof ConfigurableApplicationContext) ?
((ConfigurableApplicationContext) getParent()).getBeanFactory() : getParent();
}
获取父BeanFactory
public DefaultListableBeanFactory(BeanFactory parentBeanFactory) {
super(parentBeanFactory);
}
public AbstractAutowireCapableBeanFactory(BeanFactory parentBeanFactory) {
this();
setParentBeanFactory(parentBeanFactory);
}
setParentBeanFactory设置父BeanFactory。
我们对BeanFactory继承关系了解一下,为后面的解析提供比较清晰的路线,如图所示:
现在BeanFactory创建好了, ApplicationContext 继承了BeanFactory,还 继承了 ResourceLoader 接口,使得 ApplicationContext 可以访问到任何外部资源, 提供了更多面向实际应用的功能,接下来我们进行第二步,分析解析配置文件和注册Bean。
第二步:先转码在读取配置文件
loadBeanDefinitions(beanFactory) 将找到答案,这个方法将开始加载、解析 Bean 的定义,也就是把用户定义的数据结构转化为 Ioc 容器中的特定数据结构。我们要分析一下这个方法。
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
initBeanDefinitionReader(beanDefinitionReader);
loadBeanDefinitions(beanDefinitionReader);
}
XmlBeanDefinitionReader 来读取并解析 xml 文件,XmlBeanDefinitionReader 是 BeanDefinitionReader 接口的实现。我们来看一下继承关系,如图所示:
BeanDefinitionReader 读取Resource所指向的配置文件资源,然后解析配置文件,配置文件中每一个Bean解析成一个BeanDefinition对象,并保存到BeanDefinitionRegistry中。我们这边先了解一下。先实现通过BeanFactory创建XmlBeanDefinitionReader对象,然后为XmlBeanDefinitionReader 配置ResourceLoader,因为DefaultResourceLoader是父类,所以this可以直接被使用,ResourceLoader对资源的加载。 如图所示:
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {
String[] configLocations = getConfigLocations();
if (configLocations != null) {
for (String configLocation : configLocations) {
reader.loadBeanDefinitions(configLocation);
}
}
}
@Override
public String[] getConfigLocations() {
return super.getConfigLocations();
}
protected String[] getConfigLocations() {
return (this.configLocations != null ? this.configLocations : getDefaultConfigLocations());
}
由 AbstractRefreshableWebApplicationContext父类AbstractRefreshableConfigApplicationContext实现getConfigLocations方法,获取了web.xml配置的param-value的值,然后getConfigLocations保存在数组里面。如图所示:
现在获取了param-value的值,接下去就开始读取配置文件,具体实现时由XmlBeanDefinitionReader父类AbstractBeanDefinitionReader实现的,
reader.loadBeanDefinitions(configLocation);源代码:
public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
return loadBeanDefinitions(location, null);
}
public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {
ResourceLoader resourceLoader = getResourceLoader();
if (resourceLoader == null) {
throw new BeanDefinitionStoreException(
"Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
}
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);
}
}
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;
}
}
这个方法有一个ResourcePatternResolver加载了
web.xml配置的
param-value对应的资源,例如
classpath:xxx*.xml 加载了
xxx下为
xml为后缀的文件资源,
loadBeanDefinitions进行对加载进来的资源进行解析。在解析之前先进行转码,是通过
EncodedResource
对资源文件进行转码,源代码如下:
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
return loadBeanDefinitions(new EncodedResource(resource));
}
对
资源文件转码完,就开始读进来,以流的形式,源代码如下:
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, "EncodedResource must not be null");
if (logger.isInfoEnabled()) {
logger.info("Loading XML bean definitions from " + encodedResource.getResource());
}
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet<EncodedResource>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
try {
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
inputStream.close();
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
}
finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
}
说明:
(1)getValidationModeForResource(resource);获取对XML文件的验证模式
(2)Document doc = this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware());加载XML文件,并获取对应的Document。这边是把配置文件读进来,以Document 形式存储。
(3)registerBeanDefinitions(doc, resource);解析并注册bean。
第三步:解析并注册bean,解析 Bean 的定义,也就是把用户定义的数据结构转化为 Ioc 容器中的特定数据结构。我们继续第二步中先把文件读进来,接下来进行解析和注册是由registerBeanDefinitions(doc, resource);这个方法实现的,源代码如下:
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
documentReader.setEnvironment(this.getEnvironment());
int countBefore = getRegistry().getBeanDefinitionCount();//<span style="color:#ff0000;">统计前BeanDefinition加载个数</span>
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
<span style="color:#ff0000;">//解析并注册bean</span>
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
logger.debug("Loading bean definitions");
Element root = doc.getDocumentElement();
doRegisterBeanDefinitions(root);
}
protected void doRegisterBeanDefinitions(Element root) {
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
Assert.state(this.environment != null, "Environment must be set for evaluating profiles");
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
if (!this.environment.acceptsProfiles(specifiedProfiles)) {
return;
}
}
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(this.readerContext, root, parent);
preProcessXml(root);
parseBeanDefinitions(root, this.delegate);
postProcessXml(root);
this.delegate = parent;
}
说明:
(1)public static final String PROFILE_ATTRIBUTE = "profile";判断bean节点是否定义了profile属性,如果有,就要到环境变量中去寻找
(2)BeanDefinitionParserDelegate是对BeanDefinition的解析的,这里就不具体分析了。
(2) parseBeanDefinitions(root, this.delegate);把bean注册到BeanDefinition对象中。
这个 parseBeanDefinitions(root, this.delegate)开始注册了,我们解析到重点了,源代码如下:
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);
}
}
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
//对IMPORT标签进行处理的
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
//对ALIAS标签进行处理的
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
//对BEAN标签进行处理的
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
//我们来对处理bean标签进行分析
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
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));
}
}
解析Bean的id、name等元素设置到BeanDefinition然后放到放到BeanDefinitionHolder中,这个是由parseBeanDefinitionElement进行处理的,源代码如下:
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
//解析ID属性
String id = ele.getAttribute(ID_ATTRIBUTE);
//解析name属性
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
List<String> aliases = new ArrayList<String>();
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}
String beanName = id;
if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
beanName = aliases.remove(0);
if (logger.isDebugEnabled()) {
logger.debug("No XML 'id' specified - using '" + beanName +
"' as bean name and " + aliases + " as aliases");
}
}
if (containingBean == null) {
checkNameUniqueness(beanName, aliases, ele);
}
//对其它标签进行解析
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
if (!StringUtils.hasText(beanName)) {
try {
if (containingBean != null) {
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
}
else {
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);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Neither XML 'id' nor 'name' specified - " +
"using generated bean name [" + beanName + "]");
}
}
catch (Exception ex) {
error(ex.getMessage(), ele);
return null;
}
}
String[] aliasesArray = StringUtils.toStringArray(aliases);
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
return null;
}
//对其它标签进行解析
public AbstractBeanDefinition parseBeanDefinitionElement(
Element ele, String beanName, BeanDefinition containingBean) {
this.parseState.push(new BeanEntry(beanName));
//对class属性进行解析
String className = null;
if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
}
try {
//对parent属性进行解析
String parent = null;
if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
parent = ele.getAttribute(PARENT_ATTRIBUTE);
}
AbstractBeanDefinition bd = createBeanDefinition(className, parent);
//解析默认bean的各种属性
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
//解析元数据
parseMetaElements(ele, bd);
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
//解析构造函数
parseConstructorArgElements(ele, bd);
//解析Property
parsePropertyElements(ele, bd);
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;
}
对bean的id、name、class等属性的解析并设置到BeanDefinition然后放到放到BeanDefinitionHolder中,并放入到IOC容器中建立对应的数据结构。
现在IOC容器中已经建立对应的数据结构,接下来开始对对bean进行注册,
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());源代码如下:
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 aliase : aliases) {
registry.registerAlias(beanName, aliase);
}
}
}
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
synchronized (this.beanDefinitionMap) {
Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
if (!this.allowBeanDefinitionOverriding) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
"': There is already [" + oldBeanDefinition + "] bound.");
}
else {
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName +
"': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
}
}
else {
this.beanDefinitionNames.add(beanName);
this.frozenBeanDefinitionNames = null;
}
this.beanDefinitionMap.put(beanName, beanDefinition);
}
resetBeanDefinition(beanName);
}
先检查是不是有相同名字的BeanDefinition已经在IoC容器中注册了,如果有相同名字的BeanDefinition,但又不允许覆盖,那么会抛出异常,如果可以可以覆盖,或者IOC容器中没注册,然后把Bean的名字存入到beanDefinitionNames的同时,把beanName作为Map的key,把beanDefinition作为value存入到IoC容器持有的BeanDefinitionMap中去。
总结:
(1)SpringMVC先创建BeanFactory时先销毁所有Bean,关闭BeanFactory,然后重新创建一个BeanFactory,并将其赋给BeanFactory实例变量。
(2)创建好了BeanFactory,并设置好环境,ApplicationContext 继承了 ResourceLoader 接口,并通过ResourcePatternResolver加载了web.xml配置的param-value对应的资源,例如classpath:xxx*.xml 加载了xxx下为xml为后缀的文件资源,loadBeanDefinitions进行对加载进来的资源进行解析,在解析之前先进行转码,是通过EncodedResource对资源文件进行转码
(3)对读取进来的配置文件进行验证,是否是XML格式的,然后配置文件中的Bean的id、name、class等属性的解析并设置到BeanDefinition然后放到放到BeanDefinitionHolder中,并放入到IOC容器中建立对应的数据结构。是以Document形式的存储的。
(4)在IOC容器中已经建立对应的数据结构,解析 Bean 的定义和注册,先检查是不是有相同名字的BeanDefinition已经在IoC容器中注册了,如果有相同名字的BeanDefinition,但又不允许覆盖,那么会抛出异常,如果可以可以覆盖,或者IOC容器中没注册,然后把Bean的名字存入到beanDefinitionNames的同时,把beanName作为Map的key,把beanDefinition作为value存入到IoC容器持有的BeanDefinitionMap中去。