obtainFreshBeanFactory()

文章详细描述了如何在Spring框架中获取和配置BeanFactory,包括创建新的beanFactory,定制配置,加载bean定义以及处理默认元素和循环引用。重点关注了`refreshBeanFactory`和`loadBeanDefinitions`方法的工作原理。
摘要由CSDN通过智能技术生成

去获取bean工厂

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

// 调用子类去刷新bean工厂
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    refreshBeanFactory();
    return getBeanFactory();
}

refreshBeanFactory

首先去调用AbstractRefreshableApplicationContext下边的方法refreshBeanFactory(),次方法是一个抽象类的方法,来看下实现。

    @Override
	protected final void refreshBeanFactory() throws BeansException {
		// beanFactory是不是存在
        if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
            // 创建beanFactory
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			beanFactory.setSerializationId(getId());
            // 配置beanFactory
			customizeBeanFactory(beanFactory);
            // 将bean的定义加载到context中
			loadBeanDefinitions(beanFactory);
			this.beanFactory = beanFactory;
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source             
            for " + getDisplayName(), ex);
		}
    }

首先判断beanFactory是不是存在,存在就销毁掉。下一步去创建beanFactory.

1、createBeanFactory() 创建beanFactory

    protected DefaultListableBeanFactory createBeanFactory() {
        // 使用的是 DefaultListableBeanFactory,
        // 初始化参数parent为null,不用管参数。
		return new DefaultListableBeanFactory(getInternalParentBeanFactory());
	}

2、customizeBeanFactory(beanFactory) 配置beanFactory

customizeBeanFactory为AbstractRefreshableApplicationContext下边的一个方法,为上下文的context配置beanFactory参数。

    protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
		if (this.allowBeanDefinitionOverriding != null) {     
          beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
		}
		if (this.allowCircularReferences != null) {
		  beanFactory.setAllowCircularReferences(this.allowCircularReferences);
		}
	}

该方法是交于context子类去实现的,如果子类的context实现了allowBeanDefinitionOverriding和allowCircularReferences参数,则设置给beanFactory。

3、loadBeanDefinitions(beanFactory)

loadBeanDefinitions方法为AbstractRefreshableApplicationContext下边的一个方法。目的是将bean的定义加载到context中。

以其中一个实现AbstractXmlApplicationContext为例。

    protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws     
       BeansException, IOException {
		// 通过指定的beanFactory新建一个bean的定义类
		XmlBeanDefinitionReader beanDefinitionReader = new 
        XmlBeanDefinitionReader(beanFactory);

		// 使用一下配置,配置bean定义的reader
		// 资源加载环境
		beanDefinitionReader.setEnvironment(getEnvironment());
		beanDefinitionReader.setResourceLoader(this);
		beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

        // 允许子类提供的reader进行初始化
        // 然后继续加载实际上的bean定义
		initBeanDefinitionReader(beanDefinitionReader);
		loadBeanDefinitions(beanDefinitionReader);
	}
loadbeanDefinitions(beanDefinitionReader)

重点看一下loadbeanDefinitions方法,进去方法看一下。

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

其中究竟是走getConfigResources或者是使用getConfigLocations,根据最开始初始化时进行判断,以目前走的线路来看。

public ClassPathXmlApplicationContext(
			String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
			throws BeansException {

		super(parent);
		setConfigLocations(configLocations);
		if (refresh) {
			refresh();
		}
	}

初始化配置,设置的是configLocations,所以loadbeanDefinitions的方法走了getConfigLocations。

(setConfigLocations(configLocations)方法对AbstractRefreshableConfigApplicationContext类的configLocations初始化,后面调用getConfigLocations的时候,方法体中的configLocations的参数就是初始化类中初始化的configLocations)

    protected String[] getConfigLocations() {
        // this.configLocations 就是setConfigLocations(configLocations);
        // 中的configLocations
		return (this.configLocations != null ? this.configLocations : 
          getDefaultConfigLocations());
	}

接下来看reader.loadBeanDefinitions这行代码。通过一个循环加载location

public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
		Assert.notNull(locations, "Location array must not be null");
		int count = 0;
		for (String location : locations) {
			count += loadBeanDefinitions(location);
		}
		return count;
	}

