spring(四):IoC初始化流程&BeanDefinition加载注册

ApplicationContext context = new ClassPathXmlApplicationContext("hello.xml");
    /**
     * 
     * @param configLocations Spring的xml配置文件
     * @param refresh 是否需要刷新,决定了是否进行bean解析、注册及实例化
     * @param parent 父ApplicationContext
     * @throws BeansException
     */
	public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException {
    	super(parent);
        // 设置框架要加载的资源文件的位置<<AbstractRefreshableConfigApplicationContext>>
    	this.setConfigLocations(configLocations);
    	if (refresh) {
            // ★
        	this.refresh();	// <AbstractApplicationContext>
    	}
	}
	public void refresh() throws BeansException, IllegalStateException {
        synchronized(this.startupShutdownMonitor) {
            // 容器预先准备,记录容器启动时间和标记
            this.prepareRefresh();
            // 创建bean工厂,里面实现了BeanDefinition的装载★
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
            // 配置bean工厂的上下文信息,如类装载器等
            this.prepareBeanFactory(beanFactory);

            try {
                // 在BeanDefinition被装载后,提供一个修改BeanFactory的入口
                postProcessBeanFactory(beanFactory);
                this.postProcessBeanFactory(beanFactory);
                // 在bean初始化之前,提供对BeanDefinition修改入口
                // PropertyPlaceholderConfigurer在这里被调用
                this.invokeBeanFactoryPostProcessors(beanFactory);
                // 注册BeanPostProcessors,用于在bean被初始化时进行拦截,进行额外初始化操作
                this.registerBeanPostProcessors(beanFactory);
                // 初始化MessageSource
                this.initMessageSource();
                // 初始化上下文事件广播
                this.initApplicationEventMulticaster();
                // 这是一个模板方法
                this.onRefresh();
                // 注册监听器
                this.registerListeners();
                this.finishBeanFactoryInitialization(beanFactory);
                this.finishRefresh();
            } catch (BeansException var9) {
                ...
            } finally {
                this.resetCommonCaches();
            }

        }
    }

    protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        // 如果存在BeanFactory则销毁并关闭
        // 然后新建一个DefaultListableBeanFactory
        // 然后进行BeanFactory的属性设置,设置是否允许重写BeanDefinition、是否允许循环引用
        // 接着载入BeanDefinition<根据用途不同有多个实现子类>
        this.refreshBeanFactory();	// <<AbstractRefreshableApplicationContext>>
        return this.getBeanFactory();
    }
// 例:具体实现子类AbstractXmlApplicationContext
    protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
        beanDefinitionReader.setEnvironment(this.getEnvironment());
        beanDefinitionReader.setResourceLoader(this);
        beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
        this.initBeanDefinitionReader(beanDefinitionReader);
        // ★
        this.loadBeanDefinitions(beanDefinitionReader);
    }

// AbstractBeanDefinitionReader
    public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
        // 取得ResourceLoader,这里是DefaultResourceLoader
        ResourceLoader resourceLoader = this.getResourceLoader();
        if (resourceLoader == null) {
            ...
        } else {
            int count;
            // 路径模式解析,得到指向Bean定义信息的资源集合
            if (resourceLoader instanceof ResourcePatternResolver) {
                try {
                    // DefaultResourceLoader的getResources完成具体定位
                    Resource[] resources = ((ResourcePatternResolver)resourceLoader).getResources(location);
                    count = this.loadBeanDefinitions(resources);
                    if (actualResources != null) {
                        Collections.addAll(actualResources, resources);
                    }

                    ...

                    return count;
                }...
            } else {
                // DefaultResourceLoader的getResources完成具体定位★
                ...
            }
        }
    }

---开始获取资源---

// DefaultResourceLoader
    public Resource getResource(String location) {
        Assert.notNull(location, "Location must not be null");
        Iterator var2 = this.protocolResolvers.iterator();

        Resource resource;
        do {
            if (!var2.hasNext()) {
                if (location.startsWith("/")) {
                    return this.getResourceByPath(location);
                }

                if (location.startsWith("classpath:")) {
                    return new ClassPathResource(location.substring("classpath:".length()), this.getClassLoader());
                }

                try {
                    URL url = new URL(location);
                    return (Resource)(ResourceUtils.isFileURL(url) ? new FileUrlResource(url) : new UrlResource(url));
                } catch (MalformedURLException var5) {
                    return this.getResourceByPath(location);
                }
            }

            ProtocolResolver protocolResolver = (ProtocolResolver)var2.next();
            resource = protocolResolver.resolve(location, this);
        } while(resource == null);

        return resource;
    }

---资源获取完毕---

// XmlBeanDefinitionReader
	protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {
        try {
            // 将xml配置文件转成Document,这里使用了SAX对XML的解析
            Document doc = this.doLoadDocument(inputSource, resource);
            // ★
            int count = this.registerBeanDefinitions(doc, resource);
        }
        ...
    }

    public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
        BeanDefinitionDocumentReader documentReader = this.createBeanDefinitionDocumentReader();    // 通过反射获取
        int countBefore = this.getRegistry().getBeanDefinitionCount();
        documentReader.registerBeanDefinitions(doc, this.createReaderContext(resource));    // <<BeanDefinitionDocumentReader>>接口方法
        return this.getRegistry().getBeanDefinitionCount() - countBefore;
    }

