第一次总是很生涩-小白开始学Spring-BeanDefinition是怎么创建出来的

2.2 望闻问切

到这里我们可以看到,我们可以通过这种方式注入bean了。接下来我们就开启debug模式,一步一步来看看

2.2.1 ClassPathXmlApplicationContext.java 构造方法
ApplicationContext applicationContext = 
    new ClassPathXmlApplicationContext("classpath:application.xml");

调用ClassPathXmlApplicationContext构造方法的时候,我们可以看到源码:
    
    public ClassPathXmlApplicationContext(
			String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
			throws BeansException {

		super(parent);
    //通过调试我们可以看到这一行就是设置配置文件的位置
    //即上面的传入构造函数的参数  configLocations = "classpath:application.xml"
		setConfigLocations(configLocations);
		if (refresh) {
            //这是关键的方法,为什么这个方法不是什么init或者create的呢?为啥会叫refres呢?
            //因为applicationContext是可以重建的,调用这个方法是可以重新初始化applicationContext的
            //接下来我们细看一下refresh()方法是怎样的
			refresh();
		}
	}
2.2.2 AbstractApplicationContext.java refresh() 把握整体
@Override
	public void refresh() throws BeansException, IllegalStateException {
        //首先这里加了个锁,这个startupShutdownMonitor就是一个Object对象
        //加锁的目的在于保证容器的完整性,因为可能出现当前refresh()还没有结束,又来一次更新或者销毁容器
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
            //会初始化占位符、属性源等
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
            /*
            通过这个obtainFreshBeanFactory方法,会初始化beanFactory,
            加载注册bean等,但现在的bean还没有初始化。
            得到的beanFactory里面已经包含了配置文件里配置的bean的信息,用beanDefinitionMap保存
            这个map以我们配置的bean的id或者name作为key,以BeanDefinition实体作为value
            (同时这个id或者name的值会被保存到beanDefinitionNames这个ArrayList里面)
            由此可见 这个方法是多么的重要! 要仔细的看这个方法的具体实现*/
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				initMessageSource();
 
				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				onRefresh();

				// Check for listener beans and register them.
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
			}
		}
	}
2.2.2.1 AbstractApplicationContext.java refresh()->prepareRefresh()
这个方法主要就是对xml配置文件的校验等:
	/**
	 * Prepare this context for refreshing, setting its startup date and
	 * active flag as well as performing any initialization of property sources.
	 */
	protected void prepareRefresh() {
		// Switch to active.
        //记录时间,设置closed = false , active =  true
		this.startupDate = System.currentTimeMillis();
		this.closed.set(false);
		this.active.set(true);

		if (logger.isDebugEnabled()) {
			if (logger.isTraceEnabled()) {
				logger.trace("Refreshing " + this);
			}
			else {
				logger.debug("Refreshing " + getDisplayName());
			}
		}

		// Initialize any placeholder property sources in the context environment.
        //这个方法是替换(初始化)属性源的方法,子类中没有默认实现
		initPropertySources();

		// Validate that all properties marked as required are resolvable:
		// see ConfigurablePropertyResolver#setRequiredProperties
        //校验我们的配置文件是否是正确的、可解析的
		getEnvironment().validateRequiredProperties();

		// Store pre-refresh ApplicationListeners...
		if (this.earlyApplicationListeners == null) {
			this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
		}
		else {
			// Reset local application listeners to pre-refresh state.
			this.applicationListeners.clear();
			this.applicationListeners.addAll(this.earlyApplicationListeners);
		}

		// Allow for the collection of early ApplicationEvents,
		// to be published once the multicaster is available...
		this.earlyApplicationEvents = new LinkedHashSet<>();
	}
2.2.2.2 AbstractApplicationContext.java refresh()->obtainFreshBeanFactory()
/**
	 * Tell the subclass to refresh the internal bean factory.
	 * @return the fresh BeanFactory instance
	 * @see #refreshBeanFactory()
	 * @see #getBeanFactory()
	 */
	protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		refreshBeanFactory();
		return getBeanFactory();
	}

看来refreshBeanFactory()才是核心的方法,继续进入这个方法看:

refresh()->obtainFreshBeanFactory()->refreshBeanFactory()