loadBeanDefinitions一直点进去

    public int loadBeanDefinitions(String location, @Nullable Set<Resource>     
          actualResources)     
    throws BeanDefinitionStoreException {

         // ResourceLoader 是在loadBeanDefinitions方法中 
         // beanDefinitionReader.setResourceLoader(this);进行的配置。this就是 
         // ClassPathXmlApplicationContext 
		ResourceLoader resourceLoader = getResourceLoader();
		if (resourceLoader == null) {
			throw new BeanDefinitionStoreException(
					"Cannot load bean definitions from location [" + location + "]: no ResourceLoader available");
		}

		if (resourceLoader instanceof ResourcePatternResolver resourcePatternResolver) {
			// Resource pattern matching available.
			try {
                // 获取resource
				Resource[] resources = resourcePatternResolver.getResources(location);
				// 解析资源,分析如下。
                int count = loadBeanDefinitions(resources);
				if (actualResources != null) {
					Collections.addAll(actualResources, resources);
				}
				if (logger.isTraceEnabled()) {
					logger.trace("Loaded " + count + " bean definitions from location pattern [" + location + "]");
				}
				return count;
			}
			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 count = loadBeanDefinitions(resource);
			if (actualResources != null) {
				actualResources.add(resource);
			}
			if (logger.isTraceEnabled()) {
				logger.trace("Loaded " + count + " bean definitions from location [" + location + "]");
			}
			return count;
		}
	}

进入方法片段,getResourceLoader中的resource是ClassPathXmlApplicationContext 在(beanDefinitionReader.setResourceLoader(this))这行代码已给出。ClassPathXmlApplicationContext中最终继承了ResourcePatternResolver,所以没有走else,再获取到Resource[]的数组后,开始进行解析。调用loadBeanDefinitions()方法,dubug会发现,最终会走到XmlBeanDefinitionReader的loadBeanDefinitions(Resource resource)方法,然后会先制作Document对象,再调用registerBeanDefinitions方法

    public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
        // 创建对象,不用去看
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		// getRegistry就是beanFactory
        int countBefore = getRegistry().getBeanDefinitionCount();
        // 进行注册beanDefinitions
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}

进入documentReader.registerBeanDefinitions进去看一下具体是怎么进行注册到beanDefinitionsMap的。

protected void doRegisterBeanDefinitions(Element root) {
		// 进行节点的解析
		BeanDefinitionParserDelegate parent = this.delegate;
		this.delegate = createDelegate(getReaderContext(), root, parent);

		if (this.delegate.isDefaultNamespace(root)) {
			String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
			if (StringUtils.hasText(profileSpec)) {
				String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
						profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
		
		
				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中进行。

    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 ele) {
					if (delegate.isDefaultNamespace(ele)) {
                        // 进行解析
						parseDefaultElement(ele, delegate);
					}
					else {
						delegate.parseCustomElement(ele);
					}
				}
			}
		}
		else {
			delegate.parseCustomElement(root);
		}
	}

首先会判断是否是默认空间。如果不是默认空间会去解析其他空间。咱们走默认空间。走到parseDefaultElement方法进行解析。那么哪些是默认空间呢-(Import、bean、alias)

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);
		}
		else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
			// recurse
			doRegisterBeanDefinitions(ele);
		}
	}

我得xml为bean,则进入到processBeanDefinition方法。

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); // 封装了beanDefinition
		if (bdHolder != null) {
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				// 注册最终的实例
				BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error("Failed to register bean definition with name '" +
						bdHolder.getBeanName() + "'", ele, ex);
			}
			// 发送注册事件
			getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
		}
	}

BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());的方法进行注册。

最终会看到一个this.beanDefinitionMap.put(beanName, beanDefinition);的操作,至此,beanDefinitions添加到了beanDefinitionMap中。

最终返回一个包含beanDefinitionMap的beanFactory

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值