spring基于xml方式加载spring(一)

基于xml方式加载spring(一)

启动spring上下文到解析spring.xml

启动spring上下文方法

 ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");

在这里插入图片描述

//ClassPathXmlApplicationContext 的构造方法,调用多个参数的构造方法
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
		this(new String[] {configLocation}, true, null);
	}
	//其中refresh()是主要的
public ClassPathXmlApplicationContext(
			String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
			throws BeansException {

		super(parent);
		setConfigLocations(configLocations);
		if (refresh) {
			refresh();
		}
	}
     /*1、创建BeanFactory对象
			* 2、xml解析
			* 	传统标签解析:bean、import等
			* 	自定义标签解析 如:<context:component-scan base-package="com.xiangxue.jack"/>
			* 	自定义标签解析流程:
			* 		a、根据当前解析标签的头信息找到对应的namespaceUri
			* 		b、加载spring所有jar中的spring.handlers文件。并建立映射关系
			* 		c、根据namespaceUri从映射关系中找到对应的实现了NamespaceHandler接口的类
			* 		d、调用类的init方法,init方法是注册了各种自定义标签的解析类
			* 		e、根据namespaceUri找到对应的解析类,然后调用paser方法完成标签解析
			*
			* 3、把解析出来的xml标签封装成BeanDefinition对象
			* */
		AbstractApplicationContext 类
		@Override
	public void refresh() throws BeansException, IllegalStateException {}

创建beanfactory

	ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
	/**
*在这里用到了模板方法,子类实现父类的抽象方法, refreshBeanFactory()的实现方法 是AbstractRefreshableApplicationContext中的refreshBeanFactory();
*/
		protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		refreshBeanFactory();
		return getBeanFactory();
	}

refreshBeanFactory()

	@Override
	protected final void refreshBeanFactory() throws BeansException {
		//如果BeanFactory不为空,则清除BeanFactory和里面的实例
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
			//BeanFactory 实例工厂
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			beanFactory.setSerializationId(getId());
			//设置是否可以循环依赖 allowCircularReferences
			//是否允许使用相同名称重新注册不同的bean实现.
			customizeBeanFactory(beanFactory);
			//解析xml,并把xml中的标签封装成BeanDefinition对象
			loadBeanDefinitions(beanFactory);
			this.beanFactory = beanFactory;
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}

//是否允许使用相同名称重新注册不同的bean实现.
customizeBeanFactory(beanFactory);
可以通过一个类继承BeanDefinitionRegistryPostProcessor类,来控制是否注入.

public class BeanPro implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {

    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        //需要强转
        DefaultListableBeanFactory  configurableListableBeanFactory1 = (DefaultListableBeanFactory)configurableListableBeanFactory;
        configurableListableBeanFactory1.setAllowBeanDefinitionOverriding(true);
        configurableListableBeanFactory1.setAllowCircularReferences(true);
    }
}

loadBeanDefinitions(beanFactory);解析配置文件sax解析xml文件方式解析spring.xml;
首先loadBeanDefinitions(beanFactory);获得beanDefinitionReader
然后loadBeanDefinitions(beanDefinitionReader);获得配置文件,配置文件是从ClassPathXmlApplicationContext(“spring.xml”)或者ClassPathXmlApplicationContext(new String[] {“bean1.xml”,“bean2.xml”});的spring.xml,从resource目录去找
接着reader.loadBeanDefinitions(configLocations);传入的configLocations可以是多个,通过for循环挨个解析this.loadBeanDefinitions(location),
this.loadBeanDefinitions(location, (Set)null);
this.loadBeanDefinitions(resources)
this.loadBeanDefinitions((Resource)resource)
XmlBeanDefinitionReader
this.loadBeanDefinitions(new EncodedResource(resource));
this.doLoadBeanDefinitions(inputSource, encodedResource.getResource());读取xml文件,包装成bd
this.doLoadDocument(inputSource, resource)读取xml文件
this.registerBeanDefinitions(doc, resource);中这个方法documentReader.registerBeanDefinitions(doc, this.createReaderContext(resource));
this.doRegisterBeanDefinitions(doc.getDocumentElement());
this.parseBeanDefinitions(root, this.delegate);包装成BeanDefinition

@Override
	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
		// Create a new XmlBeanDefinitionReader for the given BeanFactory.
		//创建xml的解析器,这里是一个委托模式
		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

		// Configure the bean definition reader with this context's
		// resource loading environment.
		beanDefinitionReader.setEnvironment(this.getEnvironment());
		//这里传一个this进去,因为ApplicationContext是实现了ResourceLoader接口的
		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);
	}
		加载sping,xml并解析
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
		Resource[] configResources = getConfigResources();
		if (configResources != null) {
			reader.loadBeanDefinitions(configResources);
		}
		//获取需要加载的xml配置文件
		String[] configLocations = getConfigLocations();
		if (configLocations != null) {
			reader.loadBeanDefinitions(configLocations);
		}
	}