/**
	 * This implementation performs an actual refresh of this context's underlying
	 * bean factory, shutting down the previous bean factory (if any) and
	 * initializing a fresh bean factory for the next phase of the context's lifecycle.
	 */
	@Override
	protected final void refreshBeanFactory() throws BeansException {
        //判断当前环境的beanFactory是否为空(当前applicaContext是否加载了beanFactory)
        //如果存在beanFactory对象,就先销毁所有的bean,再关闭beanFactory
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
            /*
            这里为什么要使用DefaultListableBeanFactory呢?
            我们可以看一下下面的图就知道了DefaultListableBeanFactory作为最下面的子类,
            具有以上所有父类和实现的接口的功能
            (在DefaultListableBeanFactory.java里按Ctrl+Alt+shift+U弹出该视图)*/
			DefaultListableBeanFactory beanFactory = createBeanFactory();
            //设置beanFactory的序列号
			beanFactory.setSerializationId(getId());
            /*
            这个方法自定义beanFactory的功能,
            设置allowBeanDefinitionOverriding和allowCircularReferences
            即允许bean被覆盖和允许循环引用
            循环引用这一块在容器的基本实现这一节中不展开探究,以后会另外开一篇来探究他*/
			customizeBeanFactory(beanFactory);
            /*
            从方法名字上我们就可以大概看出该方法的大概功能:加载beanDefinition。
            beanDefinition就是存储 加载、注册的bean的信息的。
            所以在代码层面上,我们可以简单认为,bean就是beanDefinition的实例。
            这个方法把各个加载完成的beanDefinition放入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);
		}
	}

在这里插入图片描述

关于bean的覆盖问题和循环引用问题,这里简单的说明一下:

bean的覆盖指的是当allowBeanDefinitionOverriding=true的时候,beanDefinitionMap中的key是否有相同的。如果有,那么后面的beanDefinition会把前面的给覆盖掉。当allowBeanDefinitionOverriding=false的时候,不会覆盖,会直接报错。

bean的循环依赖是指A依赖B,B依赖C,C又依赖A这种情况。在单例情况下,Spring是默认允许循环依赖的。

关于BeanDefinition,他保存了bean实际指向的类、是否是单例、依赖了其他哪些bean等信息,底层 就是通过反射从这个beanDefinition里实例化bean的,我们具体看一看这个接口具体包含了哪一些属性:

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

	
	String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
	
	String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
	
	int ROLE_APPLICATION = 0;

	int ROLE_SUPPORT = 1;

	int ROLE_INFRASTRUCTURE = 2;

	void setParentName(@Nullable String parentName);

	@Nullable
	String getParentName();

	void setBeanClassName(@Nullable String beanClassName);
	
	@Nullable
	String getBeanClassName();

	void setScope(@Nullable String scope);

	@Nullable
	String getScope();

	void setLazyInit(boolean lazyInit);

	boolean isLazyInit();

	void setDependsOn(@Nullable String... dependsOn);

	@Nullable
	String[] getDependsOn();

	void setAutowireCandidate(boolean autowireCandidate);

	boolean isAutowireCandidate();

	void setPrimary(boolean primary);

	boolean isPrimary();

	void setFactoryBeanName(@Nullable String factoryBeanName);

	@Nullable
	String getFactoryBeanName();

	void setFactoryMethodName(@Nullable String factoryMethodName);

	@Nullable
	String getFactoryMethodName();

	ConstructorArgumentValues getConstructorArgumentValues();

	default boolean hasConstructorArgumentValues() {
		return !getConstructorArgumentValues().isEmpty();
	}
 
	MutablePropertyValues getPropertyValues();

	default boolean hasPropertyValues() {
		return !getPropertyValues().isEmpty();
	}
	
	void setInitMethodName(@Nullable String initMethodName);
	
	@Nullable
	String getInitMethodName();

	void setDestroyMethodName(@Nullable String destroyMethodName);
	
	@Nullable
	String getDestroyMethodName();

	void setRole(int role);
	
	int getRole();

	void setDescription(@Nullable String description);
	
	@Nullable
	String getDescription();
	
	ResolvableType getResolvableType();

	boolean isSingleton();

	boolean isPrototype();
	
	boolean isAbstract();

	@Nullable
	String getResourceDescription();
	
	@Nullable
	BeanDefinition getOriginatingBeanDefinition();

}

现在来看看这个极为重要的loadBeanDefinitions方法:

refresh()->obtainFreshBeanFactory()->refreshBeanFactory()->loadBeanDefinitions(beanFactory)

	@Override
	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
		// Create a new XmlBeanDefinitionReader for the given BeanFactory.
     //beanDefinitionReader加载配置文件中的配置并解析
		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);
	}

refresh()->obtainFreshBeanFactory()->refreshBeanFactory()->loadBeanDefinitions(beanFactory)->loadBeanDefinitions(beanDefinitionReader)

	protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
		Resource[] configResources = getConfigResources();
		if (configResources != null) {
   //1
			reader.loadBeanDefinitions(configResources);
		}
		String[] configLocations = getConfigLocations();
		if (configLocations != null) {
   
   //2
			reader.loadBeanDefinitions(configLocations);
		}
	}

上面的分支最终都会进入loadBeanDefinitions(Resource… resource)这个方法,注意的是有许多重载的loadBeanDefinitions方法

@Override
	public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
		Assert.notNull(resources, "Resource array must not be null");
		int count = 0;
//一个resource代表了一个资源文件,遍历解析每一个资源文件
		for (Resource resource : resources) {
   //在这里进行了解析
			count += loadBeanDefinitions(resource);
		}
//返回的是加载的beanDefinition的数量
		return count;
	}

方法loadBeanDefinitions(Resource resource):

@Override
	public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
//又转到了 loadBeanDefinitions(EncodedResource encodedResource)方法
		return loadBeanDefinitions(new EncodedResource(resource));
	}

方法 loadBeanDefinitions(EncodedResource encodedResource):

public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
		Assert.notNull(encodedResource, "EncodedResource must not be null");
		if (logger.isTraceEnabled()) {
			logger.trace("Loading XML bean definitions from " + encodedResource);
		}
//resourcesCurrentlyBeingLoaded是一个threadLocal对象,这个set集合保存了当前环境下正在加载的resource
		Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
		if (currentResources == null) {
			currentResources = new HashSet<>(4);
			this.resourcesCurrentlyBeingLoaded.set(currentResources);
		}
//如果这个set集合里面已经有了该资源,说明已经加载过该资源,就会报错
		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());
				}
       //最后是通过doLoadBeanDefinitions方法来解析这个xml配置文件
				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();
			}
		}
	}

方法doLoadBeanDefinitions(InputSource inputSource, Resource resource):

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
			throws BeanDefinitionStoreException {

		try {
    //先解析为document
			Document doc = doLoadDocument(inputSource, resource);
    //继续看这个方法,会把document进行进一步解析 ,count是本次注册的bean的数量     
			int count = registerBeanDefinitions(doc, resource);
			return count;
		}
		catch (Exception ex) {
			throw ex;
		}
		
	}

方法registerBeanDefinitions(Document doc, Resource resource):

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
//这里getBeanDefinitionCount()是在DefaultListBeanFactory.java下面的,实际上返回的就是beanDefinitionMap的size,countBefore就是现有的beanDefinition的数量
		int countBefore = getRegistry().getBeanDefinitionCount();
//需要关注这里,进行解析
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
 //被注册的总数-之前的数量 = 本次注册了的数量
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}

方法registerBeanDefinitions(Document doc, XmlReaderContext readerContext):

public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
		this.readerContext = readerContext;
//doc.getDocumentElement()得到的是element对象
		doRegisterBeanDefinitions(doc.getDocumentElement());
	}

in DefaultBeanDefinitionDocumentReader.java

方法doRegisterBeanDefinitions(Element root):

protected void doRegisterBeanDefinitions(Element root) {
 //涉及到递归,因为解析的beans标签中可能还会有beans标签,往下看就知道了
		BeanDefinitionParserDelegate parent = this.delegate;
		this.delegate = createDelegate(getReaderContext(), root, parent);
		if (this.delegate.isDefaultNamespace(root)) {
         /*
         这里是适配环境配置的profile
         在springboot项目里面,我们可以以application-[profile].yml形式配置,例如:
         application-dev.yml、application-prod.yml等
         通过spring.profiles.active 选择项目加载的配置文件
         例如:当配置spring.profiles.active: dev时,项目会按照application-dev.yml的配置来启动了。
         单纯的spring项目中,我们以<beans profile="dev"></beans>这种方式配置profile
         然后在启动项目的时候指定就ok了:
         -Dspring.profiles.active="dev"
         */
			String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
			if (StringUtils.hasText(profileSpec)) {
				String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
						profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
				// We cannot use Profiles.of(...) since profile expressions are not supported
				// in XML config. See SPR-12458 for details.
				if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
					if (logger.isDebugEnabled()) {
						logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec +
								"] not matching: " + getReaderContext().getResource());
					}
					return;
				}
			}
		}
 //这个方法是一个空方法,可能是提供给子类扩展的,用户有需要扩展功能的地方应该就在这里和下面进行扩展。当然,这里是解析前,下面是解析后。
		preProcessXml(root);
 //进行解析
		parseBeanDefinitions(root, this.delegate);
		postProcessXml(root);

		this.delegate = parent;
	}

