zoukankan      html  css  js  c++  java
  • Spring源码03---parseDefaultElement

    首先让我们回到 https://www.cnblogs.com/xiaomaomao/p/14106990.html 文末的 parseBeanDefinitions 方法,这个方法主要是解析 beans 标签下面默认的标签(beans、import、alias、bean)

    代码块一、parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)

    // DefaultBeanDefinitionDocumentReader 类中的方法
    protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
    	// 1、判断当前是否是默认的命名空间, Spring 配置文件默认的命名空间如下:
    	// xmlns="http://www.springframework.org/schema/beans" ,因为它不包含前缀 xnlns:前缀
        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)) {
                        // 1.1、解析默认名称空间下面的默认元素,包括 import、alias、beans、bean ---- (详情见代码块二)
                        parseDefaultElement(ele, delegate);
                    }
                    else {
                        // 1.2、解析默认名称空间下面的自定义元素,包括 context、tx... 等
                        delegate.parseCustomElement(ele);
                    }
                }
            }
        }
        else {
            // 2、解析自定义命名空间下的元素
            delegate.parseCustomElement(root);
        }
    }
    

    本文主要是为了弄清楚 Spring 是如何解析这些默认的元素的,对应的代码是 parseDefaultElement(ele, delegate), 这里面包含了 Spring beans 标签下的所有默认的标签的解析,包括我们最常用,也最重要的 bean 标签的解析

    代码块二、parseDefaultElement(ele, delegate)

    // DefaultBeanDefinitionDocumentReader 类中的方法
    private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
    	// 1、解析 import 标签
    	if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
    		importBeanDefinitionResource(ele);
    	}
    	// 2、解析 alias 标签
    	else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
    		processAliasRegistration(ele);
    	}
    	// 3、解析 bean 标签,这个是我们最常用也最核心的,因为我们在 Spring 配置文件中配置最多的就是 bean 标签
    	// 注意:这里解析的是 beans 标签中的一个 bean 标签
    	// 我们这里就着重看一下是如何解析 bean 标签的 ---- (详细见代码块三)
    	else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
    		processBeanDefinition(ele, delegate);
    	}
    	// 4、解析 beans 标签
    	else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
    		// 4.1、递归调用,因为默认的命名空间是 beans , beans 标签中是可以嵌套 beans 标签的
    		// 所以需要递归调用解析 beans 标签里面的 beans 标签里面的标签
    		doRegisterBeanDefinitions(ele);
    	}
    }
    

    代码块三、processBeanDefinition(ele, delegate)

    // DefaultBeanDefinitionDocumentReader 类中的方法
    protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
    	// 1、解析一个 bean 标签,并且将解析好的数据封装在 BeanDefinitionHolder 对象中 ---- (详情见代码块四)
    	BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
    	if (bdHolder != null) {
    		// 2、若存在默认标签的子节点下再有自定义属性,需要再次对自定义标签再进行解析(基本不用,不做深入解析)
    		bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
    		try {
    			// 3、注册 BeanDefinition ---- (详情见代码块八)
    			BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
    		}
    		catch (BeanDefinitionStoreException ex) {
    			getReaderContext().error("Failed to register bean definition with name '" +
    					bdHolder.getBeanName() + "'", ele, ex);
    		}
    		// 4、发送注册事件
    		getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
    	}
    }
    

    在解析 bean 标签之前,我们先去看一下我们用的最多的 bean 标签,它里面到底可以配置什么信息.

    bean 标签中可以配置的属性如下:

     bean 标签中可以配置的子标签如下:

    在执行 BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele) 这句代码之前,我们需要去看一下BeanDefinitionHolder 这个类,打开这个类,可以发现这个类总共就只有三个属性, beanName、aliases、beanDefinition ,其中最重要的就是 beanDefinition,它封装的是 bean 定义信息,也就是它可以封装 bean 标签中的除了 id 、name属性之外的所有属性,以及封装 bean 标签下面的子标签中的数据信息

    然后我们再去看一下 BeanDefinition 这个类,并且结合上图中的 bean 标签里面可以配置的属性值一起看,我们会发现, BeanDefiniton 实际上可以看做是对应 bean 标签的一个实例.

    public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
    	// 1、默认的 scope 只支持 singleton 和 prototype 两种,
    	// request, session, globalSession, application, websocket ... 这些属于 web 的扩展
    	String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
    	String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
    	// 2、应用的角色
    	int ROLE_APPLICATION = 0;
    	// 3、支持的角色
    	int ROLE_SUPPORT = 1;
    	// 4、基础架构角色
    	int ROLE_INFRASTRUCTURE = 2;
    	// 5、获取父 bean ,这里的父 bean ,不是 java 中继承关系的父类,它代表的是继承父 bean 中的属性
    	// 对应的是 bean 标签中的 parent 属性,定义父 bean 仅仅是为了继承父 bean 的属性而已,子 bean 和
    	// 父 bean 不需要存在继承关系
    	String getParentName();
    	// 6、设置 Bean 的类名称,将来是要通过反射来生成实例的
    	void setBeanClassName(String beanClassName);
    	String getBeanClassName();
    	// 7、设置 bean 的 scope 属性
    	void setScope(String scope);
    	String getScope();
    	void setLazyInit(boolean lazyInit);
    	// 8、设置是否懒加载初始化
    	boolean isLazyInit();
    	// 9、设置该 Bean 依赖的所有的 Bean ,注意:这里的依赖不是指属性依赖(如 @Autowire 标记的)
    	// 而是 bean 标签里面的 depends-on="" 属性设置的值.
    	void setDependsOn(String... dependsOn);
    	String[] getDependsOn();
    	void setAutowireCandidate(boolean autowireCandidate);
    	// 10、是否可以通过 @Atuowired 自动装配
    	boolean isAutowireCandidate();
    	void setPrimary(boolean primary);
    	// 11、是否是主要的,同一接口的多个实现,如果不指定名字的话, Spring 会优先选择设置 primary 为 true 的 bean
    	boolean isPrimary();
    	// 12、设置工厂 bean 的名称,在 Spring 中,不是所有的 bean 都是通过反射生成的,也可以通过工厂 bean 来生成
    	void setFactoryBeanName(String factoryBeanName);
    	String getFactoryBeanName();
    	// 13、设置工厂 bean 的方法名
    	void setFactoryMethodName(String factoryMethodName);
    	String getFactoryMethodName();
    	// 14、构造参数注入值
    	ConstructorArgumentValues getConstructorArgumentValues();
    	// 15、Property 属性注入值
    	MutablePropertyValues getPropertyValues();
    	boolean isSingleton();
    	boolean isPrototype();
    	// 16、如果这个 Bean 是被设置为 abstract ,那么不能实例化,常用于作为父 bean 用于继承,其实也很少用......
    	boolean isAbstract();
    	int getRole();
    	String getDescription();
    	String getResourceDescription();
    	BeanDefinition getOriginatingBeanDefinition();
    }

    看完了 BeanDefinitionHolder 和 BeanDefinition  ,我们接着回到代码吧

    代码块四、parseBeanDefinitionElement(ele)

    // BeanDefinitionParserDelegate 类中的方法
    public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
    	// 1、获取该 bean 标签中的 id 属性值
    	String id = ele.getAttribute(ID_ATTRIBUTE);
    	// 2、获取 bean 标签的 name 属性值
    	String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
    	// 3、如果 bean 标签中配置了<bean name="m1,m2;m3;m4" class="com.xiaomaomao.entity.Mango" >
    	// 它会使用 , ; 进行分割,并且将分割后的 m1 m2 m3 m4 存入 List 集合 aliases 中
    	List<String> aliases = new ArrayList<String>();
    	if (StringUtils.hasLength(nameAttr)) {
    		String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
    		aliases.addAll(Arrays.asList(nameArr));
    	}
    	// 4、将 id 值赋值给 beanName 属性
    	String beanName = id;
    	// 5、如果 bean 标签中没有配置 id 属性,只配置了 name 属性
    	if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
    		// 5.1、那么就将 name 属性的第一个值作为 beanName , 剩下的作为 别名
    		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) {
    		// 6、校验 beanName 和 aliases 的唯一性
    		checkNameUniqueness(beanName, aliases, ele);
    	}
    	// 7、解析 bean 定义元素 ---- (详情见代码块五)
    	AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
    	if (beanDefinition != null) {
    		// 8、如果 bean 标签中既没有配置 id 也没有配置 name 属性
    		// <bean class="com.xiaomaomao.entity.Mango">
    		if (!StringUtils.hasText(beanName)) {
    			try {
    				// 8.1、如果包含内部 bean 的情况下
    				if (containingBean != null) {
    					beanName = BeanDefinitionReaderUtils.generateBeanName(
    							beanDefinition, this.readerContext.getRegistry(), true);
    				}
    				else {
    					// 8.2 、不包含内部 bean 的情况下, Spring 会根据自己的规则生成 beanName
    					// beanName : com.xiaomaomao.entity.Mango#0
    					beanName = this.readerContext.generateBeanName(beanDefinition);
    					// 8.3、使用 beanClassName 作为别名
    					// beanClassName : com.xiaomaomao.entity.Mango
    					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;
    			}
    		}
    		// 9、将存放所有别名的 List 集合转化为 String 类型的数组
    		String[] aliasesArray = StringUtils.toStringArray(aliases);
    		// 10、返回 BeanDefinitionHolder 对象
    		return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
    	}
    	return null;
    }

    代码块五、parseBeanDefinitionElement(ele, beanName, containingBean)

    // BeanDefinitionParserDelegate 类中的方法
    public AbstractBeanDefinition parseBeanDefinitionElement(
    			Element ele, String beanName, BeanDefinition containingBean) {
    	// 1、将 beanName 封装进 BeanEntry 的 beanDefinitionName 属性中,然后再存入本类的 ParseState 中
    	this.parseState.push(new BeanEntry(beanName));
    
    	String className = null;
    	// 2、如果 bean 标签中配置了 class 属性,获取到 class 属性配置的值
    	if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
    		className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
    	}
    	
    	try {
    		String parent = null;
    		// 3、判断 bean 标签中是否配置了 parent 属性
    		if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
    			parent = ele.getAttribute(PARENT_ATTRIBUTE);
    		}
    		// 4、创建一个可以承载 bean 标签数据的 AbstractBeanDefinition 对象,并设置 beanClass 属性 ---- (详情见代码块六)
    		AbstractBeanDefinition bd = createBeanDefinition(className, parent);
    		// 5、解析 bean 标签的剩余属性 ---- (详情见代码块七)
    		parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
    		// 6、封装 description 属性
    		bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
    		// 7、解析 bean 标签里面的 meta 标签
    		parseMetaElements(ele, bd);
    		// 8、解析 bean 标签里面的 lookup - method 标签
    		parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
    		// 9、解析 bean 标签里面的 replace - method 标签
    		parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
    		
    		// 10、解析 bean 标签里面的 constructor-arg 标签,这个标签很重要,当我们使用有参数构造方法注入值的时候使用该标签
    		// 对 bean 对象里面的属性赋值,如果没有有参数构造方法,那么会报错
    		parseConstructorArgElements(ele, bd);
    		// 11、解析 bean 标签里面的 property 标签,这个标签也很重要,使用 无参数构造方法 和 setxxx 方法对 bean 对象进行赋值
    		parsePropertyElements(ele, bd);
    		
    		// 12、解析 bean 标签里面的 qualifier 标签 
    		parseQualifierElements(ele, bd);
    		// 13、设置当前 Spring 配置文件的资源路径
    		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 {
    		// 14、移除 ParseState 中之前存入的 BeanDefinitionName
    		this.parseState.pop();
    	}
    
    	return null;
    }

    代码块六、createBeanDefinition(className, parent)

    // BeanDefinitionParserDelegate 类中的方法
    protected AbstractBeanDefinition createBeanDefinition(String className, String parentName)
    		throws ClassNotFoundException {
    
    	return BeanDefinitionReaderUtils.createBeanDefinition(
    			parentName, className, this.readerContext.getBeanClassLoader());
    }
    
    // BeanDefinitionReaderUtils 类中的方法
    public static AbstractBeanDefinition createBeanDefinition(
    		String parentName, String className, ClassLoader classLoader) throws ClassNotFoundException {
    	// 1、新建一个 GenericBeanDefinition 对象用于承载数据,它是 AbstractBeanDefinition 的子类
    	GenericBeanDefinition bd = new GenericBeanDefinition();
    	// 2、设置 parentName
    	bd.setParentName(parentName);
    	// 3、如果 bean 标签中配置了 class 属性
    	if (className != null) {
    		if (classLoader != null) {
    			// 3.1、如果 classLoader 不为空,使用反射构建出 BeanClass ,并设置为 GenericBeanDefinition 的属性.
    			bd.setBeanClass(ClassUtils.forName(className, classLoader));
    		}
    		else {
    			// 3.2、如果 classLoader 为空,将 className 设置为 GenericBeanDefinition 的属性.
    			bd.setBeanClassName(className);
    		}
    	}
    	// 4、返回 GenericBeanDefinition 对象
    	return bd;
    }

    代码块七、parseBeanDefinitionAttributes(ele, beanName, containingBean, bd)

    // BeanDefinitionParserDelegate 类中的方法
    public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
    		BeanDefinition containingBean, AbstractBeanDefinition bd) {
    	// 1、对于 1.0 版本的 singleton 属性 bean 标签已经不支持了,如果你想使用,必须要用 scope="singleton" 去声明
    	// 否则会报错,当然 Spring 默认 bean 的 scope 就是 singleton
    	if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
    		error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
    	}
    	// 2、将 bean 标签中的 scope 属性对应的值使用 GenericBeanDefinition 对象进行封装
    	else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {
    		bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
    	}
    	// 3、在内部bean定义的情况下,从包含bean接受默认值.
    	else if (containingBean != null) {
    		bd.setScope(containingBean.getScope());
    	}
    	// 4、GenericBeanDefinition 对象封装 bean 的 abstract 属性
    	if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
    		bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
    	}
    	// 5、Spring 默认不使用懒加载,如果你想使用懒加载初始化,它的值为 false ,如果需要在 bean 标签上明确规定为 true
    	// <bean id="mango" name="m1,m2;m3;m4" class="com.xiaomaomao.entity.Mango" lazy-init="true">
    	String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
    	if (DEFAULT_VALUE.equals(lazyInit)) {
    		lazyInit = this.defaults.getLazyInit();
    	}
    	bd.setLazyInit(TRUE_VALUE.equals(lazyInit));
    	// 6、封装 autowire 属性
    	String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
    	bd.setAutowireMode(getAutowireMode(autowire));
    	// 7、封装 dependency-check 属性
    	String dependencyCheck = ele.getAttribute(DEPENDENCY_CHECK_ATTRIBUTE);
    	bd.setDependencyCheck(getDependencyCheck(dependencyCheck));
    	// 8、封装 depends-on 属性
    	if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
    		String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
    		bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));
    	}
    	// 9、封装 autowire-candidate 属性
    	String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE);
    	if ("".equals(autowireCandidate) || DEFAULT_VALUE.equals(autowireCandidate)) {
    		String candidatePattern = this.defaults.getAutowireCandidates();
    		if (candidatePattern != null) {
    			String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern);
    			bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName));
    		}
    	}
    	else {
    		bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate));
    	}
    	// 10、封装 primary 属性
    	if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) {
    		bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));
    	}
    	// 11、封装 init-method 属性
    	if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {
    		String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
    		if (!"".equals(initMethodName)) {
    			bd.setInitMethodName(initMethodName);
    		}
    	}
    	else {
    		if (this.defaults.getInitMethod() != null) {
    			bd.setInitMethodName(this.defaults.getInitMethod());
    			bd.setEnforceInitMethod(false);
    		}
    	}
    	// 12 、封装 destroy-method 属性
    	if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) {
    		String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);
    		bd.setDestroyMethodName(destroyMethodName);
    	}
    	else {
    		if (this.defaults.getDestroyMethod() != null) {
    			bd.setDestroyMethodName(this.defaults.getDestroyMethod());
    			bd.setEnforceDestroyMethod(false);
    		}
    	}
    	// 13、封装 factory-method 属性
    	if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
    		bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
    	}
    	// 14、封装 factory-bean 属性
    	if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
    		bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
    	}
    	// 15、返回封装了 bean 标签中所有属性的 GenericBeanDefinition 对象
    	return bd;
    }

    让我们回到 解析一个 bean 标签开始的位置 BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);

    // DefaultBeanDefinitionDocumentReader 类中的方法
    protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
    	// 1、解析一个 bean 标签,并且将解析好的数据封装在 BeanDefinitionHolder 对象中 ---- (详情见代码块四)
    	BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
    	if (bdHolder != null) {
    		// 2、若存在默认标签的子节点下再有自定义属性,需要再次对自定义标签再进行解析(基本不用,不做深入解析)
    		bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
    		try {
    			// 3、注册 BeanDefinition ---- (详情见代码块八)
    			BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
    		}
    		catch (BeanDefinitionStoreException ex) {
    			getReaderContext().error("Failed to register bean definition with name '" +
    					bdHolder.getBeanName() + "'", ele, ex);
    		}
    		// 4、发送注册事件
    		getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
    	}
    }
    

    到这里为止整个 BeanDefinitionHolder 对象就全部解析出来了,里面封装了 beanName、aliases、以及 BeanDefinition 对象.

     代码块八、registerBeanDefinition(bdHolder, getReaderContext().getRegistry())

    // BeanDefinitionReaderUtils 类中的方法
    public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
    		throws BeanDefinitionStoreException {
    
    	// 1、获取 beanName 
    	String beanName = definitionHolder.getBeanName();
    	// 2、注册 bean 定义 ---- (详情见代码块九)
    	registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
    
    	// 3、获取所有的别名 ---- (详情见代码块十一)
    	String[] aliases = definitionHolder.getAliases();
    	if (aliases != null) {
    		for (String alias : aliases) {
    			// 4、依次获取每一个别名,然后注册别名
    			registry.registerAlias(beanName, alias);
    		}
    	}
    }
    

    代码块九、registerBeanDefinition(beanName, definitionHolder.getBeanDefinition())

    // DefaultListableBeanFactory 类中的方法
    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");
    	// 1、我们前面创建的是一个 GenericBeanDefinition 的对象用来承载数据
    	if (beanDefinition instanceof AbstractBeanDefinition) {
    		try {
    			// 2、校验 beanDefinition
    			((AbstractBeanDefinition) beanDefinition).validate();
    		}
    		catch (BeanDefinitionValidationException ex) {
    			throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
    					"Validation of bean definition failed", ex);
    		}
    	}
    	// 3、这里定义一个 oldBeanDefinition 主要是 bean 是否可以覆盖,我们在同一个 Spring 配置文件中是不能定义
    	// 两个相同 bean 的,但是可以在不同的配置文件中定义相同的 bean ,
    	// Spring 默认 bean 可以覆盖,即如果存在两个相同名称的 bean ,后加载的那个 bean 覆盖先加载的 bean
    	BeanDefinition oldBeanDefinition;
    	
    	// 4、通过 beanName 从 beanDefinitionMap 缓存中获取 beanDefinition
    	oldBeanDefinition = this.beanDefinitionMap.get(beanName);
    	// 5、如果已经存在了 beanDefinition
    	if (oldBeanDefinition != null) {
    		// 5.1、Spring 默认是可以 bean 覆盖的,但是如果设置了不可以进行 bean 覆盖,那么就抛出异常
    		if (!isAllowBeanDefinitionOverriding()) {
    			throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
    					"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
    					"': There is already [" + oldBeanDefinition + "] bound.");
    		}
    		// 5.2、根据 Role 值进行判断,ROLE_APPLICATION=0 ROLE_SUPPORT=1 ROLE_INFRASTRUCTURE=2
    		else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
    			// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
    			if (this.logger.isWarnEnabled()) {
    				this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
    						"' with a framework-generated bean definition: replacing [" +
    						oldBeanDefinition + "] with [" + beanDefinition + "]");
    			}
    		}
    		// 5.3、如果前后加载的两个 beanDefinition 内容不同 (这里的新、旧 beanDefinition 只是 beanName 相同)
    		else if (!beanDefinition.equals(oldBeanDefinition)) {
    			if (this.logger.isInfoEnabled()) {
    				this.logger.info("Overriding bean definition for bean '" + beanName +
    						"' with a different definition: replacing [" + oldBeanDefinition +
    						"] with [" + beanDefinition + "]");
    			}
    		}
    		else {
    			if (this.logger.isDebugEnabled()) {
    				this.logger.debug("Overriding bean definition for bean '" + beanName +
    						"' with an equivalent definition: replacing [" + oldBeanDefinition +
    						"] with [" + beanDefinition + "]");
    			}
    		}
    		// 5.4、使用新加载的 beanDefinition 覆盖原先 beanDefinitionMap 缓存中的 oldBeanDefinition
    		// {beanName:oldBeanDefinition} ----> {beanName:beanDefinition}
    		this.beanDefinitionMap.put(beanName, beanDefinition);
    	}
    	// 6、如果 beanDefinitionMap 缓存中不存在 beanName
    	else {
    		// 7、如果创建 Bean 已经开始了
    		if (hasBeanCreationStarted()) {
    			// Cannot modify startup-time collection elements anymore (for stable iteration)
    			// 7.1、加锁
    			synchronized (this.beanDefinitionMap) {
    				// 7.2、将本次传进来的 beanName 和 BeanDefinition 映射放入 beanDefinitionMap 缓存
    				this.beanDefinitionMap.put(beanName, beanDefinition);
    				// 7.3、将本次传进来的 beanName 加入beanDefinitionNames 缓存
    				List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);
    				updatedDefinitions.addAll(this.beanDefinitionNames);
    				updatedDefinitions.add(beanName);
    				this.beanDefinitionNames = updatedDefinitions;
    				// 7.4、如果 manualSingletonNames 包含 beanName ,将 beanName 从 manualSingletonNames 移除
    				if (this.manualSingletonNames.contains(beanName)) {
    					Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);
    					updatedSingletons.remove(beanName);
    					this.manualSingletonNames = updatedSingletons;
    				}
    			}
    		}
    		// 8、目前在注册阶段,还没有到创建 bean 阶段,我们这里是初次启动项目,肯定没有创建 bean
    		else {
    			// Still in startup registration phase
    			// 8.1、将 beanName beanDefinition 以键值对的形式存入 beanDefinitionMap 缓存中
    			this.beanDefinitionMap.put(beanName, beanDefinition);
    			// 8.2、将 beanName 存入 beanDefinitionNames 缓存中
    			this.beanDefinitionNames.add(beanName);
    			// 8.3、移除 manualSingletonNames 缓存中的 beanName
    			this.manualSingletonNames.remove(beanName);
    		}
    		this.frozenBeanDefinitionNames = null;
    	}
    	// 9、如果存在相同 beanName 的 BeanDefinition,并且 beanName 已经存在单例对象,则将该 beanName 对应的缓存信息、单例对象清除,
        // 因为这些对象都是通过 oldBeanDefinition 创建出来的,需要使用新的 BeanDefinition 覆盖掉
        // 我们需要用新的 BeanDefinition(也就是本次传进来的 beanDefinition)来创建这些缓存和单例对象
    	// (详情见代码块十)
    	if (oldBeanDefinition != null || containsSingleton(beanName)) {
    		resetBeanDefinition(beanName);
    	}
    }
    

    代码块十、resetBeanDefinition(beanName)

    // DefaultListableBeanFactory 类中的方法
    protected void resetBeanDefinition(String beanName) {
        // Remove the merged bean definition for the given bean, if already created.
        // 1、删除 beanName 的 mergedBeanDefinitions 缓存(如果有的话)
        clearMergedBeanDefinition(beanName);
     
        // Remove corresponding bean from singleton cache, if any. Shouldn't usually
        // be necessary, rather just meant for overriding a context's default beans
        // (e.g. the default StaticMessageSource in a StaticApplicationContext).
        // 2、从单例缓存中删除该 beanName 对应的 bean(如果有的话)
        destroySingleton(beanName);
     
        // Reset all bean definitions that have the given bean as parent (recursively).
        // 3.重置 beanName 的所有子 Bean 定义(递归)
        for (String bdName : this.beanDefinitionNames) {
            if (!beanName.equals(bdName)) {
                BeanDefinition bd = this.beanDefinitionMap.get(bdName);
                // 当前遍历的 BeanDefinition 的 parentName 为 beanName,则递归调用 resetBeanDefinition 进行重置
                if (beanName.equals(bd.getParentName())) {
                    resetBeanDefinition(bdName);
                }
            }
        }
    }
    

    代码块十一、resetBeanDefinition(bdName)

    // SimpleAliasRegistry 类中的方法
    public void registerAlias(String name, String alias) {
    	Assert.hasText(name, "'name' must not be empty");
    	Assert.hasText(alias, "'alias' must not be empty");
    	// 1、如果 beanName 和别名相同,则 alias 无效,从 aliasMap 缓存中移除
    	if (alias.equals(name)) {
    		this.aliasMap.remove(alias);
    	}
    	else {
    		// 2、通过 alias 从 aliasMap 缓存中获取 beanName 
    		String registeredName = this.aliasMap.get(alias);
    		if (registeredName != null) {
    			// 3、校验通过 alias 获取到的 beanName 和传进来的 beanName 是否相等,如果相等,代表已经别名已经注册了,无需再注册
    			if (registeredName.equals(name)) {
    				// An existing alias - no need to re-register
    				return;
    			}
    			// 4、如果不允许别名覆盖,则抛出异常
    			if (!allowAliasOverriding()) {
    				throw new IllegalStateException("Cannot register alias '" + alias + "' for name '" +
    						name + "': It is already registered for name '" + registeredName + "'.");
    			}
    		}
    		// 5、校验 name 和 alias 是否循环引用
    		checkForAliasCircle(name, alias);
    		// 6、将 alias beanName 的键值对存入 aliasMap 缓存中
    		this.aliasMap.put(alias, name);
    	}
    }
    

    到这里,一个 bean 标签的解析已经完成了,代码回到了这里

    总结:

    1、我们可以重新梳理一下思路,我们首先将 Spring 配置文件 xml 中的 bean 配置信息进行了解析,并构建了 AbstractBeanDefinition (GenericBeanDefinition ) 对象来存放所有解析出来的 bean 标签的所有属性和 bean 标签下面的子标签中的信息.

    2、然后,我们将 AbstractBeanDefinition、beanName、aliasesArray 构建成 BeanDefinitionHolder 对象并返回.

    3、最后,我们通过 BeanDefinitionHolder 将 BeanDefinition 和 beanName 注册到 BeanFactory 中,也就是存放到缓存中。

    执行完 parseDefaultElement 方法,我们得到了两个重要的缓存:

    beanDefinitionNames [beanName] 缓存

    beanDefinitionMap {beanName:beanDefinition} 缓存

    参考:https://blog.csdn.net/v123411739/article/details/86669952

  • 相关阅读:
    以UIWebView的方式来播放网络多媒体档案
    Cocoa.Programming.for.Mac系统文章翻译
    iOS开发教程:Storyboard全解析第二部分
    boost日期、时间操作
    使用thrift大量编译警告消息方法
    一键自动往crontab添加条目脚本
    apache thrift的不足
    将Fedora 18 LXDE安装到U盘和进入图形界面的方法
    boost库thread.hpp编译警告(type attributes are honored only at type definition)已修复
    平板电视必知知识
  • 原文地址:https://www.cnblogs.com/xiaomaomao/p/14117395.html
Copyright © 2011-2022 走看看