• spring IOC源码分析(ApplicationContext)


    在上一篇文章中,我们以BeanFactory这条主线进行IOC的源码解析的,这里,将以ApplicationContext这条线进行分析。先看使用方法:

        @Test
        public void testApplicationContext(){
            //在启动容器时,解析注册beanDefinition,实例化bean(针对非延迟加载的bean),然后完成依赖注入,最后初始化bean(在容器启动完成后,完成了所有的这些操作)
            @SuppressWarnings("resource")
            ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-context.xml");
            StudentManager studentManager = (StudentManager) applicationContext.getBean("studentManager");
            studentManager.study();
        }

    进入ClassPathXmlApplicationContext类

        public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
                throws BeansException {
            super(parent);
         //将资源文件存放到数组中 setConfigLocations(configLocations);
    if (refresh) { refresh(); //进入该方法 } }

    进入refresh方法

        @Override
        public void refresh() throws BeansException, IllegalStateException {
            synchronized (this.startupShutdownMonitor) {
                // Prepare this context for refreshing.
                prepareRefresh();
            //启动容器,完成BeanDefination的解析注册 进入该方法
                // Tell the subclass to refresh the internal bean factory.
                ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
                // Prepare the bean factory for use in this context.
                prepareBeanFactory(beanFactory);
    
                try {
                    // Allows post-processing of the bean factory in context subclasses.
                    postProcessBeanFactory(beanFactory);
    
                    // Invoke factory processors registered as beans in the context.
                    invokeBeanFactoryPostProcessors(beanFactory);
    
                    // Register bean processors that intercept bean creation.
                    registerBeanPostProcessors(beanFactory);
    
                    // Initialize message source for this context.
                    initMessageSource();
    
                    // Initialize event multicaster for this context.
                    initApplicationEventMulticaster();
    
                    // Initialize other special beans in specific context subclasses.
                    onRefresh();
    
                    // Check for listener beans and register them.
                    registerListeners();
                    //实例化所有的非延迟加载的bean 进入该方法
                    // Instantiate all remaining (non-lazy-init) singletons.
                    finishBeanFactoryInitialization(beanFactory);
    
                    // Last step: publish corresponding event.
                    finishRefresh();
                }
    
                catch (BeansException ex) {
                    if (logger.isWarnEnabled()) {
                        logger.warn("Exception encountered during context initialization - " +
                                "cancelling refresh attempt: " + ex);
                    }
    
                    // Destroy already created singletons to avoid dangling resources.
                    destroyBeans();
    
                    // Reset 'active' flag.
                    cancelRefresh(ex);
    
                    // Propagate exception to caller.
                    throw ex;
                }
    
                finally {
                    // Reset common introspection caches in Spring's core, since we
                    // might not ever need metadata for singleton beans anymore...
                    resetCommonCaches();
                }
            }
        }

    1.解析注册BeanDefination

    进入obtainFreshBeanFactory方法

    protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    //重启容器 进入该方法 refreshBeanFactory(); ConfigurableListableBeanFactory beanFactory
    = getBeanFactory(); if (logger.isDebugEnabled()) { logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory); } return beanFactory; }

    进入refreshBeanFactory方法

        @Override
        protected final void refreshBeanFactory() throws BeansException {
    //如果已存在容器,则销毁容器中所有的bean,然后关闭容器
    if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try {         //生成容器 
    DefaultListableBeanFactory beanFactory
    = createBeanFactory(); beanFactory.setSerializationId(getId()); customizeBeanFactory(beanFactory);
            //解析加载BeanDefination 进入该方法 loadBeanDefinitions(beanFactory);
    synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } }

    进入loadBeanDefinitions方法

        @Override
        protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
            // Create a new XmlBeanDefinitionReader for the given BeanFactory.
            //XmlBeanDefinitionReader由名字可知,它的作用是读取xml文件,然后解析为BeanDefination       
    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
    // Configure the bean definition reader with this context's
            // resource loading environment.
            beanDefinitionReader.setEnvironment(this.getEnvironment());
            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); }

    进入loadBeanDefinations方法

    protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
            Resource[] configResources = getConfigResources();
            if (configResources != null) {
                reader.loadBeanDefinitions(configResources);
            }
            String[] configLocations = getConfigLocations();
            if (configLocations != null) {
    //进入该方法configLocations是之前存放资源文件的数组 reader.loadBeanDefinitions(configLocations); } }

    进入loadBeanDefinitions

        @Override
        public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
            Assert.notNull(locations, "Location array must not be null");
            int counter = 0;
    //
    for (String location : locations) {
    //进入该方法 counter
    += loadBeanDefinitions(location); } return counter; }

    进入loadBeanDefinitions

        @Override
        public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
            return loadBeanDefinitions(location, null); //进入该方法
        }

    进入loadBeanDefinitions方法

    public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {
            ResourceLoader resourceLoader = getResourceLoader();
            if (resourceLoader == null) {
                throw new BeanDefinitionStoreException(
                        "Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
            }
    
            if (resourceLoader instanceof ResourcePatternResolver) {
                // Resource pattern matching available.
                try {
    //获取资源文件 Resource[] resources
    = ((ResourcePatternResolver) resourceLoader).getResources(location);
    //进入该方法
    int loadCount = loadBeanDefinitions(resources); if (actualResources != null) { for (Resource resource : resources) { actualResources.add(resource); } } if (logger.isDebugEnabled()) { logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]"); } return loadCount; } 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 loadCount = loadBeanDefinitions(resource); if (actualResources != null) { actualResources.add(resource); } if (logger.isDebugEnabled()) { logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]"); } return loadCount; } }

    进入loadBeanDefinitins

        @Override
        public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
            Assert.notNull(resources, "Resource array must not be null");
            int counter = 0;
            for (Resource resource : resources) {
           //进入该方法 counter
    += loadBeanDefinitions(resource); } return counter; }

     进入 loadBeanDefinitions

    @Override
        public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
            return loadBeanDefinitions(new EncodedResource(resource)); //进入该方法
        }

    进入loadBeanDefinitions方法

    public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
            Assert.notNull(encodedResource, "EncodedResource must not be null");
            if (logger.isInfoEnabled()) {
                logger.info("Loading XML bean definitions from " + encodedResource.getResource());
            }
            
            Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
            if (currentResources == null) {
                currentResources = new HashSet<EncodedResource>(4);
                this.resourcesCurrentlyBeingLoaded.set(currentResources);
            }
            if (!currentResources.add(encodedResource)) {
                throw new BeanDefinitionStoreException(
                        "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
            }
            try {
                InputStream inputStream = encodedResource.getResource().getInputStream();
                try {
                    InputSource inputSource = new InputSource(inputStream);
                    if (encodedResource.getEncoding() != null) {
                        inputSource.setEncoding(encodedResource.getEncoding());
                    }
         //进入该方法
    return doLoadBeanDefinitions(inputSource, encodedResource.getResource()); } finally { inputStream.close(); } } catch (IOException ex) { throw new BeanDefinitionStoreException( "IOException parsing XML document from " + encodedResource.getResource(), ex); } finally { currentResources.remove(encodedResource); if (currentResources.isEmpty()) { this.resourcesCurrentlyBeingLoaded.remove(); } } }

    进入doLoadBeanDefinitions方法

    protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
                throws BeanDefinitionStoreException {
            try {
    //把resource文件转为document Document doc
    = doLoadDocument(inputSource, resource);
    //进入该方法
    return registerBeanDefinitions(doc, resource); } catch (BeanDefinitionStoreException ex) { throw ex; }
    //以下catch到的各种异常就是在解析document时的报错信息,经常会遇到
    catch (SAXParseException ex) { throw new XmlBeanDefinitionStoreException(resource.getDescription(), "Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex); } catch (SAXException ex) { throw new XmlBeanDefinitionStoreException(resource.getDescription(), "XML document from " + resource + " is invalid", ex); } catch (ParserConfigurationException ex) { throw new BeanDefinitionStoreException(resource.getDescription(), "Parser configuration exception parsing XML from " + resource, ex); } catch (IOException ex) { throw new BeanDefinitionStoreException(resource.getDescription(), "IOException parsing XML document from " + resource, ex); } catch (Throwable ex) { throw new BeanDefinitionStoreException(resource.getDescription(), "Unexpected exception parsing XML document from " + resource, ex); } }

    进入registerBeanDefinitions方法

    public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
            BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
            int countBefore = getRegistry().getBeanDefinitionCount();
    //进入该方法 documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
    return getRegistry().getBeanDefinitionCount() - countBefore; }

    进入registerBeanDefinitions方法

    @Override
        public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
            this.readerContext = readerContext;
            logger.debug("Loading bean definitions");
            Element root = doc.getDocumentElement();
         //进入该方法 doRegisterBeanDefinitions(root); }

    进入doRegiseterBeanDefinitions方法

        /**
         * Register each bean definition within the given root {@code <beans/>} element.
         */
        protected void doRegisterBeanDefinitions(Element root) {
            // Any nested <beans> elements will cause recursion in this method. In
            // order to propagate and preserve <beans> default-* attributes correctly,
            // keep track of the current (parent) delegate, which may be null. Create
            // the new (child) delegate with a reference to the parent for fallback purposes,
            // then ultimately reset this.delegate back to its original (parent) reference.
            // this behavior emulates a stack of delegates without actually necessitating one.
            //BeanDefinitionsParserDelegate用来解析BeanDefination的,进入该类可知,该类定义有解析beanDefination的各种方法
         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.isInfoEnabled()) { logger.info("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)) {
                //获取document的所有子节点,并对每个子节点逐一解析
           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)) {
    //如果是默认的命名空间,用默认的解析方法解析beanDefinition 进入该方法
                  //默认的命名空间是 http://www.springframework.org/schema/beans  
    parseDefaultElement(ele, delegate); }
    else {
    //如果不是默认的命名空间,使用自定义的解析方法解析beanDefinition 进入该方法 delegate.parseCustomElement(ele); } } } }
    else { delegate.parseCustomElement(root); } }

    进入方法 parseDefaultElement

    private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
    //处理不同类型的子节点 比如<import /> <alias /> <bean />
    if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) { importBeanDefinitionResource(ele); } else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) { processAliasRegistration(ele); }
    //这是处理<bean /> ,进入该方法
    else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) { processBeanDefinition(ele, delegate); } else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) { // recurse doRegisterBeanDefinitions(ele); } }

    进入processBeanDefinition方法

        protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
    //将element节点解析为BeanDefinitionHolder,BeanDefinitionHolder包含BeanDefinition,beanName,aliases BeanDefinitionHolder bdHolder
    = delegate.parseBeanDefinitionElement(ele); if (bdHolder != null) { bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try { // Register the final decorated instance. //注册beanDefination,alias,也就是将beanDefination,alias放到HashMap中 进入该方法
              BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); }
    catch (BeanDefinitionStoreException ex) { getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, ex); } // Send registration event. getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); } }

    进入registerBeanDefination方法

    public static void registerBeanDefinition(
                BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
                throws BeanDefinitionStoreException {
         //注册BeanDefination,进入该方法后可以看到,将beandefination放到currentHashMap中 
            // Register bean definition under primary name.
            String beanName = definitionHolder.getBeanName();
            registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
            //注册alias,也是将alias放到currentHashMap中
            // Register aliases for bean name, if any.
            String[] aliases = definitionHolder.getAliases();
            if (aliases != null) {
                for (String alias : aliases) {
                    registry.registerAlias(beanName, alias);
                }
            }
        }

    到此,如果是默认的命名空间,则走parseDefaultElement这个方法,已经结束。如果不是默认的命名空间,走parseCustomElement这个方法,接下来我们就进入parseCustomElement这个方法看看。

    public BeanDefinition parseCustomElement(Element ele) {
            return parseCustomElement(ele, null);
        }
    
        public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
            String namespaceUri = getNamespaceURI(ele);
            NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
            if (handler == null) {
                error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
                return null;
            }
    //解析过程在这个方法里
    return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)); }

     2.实例化bean,完成依赖注入和初始化

    进入finishBeanFactoryInitialization方法

    	/**
    	 * Finish the initialization of this context's bean factory,
    	 * initializing all remaining singleton beans.
    	 */
    	protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    		// Initialize conversion service for this context.
    		if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
    				beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
    			beanFactory.setConversionService(
    					beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
    		}
    
    		// Register a default embedded value resolver if no bean post-processor
    		// (such as a PropertyPlaceholderConfigurer bean) registered any before:
    		// at this point, primarily for resolution in annotation attribute values.
    		if (!beanFactory.hasEmbeddedValueResolver()) {
    			beanFactory.addEmbeddedValueResolver(new StringValueResolver() {
    				@Override
    				public String resolveStringValue(String strVal) {
    					return getEnvironment().resolvePlaceholders(strVal);
    				}
    			});
    		}
    
    		// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
    		String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
    		for (String weaverAwareName : weaverAwareNames) {
    			getBean(weaverAwareName);
    		}
    
    		// Stop using the temporary ClassLoader for type matching.
    		beanFactory.setTempClassLoader(null);
              //缓存所有的BeanDefination,以防止将来被修改
    		// Allow for caching all bean definition metadata, not expecting further changes.
    		beanFactory.freezeConfiguration();
                    //对非延迟加载的单例bean进行预实例化  默认就是非延迟加载(lazy-init='false')和单例(scope='singleton')
    		// Instantiate all remaining (non-lazy-init) singletons.
    		beanFactory.preInstantiateSingletons();  //进入该方法
    	}  

    进入preInstantiateSingletons方法

        @Override
        public void preInstantiateSingletons() throws BeansException {
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Pre-instantiating singletons in " + this);
            }
    
            // Iterate over a copy to allow for init methods which in turn register new bean definitions.
            // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
            List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
         //初始化所有非延迟加载的单例bean 
            // Trigger initialization of all non-lazy singleton beans...
            for (String beanName : beanNames) {
                RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
                if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
    //判断是否是factorybean
    if (isFactoryBean(beanName)) {
    //如果是factorybean,通过&beanName获取到的是factorybean对象本身;如果要获取factorybean产生的对象,则直接使用beanName获取
    final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName); //标识是否需要预实例化
                boolean isEagerInit; if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() { @Override public Boolean run() { return ((SmartFactoryBean<?>) factory).isEagerInit(); } }, getAccessControlContext()); } else { isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factory).isEagerInit()); } if (isEagerInit) {
    //实例化对象,完成依赖注入和初始化 getBean(beanName); } }
    else {
           //实例化对象,完成依赖注入和初始化 进入该方法 getBean(beanName); } } }
    // Trigger post-initialization callback for all applicable beans... for (String beanName : beanNames) { Object singletonInstance = getSingleton(beanName); if (singletonInstance instanceof SmartInitializingSingleton) { final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance; if (System.getSecurityManager() != null) { AccessController.doPrivileged(new PrivilegedAction<Object>() { @Override public Object run() { smartSingleton.afterSingletonsInstantiated(); return null; } }, getAccessControlContext()); } else { smartSingleton.afterSingletonsInstantiated(); } } } }

    对于getBean方法的分析,在上一篇博文中已经有了,这里就不再赘述。点击链接至《springIOC源码分析(BeanFactory)》

  • 相关阅读:
    修改CentOS默认yum源为国内镜像
    linux下安装部署ansible
    Centos7 下安装部署zabbix-agent客户端
    Centos7下安装部署zabbix
    Jumpserver文档链接
    分布式部署文档
    分布式部署文档
    分布式部署文档
    分布式部署文档
    分布式部署文档
  • 原文地址:https://www.cnblogs.com/51life/p/9199468.html
Copyright © 2020-2023  润新知