loadBeanDefinitions

 public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
        return this.loadBeanDefinitions(location, (Set)null);
    }

    public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
        ResourceLoader resourceLoader = this.getResourceLoader();
        if (resourceLoader == null) {
            throw new BeanDefinitionStoreException("Cannot load bean definitions from location [" + location + "]: no ResourceLoader available");
        } else {
            int count;
            if (resourceLoader instanceof ResourcePatternResolver) {
                try {
                    Resource[] resources = ((ResourcePatternResolver)resourceLoader).getResources(location);
                    count = this.loadBeanDefinitions(resources);
                    if (actualResources != null) {
                        Collections.addAll(actualResources, resources);
                    }

                    if (this.logger.isTraceEnabled()) {
                        this.logger.trace("Loaded " + count + " bean definitions from location pattern [" + location + "]");
                    }

                    return count;
                } catch (IOException var6) {
                    throw new BeanDefinitionStoreException("Could not resolve bean definition resource pattern [" + location + "]", var6);
                }
            } else {
                Resource resource = resourceLoader.getResource(location);
                count = this.loadBeanDefinitions((Resource)resource);
                if (actualResources != null) {
                    actualResources.add(resource);
                }

                if (this.logger.isTraceEnabled()) {
                    this.logger.trace("Loaded " + count + " bean definitions from location [" + location + "]");
                }

                return count;
            }
        }
    }

count = this.loadBeanDefinitions((Resource)resource);

 public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
        return this.loadBeanDefinitions(new EncodedResource(resource));
    }

    public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
        Assert.notNull(encodedResource, "EncodedResource must not be null");
        if (this.logger.isTraceEnabled()) {
            this.logger.trace("Loading XML bean definitions from " + encodedResource);
        }

        Set<EncodedResource> currentResources = (Set)this.resourcesCurrentlyBeingLoaded.get();
        if (!currentResources.add(encodedResource)) {
            throw new BeanDefinitionStoreException("Detected cyclic loading of " + encodedResource + " - check your import definitions!");
        } else {
            int var6;
            try {
                InputStream inputStream = encodedResource.getResource().getInputStream();
                Throwable var4 = null;

                try {
                    InputSource inputSource = new InputSource(inputStream);
                    if (encodedResource.getEncoding() != null) {
                        inputSource.setEncoding(encodedResource.getEncoding());
                    }

                    var6 = this.doLoadBeanDefinitions(inputSource, encodedResource.getResource());
                } catch (Throwable var24) {
                    var4 = var24;
                    throw var24;
                } finally {
                    if (inputStream != null) {
                        if (var4 != null) {
                            try {
                                inputStream.close();
                            } catch (Throwable var23) {
                                var4.addSuppressed(var23);
                            }
                        } else {
                            inputStream.close();
                        }
                    }

                }
            } catch (IOException var26) {
                throw new BeanDefinitionStoreException("IOException parsing XML document from " + encodedResource.getResource(), var26);
            } finally {
                currentResources.remove(encodedResource);
                if (currentResources.isEmpty()) {
                    this.resourcesCurrentlyBeingLoaded.remove();
                }

            }

            return var6;
        }
    }

this.doLoadBeanDefinitions(inputSource, encodedResource.getResource());

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
        BeanDefinitionDocumentReader documentReader = this.createBeanDefinitionDocumentReader();
        int countBefore = this.getRegistry().getBeanDefinitionCount();
        documentReader.registerBeanDefinitions(doc, this.createReaderContext(resource));
        return this.getRegistry().getBeanDefinitionCount() - countBefore;
    }

registerBeanDefinitions

 public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
        this.readerContext = readerContext;
        this.doRegisterBeanDefinitions(doc.getDocumentElement());
    }

doRegisterBeanDefinitions

protected void doRegisterBeanDefinitions(Element root) {
        BeanDefinitionParserDelegate parent = this.delegate;
        this.delegate = this.createDelegate(this.getReaderContext(), root, parent);
        if (this.delegate.isDefaultNamespace(root)) {
            String profileSpec = root.getAttribute("profile");
            if (StringUtils.hasText(profileSpec)) {
                String[] specifiedProfiles = StringUtils.tokenizeToStringArray(profileSpec, ",; ");
                if (!this.getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
                    if (this.logger.isDebugEnabled()) {
                        this.logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec + "] not matching: " + this.getReaderContext().getResource());
                    }

                    return;
                }
            }
        }

        this.preProcessXml(root);
        this.parseBeanDefinitions(root, this.delegate);
        this.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) {
                    Element ele = (Element)node;
                    if (delegate.isDefaultNamespace(ele)) {
                        this.parseDefaultElement(ele, delegate);
                    } else {
                        delegate.parseCustomElement(ele);
                    }
                }
            }
        } else {
            delegate.parseCustomElement(root);
        }

    }

parseDefaultElement默认标签解析
parseCustomElement自定义标签解析

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值