• spring IOC


    基本实现代码:

    public class TestMain {
    	public static void main(String[] args) throws IOException {
    		//资源解析器
    		ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
    		//获取路径下的配置
    		Resource resource = resolver.getResource("classpath:bean.xml");
    		//创建bean工厂
    		DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
    		//定义xml bean解析器
    		XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
    		//装载bean
    		reader.loadBeanDefinitions(resource);
    		//获取bean
    		Car car = (Car) beanFactory.getBean("car");
    		System.out.println(car.getBrand());
    		//注意,和ApplicationContext不同,BeanFactory在首次调用getBean方法时才去创建bean的实例
    	}
    }
    上面的步奏都是创建对象实例,加载资源
    我们重点关注加载bean和读取bean的方法。首先是loadBeanDefinitions方法,源码如下:
    public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
    	return loadBeanDefinitions(new EncodedResource(resource));
    }
    继续跟进:
    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缓存
    	Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
    	if (currentResources == null) {
    		currentResources = new HashSet<>(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 {
    		//将资转成document。首先创建DocumentBuilderFactory实例,通过DocumentBuilderFactory创建DocumentBuilder,DocumentBuilder调用parse方法将InputSource解析称为Document
    		Document doc = doLoadDocument(inputSource, resource);
    		//注册定义的bean
    		return registerBeanDefinitions(doc, resource);
    	}
    	catch (BeanDefinitionStoreException ex) {
    		throw ex;
    	}
    	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);
    	}
    }
    //注册方法如下:
    public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
    	//创建documentReader
    	BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
    	//获取已经注册的bean的总数
    	int countBefore = getRegistry().getBeanDefinitionCount();
    	//注册bean
    	documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
    	return getRegistry().getBeanDefinitionCount() - countBefore;
    }
    //在看registerBeanDefinitions方法之前,我们先看看如何创建的上下文:
    public XmlReaderContext createReaderContext(Resource resource) {
    	return new XmlReaderContext(resource, this.problemReporter, this.eventListener,
    			this.sourceExtractor, this, getNamespaceHandlerResolver());
    }
    //可以看到,直接new了一个XmlReaderContext接下来:
    public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
    	this.readerContext = readerContext;
    	logger.debug("Loading bean definitions");
    	Element root = doc.getDocumentElement();
    	doRegisterBeanDefinitions(root);
    }
    protected void doRegisterBeanDefinitions(Element root) {
    	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);//此方法不做任何操作
    	//具体对每一个Element的解析
    	parseBeanDefinitions(root, this.delegate);
    	postProcessXml(root);//此方法也不做任何操作
    
    	this.delegate = parent;
    }
    //解析bean
    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)) {
    					parseDefaultElement(ele, delegate);
    				}
    				else {
    					delegate.parseCustomElement(ele);
    				}
    			}
    		}
    	}
    	else {
    		delegate.parseCustomElement(root);
    	}
    }
    //解析bean完成之后,会将解析出来的bean缓存入DefaultListableBeanFactory的beanDefinitionMap中
    
    //总结一下bean的解析过程:首先通过PathMatchingResourcePatternResolver获取配置文件,调用getResource方法获取Resource --> 然后获取文件输入流InputStream-->之后初始化Document,DefaultBeanDefinitionDocumentReader解析Document,解析xml的配置元信息Element-->BeanDefinitionReaderUtils工具将解析出来的bean存入DefaultListableBeanFactory的beanDefinitionMap中。至此,初步解析完成。
    
    下面我们看看getBean方法:
    public Object getBean(String name) throws BeansException {
    	return doGetBean(name, null, null, false);
    }
    protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
    		@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
    
    	//首先获取beanName
    	final String beanName = transformedBeanName(name);
    	Object bean;
    
    	// Eagerly check singleton cache for manually registered singletons.
    	Object sharedInstance = getSingleton(beanName);//首次获取sharedInstance为空,直接看else
    	if (sharedInstance != null && args == null) {
    		if (logger.isDebugEnabled()) {
    			if (isSingletonCurrentlyInCreation(beanName)) {
    				logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
    						"' that is not fully initialized yet - a consequence of a circular reference");
    			}
    			else {
    				logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
    			}
    		}
    		bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    	}
    
    	else {
    		// Fail if we're already creating this bean instance:
    		// We're assumably within a circular reference.
    		//如果当前实例正在被创建,则抛出异常
    		if (isPrototypeCurrentlyInCreation(beanName)) {
    			throw new BeanCurrentlyInCreationException(beanName);
    		}
    
    		// Check if bean definition exists in this factory.
    		//parentBeanFactory为空 
    		BeanFactory parentBeanFactory = getParentBeanFactory();
    		if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
    			// Not found -> check parent.
    			String nameToLookup = originalBeanName(name);
    			if (parentBeanFactory instanceof AbstractBeanFactory) {
    				return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
    						nameToLookup, requiredType, args, typeCheckOnly);
    			}
    			else if (args != null) {
    				// Delegation to parent with explicit args.
    				return (T) parentBeanFactory.getBean(nameToLookup, args);
    			}
    			else {
    				// No args -> delegate to standard getBean method.
    				return parentBeanFactory.getBean(nameToLookup, requiredType);
    			}
    		}
    
    		if (!typeCheckOnly) {
    			//标记bean被创建,并将beanName存入alreadyCreated中
    			markBeanAsCreated(beanName);
    		}
    
    		try {
    			final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
    			checkMergedBeanDefinition(mbd, beanName, args);
    
    			// Guarantee initialization of beans that the current bean depends on.
    			String[] dependsOn = mbd.getDependsOn();
    			if (dependsOn != null) {
    				for (String dep : dependsOn) {
    					if (isDependent(beanName, dep)) {
    						throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    								"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
    					}
    					registerDependentBean(dep, beanName);
    					getBean(dep);
    				}
    			}
    
    			// Create bean instance.
    			if (mbd.isSingleton()) {
    				sharedInstance = getSingleton(beanName, () -> {
    					try {
    						return createBean(beanName, mbd, args);
    					}
    					catch (BeansException ex) {
    						// Explicitly remove instance from singleton cache: It might have been put there
    						// eagerly by the creation process, to allow for circular reference resolution.
    						// Also remove any beans that received a temporary reference to the bean.
    						destroySingleton(beanName);
    						throw ex;
    					}
    				});
    				bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    			}
    
    			else if (mbd.isPrototype()) {
    				// It's a prototype -> create a new instance.
    				Object prototypeInstance = null;
    				try {
    					beforePrototypeCreation(beanName);
    					prototypeInstance = createBean(beanName, mbd, args);
    				}
    				finally {
    					afterPrototypeCreation(beanName);
    				}
    				bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
    			}
    
    			else {
    				String scopeName = mbd.getScope();
    				final Scope scope = this.scopes.get(scopeName);
    				if (scope == null) {
    					throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
    				}
    				try {
    					Object scopedInstance = scope.get(beanName, () -> {
    						beforePrototypeCreation(beanName);
    						try {
    							return createBean(beanName, mbd, args);
    						}
    						finally {
    							afterPrototypeCreation(beanName);
    						}
    					});
    					bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
    				}
    				catch (IllegalStateException ex) {
    					throw new BeanCreationException(beanName,
    							"Scope '" + scopeName + "' is not active for the current thread; consider " +
    							"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
    							ex);
    				}
    			}
    		}
    		catch (BeansException ex) {
    			cleanupAfterBeanCreationFailure(beanName);
    			throw ex;
    		}
    	}
    
    	// Check if required type matches the type of the actual bean instance.
    	if (requiredType != null && !requiredType.isInstance(bean)) {
    		try {
    			T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
    			if (convertedBean == null) {
    				throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
    			}
    			return convertedBean;
    		}
    		catch (TypeMismatchException ex) {
    			if (logger.isDebugEnabled()) {
    				logger.debug("Failed to convert bean '" + name + "' to required type '" +
    						ClassUtils.getQualifiedName(requiredType) + "'", ex);
    			}
    			throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
    		}
    	}
    	return (T) bean;
    }
    //首先从singletonObjects这个map中获取对象,有则直接返回,没有则创建之,并缓存入
  • 相关阅读:
    Linux文件系统之目录清单
    Linux系统使用iftop查看带宽占用情况
    性能分析之TCP全连接队列占满问题分析及优化过程(转载)
    什么是枚举及枚举的使用场合
    height:100%和height:auto的区别
    Jquery基础之DOM操作
    SSM三大框架整合(Spring+SpringMVC+MyBatis)
    js解析JSON
    mybatis中oracle实现分页效果
    MyBatis动态SQL语句
  • 原文地址:https://www.cnblogs.com/canmeng-cn/p/8689938.html
Copyright © 2020-2023  润新知