Spring-IOC容器的介绍(附代码)

互联网 19-3-27
本篇文章给大家带来的内容是关于Spring-IOC容器的介绍(附代码),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

Spring IoC容器对Bean定义资源的载入是从refresh()函数开始的,refresh()是一个模板方法,refresh()方法的作用是:在创建IoC容器前,如果已经有容器存在,则需要把已有的容器销毁和关闭,以保证在refresh之后使用的是新建立起来的IoC容器。refresh的作用类似于对IoC容器的重启,在新建立好的容器中对容器进行初始化,对Bean定义资源进行载入

public void refresh() throws BeansException, IllegalStateException {        Object var1 = this.startupShutdownMonitor;        synchronized(this.startupShutdownMonitor) {            //调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识            this.prepareRefresh();            //告诉子类启动refreshBeanFactory()方法,Bean定义资源文件的载入从              //子类的refreshBeanFactory()方法启动             //这个bean的载入过程 包括对xml的解析和加载为BeanDefinitions 都是从this.obtainFreshBeanFactory()这里进入            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();            /*这之后的代码都是注册容器的信息源和生命周期事件*/            //为BeanFactory配置容器特性,例如类加载器、事件处理器等            this.prepareBeanFactory(beanFactory);             try {                //为容器的某些子类指定特殊的BeanPost事件处理器                this.postProcessBeanFactory(beanFactory);                //调用所有注册的BeanFactoryPostProcessor的Bean                this.invokeBeanFactoryPostProcessors(beanFactory);                //为BeanFactory注册BeanPost事件处理器.                  //BeanPostProcessor是Bean后置处理器,用于监听容器触发的事件                 this.registerBeanPostProcessors(beanFactory);                //初始化信息源,和国际化相关.                this.initMessageSource();                //初始化容器事件传播器.                this.initApplicationEventMulticaster();                //调用子类的某些特殊Bean初始化方法                this.onRefresh();                //为事件传播器注册事件监听器.                 this.registerListeners();                //初始化所有剩余的单态Bean.                this.finishBeanFactoryInitialization(beanFactory);                //初始化容器的生命周期事件处理器,并发布容器的生命周期事件                this.finishRefresh();            } catch (BeansException var9) {                if (this.logger.isWarnEnabled()) {                    this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);                }                //销毁以创建的单态Bean                this.destroyBeans();                //取消refresh操作,重置容器的同步标识.                this.cancelRefresh(var9);                throw var9;            } finally {                this.resetCommonCaches();            }         }    }
protected final void refreshBeanFactory() throws BeansException {         //如果已经创建了BeanFactory,则销毁并关闭BeanFactory         if (this.hasBeanFactory()) {             this.destroyBeans();             this.closeBeanFactory();         }          try {              //创建了一个IOC容器             DefaultListableBeanFactory beanFactory = this.createBeanFactory();             beanFactory.setSerializationId(this.getId());             /对IoC容器进行定制化,如设置启动参数,开启注解的自动装配等             this.customizeBeanFactory(beanFactory);             //调用载入Bean定义的方法,主要这里又使用了一个委派模式,在当前类中只定义了抽象的loadBeanDefinitions方法,具体的实现调用子类容器             this.loadBeanDefinitions(beanFactory);             Object var2 = this.beanFactoryMonitor;             synchronized(this.beanFactoryMonitor) {                 this.beanFactory = beanFactory;             }         } catch (IOException var5) {             throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var5);         }     }

AbstractXmlApplicationContext 类:

 protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {         //创建XmlBeanDefinitionReader,即创建Bean读取器,并通过回调设置到容器中去,容器使用该读取器读取Bean定义资源           XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);         beanDefinitionReader.setEnvironment(this.getEnvironment());          //为Bean读取器设置Spring资源加载器,AbstractXmlApplicationContext的           //祖先父类AbstractApplicationContext继承DefaultResourceLoader,因此,容器本身也是一个资源加载器         beanDefinitionReader.setResourceLoader(this);         //为Bean读取器设置SAX xml解析器          beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));         //当Bean读取器读取Bean定义的Xml资源文件时,启用Xml的校验机制           this.initBeanDefinitionReader(beanDefinitionReader);         //Bean读取器真正实现加载的方法         this.loadBeanDefinitions(beanDefinitionReader);     }          protected void initBeanDefinitionReader(XmlBeanDefinitionReader reader) {         reader.setValidating(this.validating);     }      protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {         Resource[] configResources = this.getConfigResources();         if (configResources != null) {             reader.loadBeanDefinitions(configResources);         }          String[] configLocations = this.getConfigLocations();         if (configLocations != null) {             reader.loadBeanDefinitions(configLocations);         }      }      @Nullable     protected Resource[] getConfigResources() {         return null;     }

在其抽象父类AbstractBeanDefinitionReader中定义了载入过程

 public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {         //获取resourceLoader         ResourceLoader resourceLoader = this.getResourceLoader();         if (resourceLoader == null) {             throw new BeanDefinitionStoreException("Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");         } else {             int loadCount;             if (!(resourceLoader instanceof ResourcePatternResolver)) {                 //将指定位置的Bean定义资源文件解析为Spring IoC容器封装的资源                   //加载多个指定位置的Bean定义资源文件 完成具体的资源定位的工作                                Resource resource = resourceLoader.getResource(location);                 //加载资源 开始我们的第二步操作 转换为BeanDefinition对象                 loadCount = this.loadBeanDefinitions((Resource)resource);                 if (actualResources != null) {                     actualResources.add(resource);                 }                  if (this.logger.isDebugEnabled()) {                     this.logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");                 }                  return loadCount;             } else {                 try {                    //将指定位置的Bean定义资源文件解析为Spring IoC容器封装的资源                      //加载单个指定位置的Bean定义资源文件                       Resource[] resources = ((ResourcePatternResolver)resourceLoader).getResources(location);                     //加载资源 开始我们的第二步操作 转换为BeanDefinition对象                     loadCount = this.loadBeanDefinitions(resources);                     if (actualResources != null) {                         Resource[] var6 = resources;                         int var7 = resources.length;                          for(int var8 = 0; var8 < var7; ++var8) {                             Resource resource = var6[var8];                             actualResources.add(resource);                         }                     }                      if (this.logger.isDebugEnabled()) {                         this.logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");                     }                      return loadCount;                 } catch (IOException var10) {                     throw new BeanDefinitionStoreException("Could not resolve bean definition resource pattern [" + location + "]", var10);                 }             }         }     }

具体加载资源的方法 首先,调用资源加载器的获取资源方法resourceLoader.getResource(location),获取到要加载的资源。其次,真正执行加载功能是其子类XmlBeanDefinitionReader的loadBeanDefinitions方法。资源定位到这里就结束 最终返回的是一个Resource的对象来进行BeanDefinition的载入。在定位完成后,为BeanDefinition的载入创客I/O条件,但是具体的载入还没有开始载入。

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);                 }                 //带有classpath标识的Resource                 if (location.startsWith("classpath:")) {                     return new ClassPathResource(location.substring("classpath:".length()), this.getClassLoader());                 }                  try {                 //处理URL标识的Resource定位                     URL url = new URL(location);                     return (Resource)(ResourceUtils.isFileURL(url) ? new FileUrlResource(url) : new UrlResource(url));                 } catch (MalformedURLException var5) {                     //如果不存classpath、Url、/标志的 就教给他处理                     return this.getResourceByPath(location);                 }             }              ProtocolResolver protocolResolver = (ProtocolResolver)var2.next();             resource = protocolResolver.resolve(location, this);         } while(resource == null);          return resource;     }
protected Resource getResourceByPath(String path) {        if (path != null && path.startsWith("/")) {             path = path.substring(1);         }       //这里使用文件系统资源对象来定义bean 文件     return new FileSystemResource(path);   }
 public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {         //获取resourceLoader         ResourceLoader resourceLoader = this.getResourceLoader();         if (resourceLoader == null) {             throw new BeanDefinitionStoreException("Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");         } else {             int loadCount;             if (!(resourceLoader instanceof ResourcePatternResolver)) {                 //将指定位置的Bean定义资源文件解析为Spring IoC容器封装的资源                   //加载多个指定位置的Bean定义资源文件 完成具体的资源定位的工作                                Resource resource = resourceLoader.getResource(location);                   //加载资源 开始我们的第二步操作 转换为BeanDefinition对象                 loadCount = this.loadBeanDefinitions((Resource)resource);                 if (actualResources != null) {                     actualResources.add(resource);                 }                  if (this.logger.isDebugEnabled()) {                     this.logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");                 }                  return loadCount;             } else {                 try {                    //将指定位置的Bean定义资源文件解析为Spring IoC容器封装的资源                      //加载单个指定位置的Bean定义资源文件                       Resource[] resources = ((ResourcePatternResolver)resourceLoader).getResources(location);                     //加载资源 开始我们的第二步操作 转换为BeanDefinition对象                     loadCount = this.loadBeanDefinitions(resources);                     if (actualResources != null) {                         Resource[] var6 = resources;                         int var7 = resources.length;                          for(int var8 = 0; var8 < var7; ++var8) {                             Resource resource = var6[var8];                             actualResources.add(resource);                         }                     }                      if (this.logger.isDebugEnabled()) {                         this.logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");                     }                      return loadCount;                 } catch (IOException var10) {                     throw new BeanDefinitionStoreException("Could not resolve bean definition resource pattern [" + location + "]", var10);                 }             }         }     }
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {         Assert.notNull(encodedResource, "EncodedResource must not be null");         if(this.logger.isInfoEnabled()) {             this.logger.info("Loading XML bean definitions from " + encodedResource.getResource());         }          Set<EncodedResource> currentResources = (Set)this.resourcesCurrentlyBeingLoaded.get();         if(currentResources == null) {             currentResources = new HashSet(4);             this.resourcesCurrentlyBeingLoaded.set(currentResources);         }          if(!((Set)currentResources).add(encodedResource)) {             throw new BeanDefinitionStoreException("Detected cyclic loading of " + encodedResource + " - check your import definitions!");         } else {             int var5;             try {                 //将资源文件转为InputStream的IO流                 InputStream inputStream = encodedResource.getResource().getInputStream();                  try {                     //从InputStream中得到XML的解析源                     InputSource inputSource = new InputSource(inputStream);                     if(encodedResource.getEncoding() != null) {                         inputSource.setEncoding(encodedResource.getEncoding());                     }                      //这里是具体的读取过程                     var5 = this.doLoadBeanDefinitions(inputSource, encodedResource.getResource());                 } finally {                     //IO流的关闭                     inputStream.close();                 }             } catch (IOException var15) {                 throw new BeanDefinitionStoreException("IOException parsing XML document from " + encodedResource.getResource(), var15);             } finally {                 ((Set)currentResources).remove(encodedResource);                 if(((Set)currentResources).isEmpty()) {                     this.resourcesCurrentlyBeingLoaded.remove();                 }              }              return var5;         }     }
    protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {         try {             //@1将XML文件转换为DOM对象,解析过程由documentLoader实现             Document doc = this.doLoadDocument(inputSource, resource);             //@2这里是启动对Bean定义解析的详细过程,该解析过程会用到Spring的Bean配置规则             return this.registerBeanDefinitions(doc, resource);         } catch (BeanDefinitionStoreException var4) {             throw var4;         } catch (SAXParseException var5) {             throw new XmlBeanDefinitionStoreException(resource.getDescription(), "Line " + var5.getLineNumber() + " in XML document from " + resource + " is invalid", var5);         } catch (SAXException var6) {             throw new XmlBeanDefinitionStoreException(resource.getDescription(), "XML document from " + resource + " is invalid", var6);         } catch (ParserConfigurationException var7) {             throw new BeanDefinitionStoreException(resource.getDescription(), "Parser configuration exception parsing XML from " + resource, var7);         } catch (IOException var8) {             throw new BeanDefinitionStoreException(resource.getDescription(), "IOException parsing XML document from " + resource, var8);         } catch (Throwable var9) {             throw new BeanDefinitionStoreException(resource.getDescription(), "Unexpected exception parsing XML document from " + resource, var9);         }     }

@1

//使用标准的JAXP将载入的Bean定义资源转换成document对象  public Document loadDocument(InputSource inputSource, EntityResolver entityResolver, ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {         //创建文件解析器工厂          DocumentBuilderFactory factory = this.createDocumentBuilderFactory(validationMode, namespaceAware);         if(logger.isDebugEnabled()) {             logger.debug("Using JAXP provider [" + factory.getClass().getName() + "]");         }         //创建文档解析器           DocumentBuilder builder = this.createDocumentBuilder(factory, entityResolver, errorHandler);         //解析Spring的Bean定义资源         return builder.parse(inputSource);     }      protected DocumentBuilderFactory createDocumentBuilderFactory(int validationMode, boolean namespaceAware) throws ParserConfigurationException {      //创建文档解析工厂         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();         factory.setNamespaceAware(namespaceAware);         if(validationMode != 0) {            //设置解析XML的校验              factory.setValidating(true);             if(validationMode == 3) {                 factory.setNamespaceAware(true);                  try {                     factory.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaLanguage", "http://www.w3.org/2001/XMLSchema");                 } catch (IllegalArgumentException var6) {                     ParserConfigurationException pcex = new ParserConfigurationException("Unable to validate using XSD: Your JAXP provider [" + factory + "] does not support XML Schema. Are you running on Java 1.4 with Apache Crimson? Upgrade to Apache Xerces (or Java 1.5) for full XSD support.");                     pcex.initCause(var6);                     throw pcex;                 }             }         }          return factory;     }

Spring IoC容器根据定位的Bean定义资源文件,将其加载读入并转换成为Document对象过程完成。

 //按照Spring的Bean语义要求将Bean定义资源解析并转换为容器内部数据结构  public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {         /得到BeanDefinitionDocumentReader来对xml格式的BeanDefinition解析          BeanDefinitionDocumentReader documentReader = this.createBeanDefinitionDocumentReader();         //获得容器中注册的Bean数量         int countBefore = this.getRegistry().getBeanDefinitionCount();         //解析过程入口,这里使用了委派模式,BeanDefinitionDocumentReader只是个接口         //具体的解析实现过程有实现类DefaultBeanDefinitionDocumentReader完成         //@1         documentReader.registerBeanDefinitions(doc, this.createReaderContext(resource));         /统计解析的Bean数量          return this.getRegistry().getBeanDefinitionCount() - countBefore;     }     //创建BeanDefinitionDocumentReader对象,解析Document对象     protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {         return (BeanDefinitionDocumentReader)BeanDefinitionDocumentReader.class.cast(BeanUtils.instantiateClass(this.documentReaderClass));     }
 public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {     public static final String BEAN_ELEMENT = "bean";     public static final String NESTED_BEANS_ELEMENT = "beans";     public static final String ALIAS_ELEMENT = "alias";     public static final String NAME_ATTRIBUTE = "name";     public static final String ALIAS_ATTRIBUTE = "alias";     public static final String IMPORT_ELEMENT = "import";     public static final String RESOURCE_ATTRIBUTE = "resource";     public static final String PROFILE_ATTRIBUTE = "profile";     protected final Log logger = LogFactory.getLog(this.getClass());     private XmlReaderContext readerContext;     private BeanDefinitionParserDelegate delegate;      public DefaultBeanDefinitionDocumentReader() {     }     //根据Spring DTD对Bean的定义规则解析Bean定义Document对象      public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {         //获得XML描述符          this.readerContext = readerContext;         this.logger.debug("Loading bean definitions");         //获得Document的根元素          Element root = doc.getDocumentElement();         this.doRegisterBeanDefinitions(root);     }      protected final XmlReaderContext getReaderContext() {         return this.readerContext;     }      protected Object extractSource(Element ele) {         return this.getReaderContext().extractSource(ele);     }     //具体的解析过程由BeanDefinitionParserDelegate实现,       //BeanDefinitionParserDelegate中定义了Spring Bean定义XML文件的各种元素     protected void doRegisterBeanDefinitions(Element root) {         BeanDefinitionParserDelegate parent = this.delegate;         this.delegate = this.createDelegate(this.getReaderContext(), root, parent);         if(this.delegate.isDefaultNamespace(root)) {             String profileSpec = root.getAttribute("profile");             if(StringUtils.hasText(profileSpec)) {                 String[] specifiedProfiles = StringUtils.tokenizeToStringArray(profileSpec, ",; ");                 if(!this.getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {                     if(this.logger.isInfoEnabled()) {                         this.logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec + "] not matching: " + this.getReaderContext().getResource());                     }                      return;                 }             }         }         //在解析Bean定义之前,进行自定义的解析,增强解析过程的可扩展性         this.preProcessXml(root);         //从Document的根元素开始进行Bean定义的Document对象         this.parseBeanDefinitions(root, this.delegate);         //在解析Bean定义之后,进行自定义的解析,增加解析过程的可扩展性         this.postProcessXml(root);         this.delegate = parent;     }     //创建BeanDefinitionParserDelegate,用于完成真正的解析过程     protected BeanDefinitionParserDelegate createDelegate(XmlReaderContext readerContext, Element root, BeanDefinitionParserDelegate parentDelegate) {         BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);         //BeanDefinitionParserDelegate初始化Document根元素         delegate.initDefaults(root, parentDelegate);         return delegate;     }     //使用Spring的Bean规则从Document的根元素开始进行Bean定义的Document对象     protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {          //Bean定义的Document对象使用了Spring默认的XML命名空间         if(delegate.isDefaultNamespace(root)) {            //获取Bean定义的Document对象根元素的所有子节点             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)) {                         //使用Spring的Bean规则解析元素节点                         this.parseDefaultElement(ele, delegate);                     } else {                        //没有使用Spring默认的XML命名空间,则使用用户自定义的解//析规则解析元素节点                         delegate.parseCustomElement(ele);                     }                 }             }         } else {             //Document的根节点没有使用Spring默认的命名空间,则使用用户自定义的              //解析规则解析Document根节点             delegate.parseCustomElement(root);         }      }      private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {         //如果元素节点是<Import>导入元素,进行导入解析           if(delegate.nodeNameEquals(ele, "import")) {             this.importBeanDefinitionResource(ele);                      } else if(delegate.nodeNameEquals(ele, "alias")) {         //如果元素节点是<Alias>别名元素,进行别名解析              this.processAliasRegistration(ele);         } else if(delegate.nodeNameEquals(ele, "bean")) {         //元素节点既不是导入元素,也不是别名元素,即普通的<Bean>元素,           //按照Spring的Bean规则解析元素               this.processBeanDefinition(ele, delegate);         } else if(delegate.nodeNameEquals(ele, "beans")) {          //如果元素节点是<beans>元素注册为BeanDefintion             this.doRegisterBeanDefinitions(ele);         }      }     //解析<Import>导入元素,从给定的导入路径加载Bean定义资源到Spring IoC容器中     protected void importBeanDefinitionResource(Element ele) {         /获取给定的导入元素的location属性          String location = ele.getAttribute("resource");         if(!StringUtils.hasText(location)) {             this.getReaderContext().error("Resource location must not be empty", ele);         } else {             //获取location的值              location = this.getReaderContext().getEnvironment().resolveRequiredPlaceholders(location);             Set<Resource> actualResources = new LinkedHashSet(4);             //标识给定的导入元素的location是否是绝对路径             boolean absoluteLocation = false;              try {                 absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute();             } catch (URISyntaxException var11) {                 ;             }              int importCount;             if(absoluteLocation) {                 try {                     //使用资源读入器加载给定路径的Bean定义资源                     importCount = this.getReaderContext().getReader().loadBeanDefinitions(location, actualResources);                     if(this.logger.isDebugEnabled()) {                         this.logger.debug("Imported " + importCount + " bean definitions from URL location [" + location + "]");                     }                 } catch (BeanDefinitionStoreException var10) {                     this.getReaderContext().error("Failed to import bean definitions from URL location [" + location + "]", ele, var10);                 }             } else {             //给定的导入元素的location是相对路径                   try {                     Resource relativeResource = this.getReaderContext().getResource().createRelative(location);                     if(relativeResource.exists()) {                          //使用资源读入器加载Bean定义资源                          importCount = this.getReaderContext().getReader().loadBeanDefinitions(relativeResource);                         actualResources.add(relativeResource);                     } else {                         String baseLocation = this.getReaderContext().getResource().getURL().toString();                         importCount = this.getReaderContext().getReader().loadBeanDefinitions(StringUtils.applyRelativePath(baseLocation, location), actualResources);                     }                      if(this.logger.isDebugEnabled()) {                         this.logger.debug("Imported " + importCount + " bean definitions from relative location [" + location + "]");                     }                 } catch (IOException var8) {                     this.getReaderContext().error("Failed to resolve current resource location", ele, var8);                 } catch (BeanDefinitionStoreException var9) {                     this.getReaderContext().error("Failed to import bean definitions from relative location [" + location + "]", ele, var9);                 }             }             //在解析完<Import>元素之后,发送容器导入其他资源处理完成事件             Resource[] actResArray = (Resource[])actualResources.toArray(new Resource[actualResources.size()]);             this.getReaderContext().fireImportProcessed(location, actResArray, this.extractSource(ele));         }     }    //解析<Alias>别名元素,为Bean向Spring IoC容器注册别名       protected void processAliasRegistration(Element ele) {         //获取<Alias>别名元素中name的属性值         String name = ele.getAttribute("name");         //获取<Alias>别名元素中alias的属性值           String alias = ele.getAttribute("alias");         boolean valid = true;         if(!StringUtils.hasText(name)) {             this.getReaderContext().error("Name must not be empty", ele);             valid = false;         }          if(!StringUtils.hasText(alias)) {             this.getReaderContext().error("Alias must not be empty", ele);             valid = false;         }          if(valid) {             try {                 //向容器的资源读入器注册别名                 this.getReaderContext().getRegistry().registerAlias(name, alias);             } catch (Exception var6) {                 this.getReaderContext().error("Failed to register alias '" + alias + "' for bean with name '" + name + "'", ele, var6);             }             //在解析完<Alias>元素之后,发送容器别名处理完成事件             this.getReaderContext().fireAliasRegistered(name, alias, this.extractSource(ele));         }      }      //解析Bean定义资源Document对象的普通元素     protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {         // BeanDefinitionHolder是对BeanDefinition的封装,即Bean定义的封装类          //对Document对象中<Bean>元素的解析由BeanDefinitionParserDelegate实现  BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);          BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);         if(bdHolder != null) {             bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);              try {                 //向Spring IoC容器注册解析得到的Bean定义,这是Bean定义向IoC容器注册的入口                 BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());             } catch (BeanDefinitionStoreException var5) {                 this.getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, var5);             }             //在完成向Spring IoC容器注册解析得到的Bean定义之后,发送注册事件             this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));         }      }      protected void preProcessXml(Element root) {     }      protected void postProcessXml(Element root) {     } }

下面是针对对Bean元素的解析过程

    //解析Bean定义资源文件中的<Bean>元素,这个方法中主要处理<Bean>元素的id,name     public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {         //获取id属性         String id = ele.getAttribute("id");         //获取name属性         String nameAttr = ele.getAttribute("name");         List<String> aliases = new ArrayList();         //将Bean元素的name属性全部放到alias属性里面         if(StringUtils.hasLength(nameAttr)) {             String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, ",; ");             aliases.addAll(Arrays.asList(nameArr));         }          String beanName = id;         if(!StringUtils.hasText(id) && !aliases.isEmpty()) {             beanName = (String)aliases.remove(0);             if(this.logger.isDebugEnabled()) {                 this.logger.debug("No XML 'id' specified - using '" + beanName + "' as bean name and " + aliases + " as aliases");             }         }          if(containingBean == null) {             //检查bean元素的id和name是否是唯一的              this.checkNameUniqueness(beanName, aliases, ele);         }         //详细对<Bean>元素中配置的Bean定义进行解析的地方         AbstractBeanDefinition beanDefinition = this.parseBeanDefinitionElement(ele, beanName, containingBean);         if(beanDefinition != null) {             if(!StringUtils.hasText(beanName)) {                 try {                     if(containingBean != null) {                         //判断如果没有id和name属性时候是否包含子元素的<Bean>                         beanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, this.readerContext.getRegistry(), true);                     } else {                         //如果<Bean>元素中没有配置id、别名或者name,且包含了子//<Bean>元素,为解析的Bean使用别名向IoC容器注册                           beanName = this.readerContext.generateBeanName(beanDefinition);                         String beanClassName = beanDefinition.getBeanClassName();                         if(beanClassName != null && beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() && !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {                             aliases.add(beanClassName);                         }                     }                      if(this.logger.isDebugEnabled()) {                         this.logger.debug("Neither XML 'id' nor 'name' specified - using generated bean name [" + beanName + "]");                     }                 } catch (Exception var9) {                     this.error(var9.getMessage(), ele);                     return null;                 }             }              String[] aliasesArray = StringUtils.toStringArray(aliases);             return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);         } else {             return null;         }     }     //详细解析bean元素的地方     public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean) {         this.parseState.push(new BeanEntry(beanName));         String className = null;         //是否包含class属性         if(ele.hasAttribute("class")) {             //获取class属性值 不做实例化,bean的实例化是在第一次获取bean的时候完成,这里只获取class的值             className = ele.getAttribute("class").trim();         }          try {             String parent = null;             //如果<Bean>元素中配置了parent属性,则获取parent属性的值             if(ele.hasAttribute("parent")) {                 parent = ele.getAttribute("parent");             }            //根据<Bean>元素配置的class名称和parent属性值创建BeanDefinition               //为载入Bean定义信息做准备              AbstractBeanDefinition bd = this.createBeanDefinition(className, parent);             //对当前的<Bean>元素中配置的一些属性进行解析和设置,如配置的单态(singleton)属性等             this.parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);             //为<Bean>元素解析的Bean设置description信息 bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));             bd.setDescription(DomUtils.getChildElementValueByTagName(ele, "description"));             //对<Bean>元素的meta(元信息)属性解析             this.parseMetaElements(ele, bd);             //对<Bean>元素的lookup-method属性解析             this.parseLookupOverrideSubElements(ele, bd.getMethodOverrides());             //对<Bean>元素的replaced-method属性解析             this.parseReplacedMethodSubElements(ele, bd.getMethodOverrides());             //解析<Bean>元素的构造方法设置             this.parseConstructorArgElements(ele, bd);              //解析<Bean>元素的<property>设置             this.parsePropertyElements(ele, bd);              //解析<Bean>元素的qualifier属性             this.parseQualifierElements(ele, bd);             bd.setResource(this.readerContext.getResource());             bd.setSource(this.extractSource(ele));             AbstractBeanDefinition var7 = bd;             return var7;         } catch (ClassNotFoundException var13) {             this.error("Bean class [" + className + "] not found", ele, var13);         } catch (NoClassDefFoundError var14) {             this.error("Class that bean class [" + className + "] depends on not found", ele, var14);         } catch (Throwable var15) {             this.error("Unexpected failure during bean definition parsing", ele, var15);         } finally {             this.parseState.pop();         }          return null;     }

通过对上述源码的分析,就会明白我们在Spring配置文件中<Bean>元素的中配置的属性就是通过该方法解析和设置到Bean中去的。注意:在解析<Bean>元素过程中没有创建和实例化Bean对象,只是创建了Bean对象的定义类BeanDefinition,将<Bean>元素中的配置信息设置到BeanDefinition中作为记录,当依赖注入时才使用这些记录信息创建和实例化具体的Bean对象。上面方法中一些对一些配置如元信息(meta)、qualifier等的解析,我们在Spring中配置时使用的也不多,我们在使用Spring的<Bean>元素时,配置最多的是<property>属性。

调用BeanDefinitionReaderUtils的registerBeanDefinition方法向IoC容器注册解析的Bean

 protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {         BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);         if(bdHolder != null) {             //通过对document对象的解析和封装返回一个BeanDefinitionHolder             bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);              try {                 //通过这个holder来注册bean对象                 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));         }      }

当调用BeanDefinitionReaderUtils向IoC容器注册解析的BeanDefinition时,真正完成注册功能的是DefaultListableBeanFactory。

    public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {         String beanName = definitionHolder.getBeanName();         registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());         String[] aliases = definitionHolder.getAliases();         if(aliases != null) {             String[] var4 = aliases;             int var5 = aliases.length;              for(int var6 = 0; var6 < var5; ++var6) {                 String alias = var4[var6];                 registry.registerAlias(beanName, alias);             }         }      }

DefaultListableBeanFactory registerBeanDefinition方法

  //存储注册的俄BeanDefinition  private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap(256);  //向IoC容器注册解析的BeanDefiniton  public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {         Assert.hasText(beanName, "Bean name must not be empty");         Assert.notNull(beanDefinition, "BeanDefinition must not be null");         //校验解析的BeanDefiniton         if(beanDefinition instanceof AbstractBeanDefinition) {             try {                 ((AbstractBeanDefinition)beanDefinition).validate();             } catch (BeanDefinitionValidationException var9) {                 throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var9);             }         }          BeanDefinition oldBeanDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);         if(oldBeanDefinition != null) {             if(!this.isAllowBeanDefinitionOverriding()) {                 throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + "': There is already [" + oldBeanDefinition + "] bound.");             }              if(oldBeanDefinition.getRole() < beanDefinition.getRole()) {                 if(this.logger.isWarnEnabled()) {                     this.logger.warn("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");                 }             } else if(!beanDefinition.equals(oldBeanDefinition)) {                 if(this.logger.isInfoEnabled()) {                     this.logger.info("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");                 }             } else if(this.logger.isDebugEnabled()) {                 this.logger.debug("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");             }              this.beanDefinitionMap.put(beanName, beanDefinition);         } else {             if(this.hasBeanCreationStarted()) {                 Map var4 = this.beanDefinitionMap;                 //注册的过程中需要线程同步,以保证数据的一致性                  synchronized(this.beanDefinitionMap) {                     //把bean存放到map中                     this.beanDefinitionMap.put(beanName, beanDefinition);                     List<String> updatedDefinitions = new ArrayList(this.beanDefinitionNames.size() + 1);                     updatedDefinitions.addAll(this.beanDefinitionNames);                     updatedDefinitions.add(beanName);                     this.beanDefinitionNames = updatedDefinitions;                     if(this.manualSingletonNames.contains(beanName)) {                         Set<String> updatedSingletons = new LinkedHashSet(this.manualSingletonNames);                         updatedSingletons.remove(beanName);                         this.manualSingletonNames = updatedSingletons;                     }                 }             } else {                 this.beanDefinitionMap.put(beanName, beanDefinition);                 this.beanDefinitionNames.add(beanName);                 this.manualSingletonNames.remove(beanName);             }              this.frozenBeanDefinitionNames = null;         }          if(oldBeanDefinition != null || this.containsSingleton(beanName)) {             this.resetBeanDefinition(beanName);         }      }

至此,Bean定义资源文件中配置的Bean被解析过后,已经注册到IoC容器中,被容器管理起来,真正完成了IoC容器初始化所做的全部工作。现 在IoC容器中已经建立了整个Bean的配置信息,这些BeanDefinition信息已经可以使用,并且可以被检索,IoC容器的作用就是对这些注册的Bean定义信息进行处理和维护。这些的注册的Bean定义信息是IoC容器控制反转的基础,正是有了这些注册的数据,容器才可以进行依赖注入。

本篇文章到这里就已经全部结束了,更多其他精彩内容可以关注PHP中文网的Java视频教程栏目!

以上就是Spring-IOC容器的介绍(附代码)的详细内容,更多内容请关注技术你好其它相关文章!

来源链接:
免责声明:
1.资讯内容不构成投资建议,投资者应独立决策并自行承担风险
2.本文版权归属原作所有,仅代表作者本人观点,不代表本站的观点或立场
标签: java
上一篇:php获取远程图片并下载保存到本地的方法分析 下一篇:Spring事件机制问题排查的方法介绍

相关资讯