方法parseBeanDefinitions(Element root, BeanDefinitionParserDelegate 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;
                 /*如果是默认的命名空间里的默认节点:
                 <beans />, <bean />, <import /> ,<alias />
                 */
					if (delegate.isDefaultNamespace(ele)) {
                     //解析默认的标签
						parseDefaultElement(ele, delegate);
					}
                 //其他标签 例如<double /> ,<mvc />等
					else {
						delegate.parseCustomElement(ele);
					}
				}
			}
		}
		else {
			delegate.parseCustomElement(root);
		}
	}

方法parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate)

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
 //解析默认标签
		if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
			importBeanDefinitionResource(ele);
		}
		else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
			processAliasRegistration(ele);
		}
		else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
			processBeanDefinition(ele, delegate);
		}
 /*
 因为配置文件里beans标签中还能包含beans标签,所以这里会递归,这也就是为什么doRegisterBeanDefinitions中会有parent
 */
		else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
			// recurse
			doRegisterBeanDefinitions(ele);
		}
	}

我们这里解析的默认标签,所以看processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate)这个方法:

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
   //这里实际上是个空壳方法,实际上调用的是parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) 这个方法解析的。
 //先看下面的方法,看到bdHolder怎么创建出来的了再接着这里往下看
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
       //这里是处理自定义的nameSpace的。
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
         //到这里为止,我们已经完成了一个beanDefinition的创建了。
         //obtainFreshBeanFactory()这个方法完成的就是beanDefinition的创建和注册,那么这个方法的功能到现在为止完成了一半了。
         //接下来就是要完成beanDefinition的注册了
			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));
		}
	}

