• 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数据)
  • 相关阅读:
    T100添加合计
    T100整单操作维护交运方式
    错误代码:11300001 数据集配置错误Query:ORA-01652: 无法通过 128 (在表空间 TEMP 中) 扩展 temp 段
    T100 技术汇总
    帆软取年月常用函数
    使用oracle DB_LINK的一个注意点
    单行拆转多行的查询
    SQL-Oracle内实现柱形图式的效果
    SQL-删除重复记录
    MERGE语法详解
  • 原文地址:https://www.cnblogs.com/angelica-duhurica/p/11185996.html
Copyright © 2020-2023  润新知