// 具体实现:DefaultBeanDefinitionDocumentReader
    protected void doRegisterBeanDefinitions(Element root) {
        // BeanDefinition的具体解析是由BeanDefinitionParserDelegate完成的
        BeanDefinitionParserDelegate parent = this.delegate;
        this.delegate = this.createDelegate(this.getReaderContext(), root, parent);
        ...

        this.preProcessXml(root);
        // ★
        this.parseBeanDefinitions(root, this.delegate);
        this.postProcessXml(root);
        this.delegate = parent;
    }

    protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
        if (delegate.isDefaultNamespace(root)) {
            NodeList nl = root.getChildNodes();
			// 对Document中元素、节点的不断解析。
            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)) {
                        // 一个是默认标签的解析,如Spring自己定义的标签★
                        this.parseDefaultElement(ele, delegate);
                    } else {
                        // 一个是对自定义标签的解析,如自定义的标签
                        delegate.parseCustomElement(ele);
                    }
                }
            }
        } else {
            delegate.parseCustomElement(root);
        }

    }

    private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
        if (delegate.nodeNameEquals(ele, "import")) {
            this.importBeanDefinitionResource(ele);
        } else if (delegate.nodeNameEquals(ele, "alias")) {
            this.processAliasRegistration(ele);
        } else if (delegate.nodeNameEquals(ele, "bean")) {
            
            // <DefaultListableBeanFactory> this.beanDefinitionMap.put(...);
            this.processBeanDefinition(ele, delegate);
        } else if (delegate.nodeNameEquals(ele, "beans")) {
            // 递归
            this.doRegisterBeanDefinitions(ele);
        }

    }

    protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
        // 这里是重点!!!BeanDefinition的具体解析是由BeanDefinitionParserDelegate完成的!!!★
        BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
        if (bdHolder != null) {
            bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);

            try {
                // <<BeanDefinitionRegistry>> registerBeanDefinition(String var1, BeanDefinition var2) throws BeanDefinitionStoreException;
                // 这里的BeanDefinition就是通过bdHolder获取的(definitionHolder.getBeanDefinition())
                // 而DefaultListableBeanFactory实现了BeanDefinitionRegistry接口
                BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());
            } catch (BeanDefinitionStoreException var5) {
                this.getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, var5);
            }

            this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
        }

    }

---开始解析,载入---

// BeanDefinitionParserDelegate
    @Nullable
    public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
        // 取得<bean>中id、name、aliases等属性值
        String id = ele.getAttribute("id");
        String nameAttr = ele.getAttribute("name");
        List<String> aliases = new ArrayList();
        if (StringUtils.hasLength(nameAttr)) {
            String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, ",; ");
            aliases.addAll(Arrays.asList(nameArr));
        }
        ...

        // 详细解析,比如构造函数、属性等
        AbstractBeanDefinition beanDefinition = this.parseBeanDefinitionElement(ele, beanName, containingBean);
        if (beanDefinition != null) {
            ...
            return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
        }...
    }

---结束载入---

---开始注册---
// DefaultListableBeanFactory
    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
        ...
        BeanDefinition existingDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);
        if (existingDefinition != null) {
            ...抛出异常

            this.beanDefinitionMap.put(beanName, beanDefinition);
        } else {
            if (this.hasBeanCreationStarted()) {
                synchronized(this.beanDefinitionMap) {
                    this.beanDefinitionMap.put(beanName, beanDefinition);
                    List<String> updatedDefinitions = new ArrayList(this.beanDefinitionNames.size() + 1);
                    updatedDefinitions.addAll(this.beanDefinitionNames);
                    updatedDefinitions.add(beanName);
                    this.beanDefinitionNames = updatedDefinitions;
                    this.removeManualSingletonName(beanName);
                }
            } else {
                // 正常注册流程
                this.beanDefinitionMap.put(beanName, beanDefinition);
                this.beanDefinitionNames.add(beanName);
                
                this.removeManualSingletonName(beanName);
            }

            this.frozenBeanDefinitionNames = null;
        }

        if (existingDefinition != null || this.containsSingleton(beanName)) {
            this.resetBeanDefinition(beanName);
        }

    }

在Spring容器启动的过程中,会将类解析成Spring内部的BeanDefinition结构,并将BeanDefinition存储到DefaultListableBeanFactory中

DefaultListableBeanFactory是整Spring注册及加载Bean的默认实现

private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap(256);
private volatile List<String> beanDefinitionNames = new ArrayList(256);

总结IoC容器的初始化过程:

  1. Resource定位(指的是BeanDefinition的资源定位,由ResourceLoader通过统一的Resource接口完成)
  2. BeanDefinition载入(把用户定义好的Bean表示成IoC容器内部的数据结构,即BeanDefinition)
  3. 向IoC容器注册BeanDefinition(BeanDefinitionRegistry)(在IoC容器内部将BeanDefinition注入到一个HashMap中,IoC容器通过HashMap持有BeanDefinition数据)
posted @ 2019-07-14 21:52  白芷呀  阅读(674)  评论(0编辑  收藏  举报