从小白的角度看Spring核心流程概览(XML版)- 容器初始化第三章-创建BeanFactory

Java框架

浏览数:55

2020-6-1

本章我们来看看Spring的BeanFactory是如何被创建的

1、方法概览

入口:AbstractApplicationContext类refresh方法264行:
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();

	protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		// 真正刷新BeanFactory的方法
        this.refreshBeanFactory();
		// 返回BeanFactory
        return this.getBeanFactory();
    }

2.1、刷新BeanFactory

	//真正调用的是AbstractRefreshableApplicationContext的refreshBeanFactory方法
	protected final void refreshBeanFactory() throws BeansException {
		//判断是否已经存在BeanFactory,如果存在就销毁and关闭
        if(this.hasBeanFactory()) {
            this.destroyBeans();
            this.closeBeanFactory();
        }
        try {
			// 真正创建BeanFactory的方法
            DefaultListableBeanFactory beanFactory = this.createBeanFactory();
			// 给BeanFactory设置一个id,怎么设置的自己看~
            beanFactory.setSerializationId(this.getId());
			// 定制BeanFactory
            this.customizeBeanFactory(beanFactory);
			// 加载Bean的Definition解析器
            this.loadBeanDefinitions(beanFactory);
			// 下面就是将创建出来的BeanFactory保存起来
            Object var2 = this.beanFactoryMonitor;
            synchronized(this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        } catch (IOException var5) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var5);
        }
    }

2.1.1、创建BeanFactory

	//AbstractRefreshableApplicationContext第103行
	protected DefaultListableBeanFactory createBeanFactory() {
		//创建并返回一个DefaultListableBeanFactory工厂,其中参数是他的父工厂
        return new DefaultListableBeanFactory(this.getInternalParentBeanFactory());
    }
	//AbstractApplicationContext第725行,这里注意AbstractApplicationContext是AbstractRefreshableApplicationContext的父类,而这段逻辑对于所有上下文都管用,所以卸载这(后面这句话是我瞎猜的~)
	protected BeanFactory getInternalParentBeanFactory() {
		// 判断当前上下文是否有父上下文,如果有就返回回去。当然这里是没有的,在Spring-MVC里面的话就会有了~这样看来工厂之间也有链路关系额。以前都不知道
        return (BeanFactory)(this.getParent() instanceof ConfigurableApplicationContext?((ConfigurableApplicationContext)this.getParent()).getBeanFactory():this.getParent());
    }

2.1.2、定制BeanFactory

	//AbstractRefreshableApplicationContext第725行
	protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
		//如果 允许bean定义重写 有值,则设置对于的值,这里默认没有,不过你要是使用事务的话,就会有了。
        if(this.allowBeanDefinitionOverriding != null) {
            beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding.booleanValue());
        }
		//如果 允许循环引用 有值,则设置对于的值,这里默认也没有。
        if(this.allowCircularReferences != null) {
            beanFactory.setAllowCircularReferences(this.allowCircularReferences.booleanValue());
        }

    }

2.1.3、加载DeFinition解析器

	//这里实际调用的是AbstractXmlApplicationContext的方法,如果你是Annotation版的,那么走的就是Annotation版的了,到时候再说- -
	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
		//创建一个XmlBeanDefinition的解析器
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
		// 设置系统属性
        beanDefinitionReader.setEnvironment(this.getEnvironment());
		// 设置资源加载器
        beanDefinitionReader.setResourceLoader(this);
		// 设置实体解析器
        beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
		// 初始化BeanDefinitionReader解析器
        this.initBeanDefinitionReader(beanDefinitionReader);
		// 加载BeanDefinitions
		// 大内容,单独分析
        this.loadBeanDefinitions(beanDefinitionReader);
    }

2.2、返回BeanFactory

	//真正调用的是AbstractRefreshableApplicationContext的getBeanFactory方法
	//就是将上一步创建的BeanFactory返回回去。
	public final ConfigurableListableBeanFactory getBeanFactory() {
        Object var1 = this.beanFactoryMonitor;
        synchronized(this.beanFactoryMonitor) {
            if(this.beanFactory == null) {
                throw new IllegalStateException("BeanFactory not initialized or already closed - call 'refresh' before accessing beans via the ApplicationContext");
            } else {
                return this.beanFactory;
            }
        }
    }

总结

截至到现在,除了加载BeanDefinitions没有讲以外(其实是我自己也还没开始看….),BeanFactory的创建过程已经完全结束。 首先spring会设置一堆乱七八糟的东西,然后定位在XML文件的位置,并且保存起来。这就是整个流程的第一步,资源定位。马上我们就要开始第二步,资源的加载了~下期见~

作者:葩_