刚学习Spring的时候,印象最深的就是 DispatcherServlet,所谓的中央调度器,我也尝试从这个万能胶这里找到入口
configureAndRefreshWebApplicationContext()方法,应该就是IOC容器初始化的真正入口
我开始手写测试用例(xml配置的bean实例),ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("xxx.xml");
通过跟踪代码和debug的方式,找到了大概的初始化流程
ClassPathXmlApplicationContext 的构造方法
public ClassPathXmlApplicationContext(String configLocation) throws BeansException { this(new String[] {configLocation}, true, null); }
AbstractApplicationContext类
接着--->>>
接着--->>>AbstractXmlApplicationContext
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException { //创建XmlBeanDefinitionReader XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); beanDefinitionReader.setEnvironment(this.getEnvironment()); //容器本身也是一个资源加载器 beanDefinitionReader.setResourceLoader(this); //为Bean读取器设置SAX xml解析器 beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); //当Bean读取器读取Bean定义的Xml资源文件时,启用Xml的校验机制 initBeanDefinitionReader(beanDefinitionReader); //Bean读取器真正实现加载的方法 loadBeanDefinitions(beanDefinitionReader); } protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException { //获取Bean定义资源的定位 Resource[] configResources = getConfigResources(); if (configResources != null) { reader.loadBeanDefinitions(configResources); } //如果子类中获取的Bean定义资源定位为空,则获取FileSystemXmlApplicationContext构造方法中setConfigLocations方法设置的资源 String[] configLocations = getConfigLocations(); if (configLocations != null) { //Xml Bean读取器调用其父类AbstractBeanDefinitionReader读取定位 reader.loadBeanDefinitions(configLocations); } }
接着--->>>AbstractBeanDefinitionReader
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; }
接着--->>>
public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException { return loadBeanDefinitions(location, null); }
接着--->>>
public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException { //获取在IoC容器初始化过程中设置的资源加载器 ResourceLoader resourceLoader = getResourceLoader(); if (resourceLoader == null) { throw new BeanDefinitionStoreException("Cannot import bean definitions from location [" + location + "]: no ResourceLoader available"); } if (resourceLoader instanceof ResourcePatternResolver) { try { //加载多个指定位置的Bean定义资源文件 Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location); //委派调用其子类XmlBeanDefinitionReader的方法,实现加载功能 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 { 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; } }
接着--->>>
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; }
接着--->>>XmlBeanDefinitionReader
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException { //将读入的XML资源进行特殊编码处理 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<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的IO流 InputStream inputStream = encodedResource.getResource().getInputStream(); try { //从InputStream中得到XML的解析源 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(); } } }
接着--->>>
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException { try { //将XML文件转换为DOM对象,解析过程由documentLoader实现 Document doc = doLoadDocument(inputSource, resource); //这里是启动对Bean定义解析的详细过程,该解析过程会用到Spring的Bean配置规则 return registerBeanDefinitions(doc, resource); } catch (Exception ex) { throw ex; }}
接着--->>>
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { //获取BeanDefinitionDocumentReader BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); //获得容器中注册的Bean数量 int countBefore = getRegistry().getBeanDefinitionCount(); //具体的解析实现过程实现类DefaultBeanDefinitionDocumentReader完成 documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); //统计解析的Bean数量 return getRegistry().getBeanDefinitionCount() - countBefore; }
接着--->>>DefaultBeanDefinitionDocumentReader
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) { //获得XML描述符 this.readerContext = readerContext; logger.debug("Loading bean definitions"); //获得Document的根元素 Element root = doc.getDocumentElement(); doRegisterBeanDefinitions(root); }
接着--->>>
protected void doRegisterBeanDefinitions(Element root) { //具体的解析过程由BeanDefinitionParserDelegate实现, 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;}}} //在解析Bean定义之前,进行自定义的解析,增强解析过程的可扩展性 preProcessXml(root); //从Document的根元素开始进行Bean定义的Document对象 parseBeanDefinitions(root, this.delegate); //在解析Bean定义之后,进行自定义的解析,增加解析过程的可扩展性 postProcessXml(root); this.delegate = parent; }
接着--->>>
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) { //Bean定义的Document对象使用了Spring默认的XML命名空间 if (delegate.isDefaultNamespace(root)) { NodeList nl = root.getChildNodes(); for (int i = 0; i < nl.getLength(); i++) { Node node = nl.item(i); //获得Document节点是XML元素节点 if (node instanceof Element) { Element ele = (Element) node; //Bean定义的Document的元素节点使用的是Spring默认的XML命名空间 if (delegate.isDefaultNamespace(ele)) { parseDefaultElement(ele, delegate); } else { delegate.parseCustomElement(ele); } } } } else { delegate.parseCustomElement(root); } }
接着--->>>
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) { //如果元素节点是<Import>导入元素,进行导入解析 if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) { importBeanDefinitionResource(ele); } //如果元素节点是<Alias>别名元素,进行别名解析 else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) { processAliasRegistration(ele); } //按照Spring的Bean规则解析元素 else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) { processBeanDefinition(ele, delegate); } else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) { // recurse doRegisterBeanDefinitions(ele); } }
接着--->>>
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); // BeanDefinitionHolder是对BeanDefinition的封装,即Bean定义的封装类 // BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); if (bdHolder != null) { bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try { // Register the final decorated instance. //向Spring IOC容器注册解析得到的Bean定义,这是Bean定义向IOC容器注册的入口 BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); } catch (BeanDefinitionStoreException ex) { getReaderContext().error("Failed to register bean definition with name ‘" +bdHolder.getBeanName() + "‘", ele, ex); } //在完成向Spring IOC容器注册解析得到的Bean定义之后,发送注册事件 getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); } }
接着--->>>BeanDefinitionReaderUtils
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException { //获取解析的BeanDefinition的名称 String beanName = definitionHolder.getBeanName(); //向IOC容器注册BeanDefinition registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); //如果解析的BeanDefinition有别名,向容器为其注册别名 String[] aliases = definitionHolder.getAliases(); if (aliases != null) { for (String alias : aliases) { registry.registerAlias(beanName, alias); } } }
原文:https://www.cnblogs.com/dyg0826/p/10716040.html