在这里插入图片描述

可以关注一下这个BeanDefinitionHolder的结构,实际上就是一个beanDefinition对象和一个aliases的数组和一个beanName的字符串。

方法parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean)

这个时候ele包含了这么多信息

在这里插入图片描述

结合这个图片上内容来看代码

@Nullable
	public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
     //获取ele里面的id、name的值
		String id = ele.getAttribute(ID_ATTRIBUTE);
		String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

		List<String> aliases = new ArrayList<>();
     //当配置的bean的name属性不为空的时候,通过分隔符分割为数组
     //MULTI_VALUE_ATTRIBUTE_DELIMITERS = ",; " 即逗号分号空格
		if (StringUtils.hasLength(nameAttr)) {
			String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
			aliases.addAll(Arrays.asList(nameArr));
		}

		String beanName = id;
     //当bean没有配置id属性,就是用配置的第一个name的值作为beanName
		if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
			beanName = aliases.remove(0);
			if (logger.isTraceEnabled()) {
				logger.trace("No XML 'id' specified - using '" + beanName +
						"' as bean name and " + aliases + " as aliases");
			}
		}
     //校验beanName是否唯一
		if (containingBean == null) {
			checkNameUniqueness(beanName, aliases, ele);
		}
//到这步,可以看到就已经得到了beanDefinition对象了,我们直接往下看这个方法,再回来看接下来的代码
		AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
		if (beanDefinition != null) {
         //当这个beanDefinition对象存在,但beanName没有值,即id和name没有配置的时候,这段代码会设置一个beanName,类似这种形式:
         //"com.jerry.springSource.pojo.Student#0"
			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.isTraceEnabled()) {
						logger.trace("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);
         //这里返回了一个BeanDefinitionHolder,再往上一个方法看
			return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
		}

		return null;
	}

看下最终生成beanDefinition的这个parseBeanDefinitionElement(
Element ele, String beanName, @Nullable BeanDefinition containingBean)方法

	@Nullable
	public AbstractBeanDefinition parseBeanDefinitionElement(
			Element ele, String beanName, @Nullable BeanDefinition containingBean) {

		this.parseState.push(new BeanEntry(beanName));

		String className = null;
		if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
         //这里获取到的是全路径类名,在我的例子中,获取到的是
         //com.jerry.springSource.pojo.Student
			className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
		}
		String parent = null;
		if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
			parent = ele.getAttribute(PARENT_ATTRIBUTE);
		}

		try {
         //创建一个GenericBeanDefinition对象
			AbstractBeanDefinition bd = createBeanDefinition(className, parent);

         //设置了很多GenericBeanDefinition中的属性,ctrl+左键点击set方法,发现这些属性都定义在AbstractBeanDefinition这里面
			parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
			bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));

         //这些parse开头的方法,都是解析bean里面的标签的,从上往下分别是解析
         //meta、lookup-method、replace-method、constructor-arg、property和qualifier 
			parseMetaElements(ele, bd);
			parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
			parseReplacedMethodSubElements(ele, bd.getMethodOverrides());

			parseConstructorArgElements(ele, bd);
			parsePropertyElements(ele, bd);
			parseQualifierElements(ele, bd);

			bd.setResource(this.readerContext.getResource());
			bd.setSource(extractSource(ele));
			//返回该beanDefinition对象,看到这里就看上一层方法
			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;
	}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值