Spring源码分析

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】
免费领取10G资料包与项目实战视频资料

2019101710093\_1.png
Spring Bean的创建是典型的工厂模式,顶级接口是BeanFactory

    public interface BeanFactory {    

         //对FactoryBean的转义定义,因为如果使用bean的名字检索FactoryBean得到的对象是工厂生成的对象, 
         //如果需要得到工厂本身,需要转义 
         String FACTORY_BEAN_PREFIX = "&";

         //根据bean的名字,获取在IOC容器中得到bean实例 
         Object getBean(String name) throws BeansException;    

        //根据bean的名字和Class类型来得到bean实例,增加了类型安全验证机制。 
         Object getBean(String name, Class requiredType) throws BeansException;    

        //提供对bean的检索,看看是否在IOC容器有这个名字的bean 
         boolean containsBean(String name);    

        //根据bean名字得到bean实例,并同时判断这个bean是不是单例 
        boolean isSingleton(String name) throws NoSuchBeanDefinitionException;    

        //得到bean实例的Class类型 
        Class getType(String name) throws NoSuchBeanDefinitionException;    

        //得到bean的别名,如果根据别名检索,那么其原名也会被检索出来 
       String[] getAliases(String name);    
    }

其中BeanFactory作为最顶层的一个接口类,它定义了IOC容器的基本功能规范,BeanFactory 有三个子类:ListableBeanFactory、HierarchicalBeanFactory 和AutowireCapableBeanFactory。但是从上图中我们可以发现最终的默认实现类是 DefaultListableBeanFactory,他实现了所有的接口。那为何要定义这么多层次的接口呢?查阅这些接口的源码和说明发现,每个接口都有他使用的场合,它主要是为了区分在 Spring 内部在操作过程中对象的传递和转化过程中,对对象的数据访问所做的限制。例如 ListableBeanFactory 接口表示这些 Bean 是可列表的,而 HierarchicalBeanFactory 表示的是这些 Bean 是有继承关系的,也就是每个Bean 有可能有父 Bean。AutowireCapableBeanFactory 接口定义 Bean 的自动装配规则。这四个接口共同定义了 Bean 的集合、Bean 之间的关系、以及 Bean 行为。

Bean的定义主要由BeanDefintion描述
2019101710093\_2.png
Bean的解析非常复杂,Bean的解析主要是对Spring配置文件的解析,解析过程如图
2019101710093\_3.png
Context组件
ApplicationContext是Context的顶级父类,除了能标识一个应用环境的基本信息,还继承了5个接口,主要是扩展了Context功能
2019101710093\_4.png
Application要完成以下几件事情
1.标识一个应用环境
2.利用BeanFactory创建Bean对象
3.保存对象关系表
4.能够捕获各种对象
IOC容器是怎么工作的
1.首先是ClassPathXmlApplicationContext的构造函数

    public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
                  throws BeansException {
              super(parent);
              setConfigLocations(configLocations);
              if (refresh) {
                  refresh();
              }
         }

2.设置资源加载器和资源定位

通过分析ClassPathXmlApplicationContext 的源代码可以知道,在创建ClassPathXmlApplicationContext 容器时,构造方法做以下两项重要工作:
首先,调用父类容器的构造方法(super(parent)方法)为容器设置好Bean资源加载器。
然后,再调用父类AbstractRefreshableConfigApplicationContext的setConfigLocations(configLocations)方法设置Bean定义资源文件的定位路径。
通过追踪ClassPathXmlApplicationContext 的继承体系,发现其父类的父类AbstractApplicationContext中初始化IoC容器所做的主要源码如下:

    public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext, DisposableBean {  
        //静态初始化块,在整个容器创建过程中只执行一次 
        static {  
            //为了避免应用程序在Weblogic8.1关闭时出现类加载异常加载问题,加载IoC容器关闭事件(ContextClosedEvent)类 
            ContextClosedEvent.class.getName();  
        }  
        //FileSystemXmlApplicationContext调用父类构造方法调用的就是该方法 
        public AbstractApplicationContext(ApplicationContext parent) {  
            this.parent = parent;  
            this.resourcePatternResolver = getResourcePatternResolver();  
        }  
        //获取一个Spring Source的加载器用于读入Spring Bean定义资源文件 
        protected ResourcePatternResolver getResourcePatternResolver() {  
            // AbstractApplicationContext继承DefaultResourceLoader,也是一个Spring资源加载器,其getResource(String location)方法用于载入资源 
            return new PathMatchingResourcePatternResolver(this);  
        }   
    }

AbstractApplicationContext构造方法中调用PathMatchingResourcePatternResolver的构造方法创建Spring资源加载器:

    public PathMatchingResourcePatternResolver(ResourceLoader resourceLoader) {
              Assert.notNull(resourceLoader, "ResourceLoader must not be null");
              this.resourceLoader = resourceLoader;
         }

设置容器后,执行setConfigLocations()方法,通过调用父类中的方法, 进行对Bean定义资源文件的定位

处理单个资源文件路径为一个字符串的情况

    public void setConfigLocation(String location) {
    setConfigLocations(StringUtils.tokenizeToStringArray(location, CONFIG_LOCATION_DELIMITERS));
    }

解析Bean定义资源文件的路径,处理多个资源文件字符串数组

    public void setConfigLocations(String... locations) {
    if (locations != null) {
    Assert.noNullElements(locations, "Config locations must not be null");
    this.configLocations = new String[locations.length];
    for (int i = 0; i < locations.length; i++) {
    // resolvePath为同一个类中将字符串解析为路径的方法
    this.configLocations[i] = resolvePath(locations[i]).trim();
    }
    }
    else {
    this.configLocations = null;
    }
    }

这里的refresh()方法是在AbstractApplicationContext中,refresh()方法是Spring IOC容器对Bean定义资源的载入的开始

    public void refresh() throws BeansException, IllegalStateException {
              synchronized (this.startupShutdownMonitor) {
                  // 为刷新准备的context
                  prepareRefresh();
                  //告诉子类刷新内部BeanFactory
                  ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
                  // 为beanFactory配置容器属性
                  prepareBeanFactory(beanFactory);
                  try {
                        // 为容器的某些子类指定特殊的BeanPost事件处理器
                       postProcessBeanFactory(beanFactory);
                       // 调用所有注册BeanFactoryPostProcessor 的bean
                       invokeBeanFactoryPostProcessors(beanFactory);
                       // 为BeanFactory注册BeanPost事件处理器.
                       registerBeanPostProcessors(beanFactory);
                       // 初始化信息源
                       initMessageSource();
                       // 初始化事件传播器
                       initApplicationEventMulticaster();
                       // 刷新其他由子类实现的方法
                       onRefresh();
                       // 检查并注册
                       registerListeners();
                       //初始化所有的non-lazy-init) 单例
                       finishBeanFactoryInitialization(beanFactory);
                       // 最后一步:发布事件
                       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.构建BeanFactory,以便产生所需的“演员”
2.注册可能感兴趣的事件
3.创建Bean实例对象
4.触发被监听的事件
refresh这个方法包含了整个BeanFactory初始化的过程,定位资源由obtainFreshBeanFactory()来完成
obtainFreshBeanFactory

     protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
              refreshBeanFactory();
              ConfigurableListableBeanFactory beanFactory = getBeanFactory();
              if (logger.isDebugEnabled()) {
                  logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
              }
              return beanFactory;
         }

可以看到其调用了refreshBeanFactory(),refreshBeanFactory()在这个类中是抽象方法,其实现在AbstractRefreshableApplicationContext中。
代码如下
refreshBeanFactory

    protected final void refreshBeanFactory() throws BeansException {
              if (hasBeanFactory()) {//如果有容器销毁容器中的bean,关闭容器
                  destroyBeans();
                  closeBeanFactory();
              }
              try {
                  //创建IOC容器
                  DefaultListableBeanFactory beanFactory = createBeanFactory();
                  beanFactory.setSerializationId(getId());
                  //对容器定制化,如启动参数,开启注解的自动装配等等
                  customizeBeanFactory(beanFactory);、
                  //调用载入bean定义的方法
                  loadBeanDefinitions(beanFactory);
                  synchronized (this.beanFactoryMonitor) {
                       this.beanFactory = beanFactory;
                  }
              }
              catch (IOException ex) {
                  throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
              }
         }

在这个方法中,先判断BeanFactory是否存在,如果存在则先销毁beans并关闭beanFactory,接着创建DefaultListableBeanFactory,并调用loadBeanDefinitions(beanFactory)装载bean定义。loadBeanDefinitions方法同样是抽象方法,是由其子类实现的,也即在AbstractXmlApplicationContext中。

    public abstract class AbstractXmlApplicationContext extends AbstractRefreshableConfigApplicationContext {
         @Override
         protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
              // 使用xmlBeanDefinitionReader 来载入bean定义信息的XML文件
              XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

              // 配置reader的环境
              beanDefinitionReader.setEnvironment(this.getEnvironment());
              // 设置Spring资源加载器
              beanDefinitionReader.setResourceLoader(this);
              //设置SAX XML解析器
              beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
              //当Bean读取器读取Bean定义的XML资源文件时,启用XML校验机制
              initBeanDefinitionReader(beanDefinitionReader);
              // 这里转到定义好的XmlBeanDefinitionReader中对载入bean信息进行处理
              loadBeanDefinitions(beanDefinitionReader);
         }
    }

再转到beanDefinitionReader中进行处理

    protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
              //获取Bean定义资源的定位
              Resource[] configResources = getConfigResources();
              if (configResources != null) {
                 //调用XmlBeanDefinitionReader来载入bean定义信息
                   reader.loadBeanDefinitions(configResources);
              }
              //如果子类中获取的Bean定义资源定位为空,则获取ClassPathXmlApplicationContext构造方法中setConfigLocations方法设置的资源
              String[] configLocations = getConfigLocations();
              if (configLocations != null) {
                   reader.loadBeanDefinitions(configLocations);
              }
         }

BeanDefinitionReader的结构
2019101710093\_5.png

    public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
    Assert.notNull(resources, "Resource array must not be null");
    int counter = 0;
    Resource[] var3 = resources;
    int var4 = resources.length;

    for(int var5 = 0; var5 < var4; ++var5) {
    Resource resource = var3[var5];
    counter += this.loadBeanDefinitions((Resource)resource);
    }
    return counter;
    }

在XmlBeanDefinitionReader

    public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
    return this.loadBeanDefinitions(new EncodedResource(resource));
    }

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

    public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {
              ResourceLoader resourceLoader = getResourceLoader(); //这里得到当前定义的ResourceLoader,默认是使用DefaultResourceLoader
              if (resourceLoader == null) { //如果没有找到需要的ResourceLoader,直接抛出异常
                  throw new BeanDefinitionStoreException(
                            "Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
              }
              if (resourceLoader instanceof ResourcePatternResolver) {
                  // 处理我们在定义位置时使用的各种pattern,需要 ResourcePatternResolver来完成
                  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 {
                   // 这里通过ResourceLoader来完成位置定位
                  Resource resource = resourceLoader.getResource(location);
                   // 这里已经把一个位置定义转化为Resource接口,可以供XmlBeanDefinitionReader来使用了
                  int loadCount = loadBeanDefinitions(resource);
                  if (actualResources != null) {
                       actualResources.add(resource);
                  }
                  if (logger.isDebugEnabled()) {
                       logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
                  }
                  return loadCount;
              }
         }

可以知道此时调用的是DefaultResourceLoader中的getSource()方法定位Resource,因为ClassPathXmlApplicationContext本身就是DefaultResourceLoader的实现类,所以此时又回到了ClassPathXmlApplicationContext中来

    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 {
                   //这里通过Resource得到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();
                  }
              }
         }

doLoadBeanDefinitions()先把定义文件解析为DOM对象,然后进行具体的注册过程

    protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
                  throws BeanDefinitionStoreException {
              try {
                 //通过解析得到DOM,然后完成bean在IOC容器中的注册
                  Document doc = doLoadDocument(inputSource, resource);
                  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);
              }
         }
    //使用标准的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 DocumentBuilder createDocumentBuilder(DocumentBuilderFactory factory, EntityResolver entityResolver, ErrorHandler errorHandler) throws ParserConfigurationException {
    //创建文档解析工厂
    DocumentBuilder docBuilder = factory.newDocumentBuilder();
    //设置解析XML的校验
    if (entityResolver != null) {
    docBuilder.setEntityResolver(entityResolver);
    }

    if (errorHandler != null) {
    docBuilder.setErrorHandler(errorHandler);
    }

    return docBuilder;
    }

具体的注册过程registerBeanDefinitions

    public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
              // 首先得到XmlBeanDefinitionDocumentReader来处理xml的bean定义文件
              BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
    //获取容器中注册的bean的数量
              int countBefore = getRegistry().getBeanDefinitionCount();
              //调用注册方法
              documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
              return getRegistry().getBeanDefinitionCount() - countBefore;
         }
    //创建BeanDefinitionDocumentReader对象,解析Document对象
    protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {
    return BeanDefinitionDocumentReader.class.cast(BeanUtils.instantiateClass(this.documentReaderClass));
    }

具体的过程在BeanDefinitionDocumentReader类中完成,在DefaultBeanDefinitionDocumentReader的方法中完成bean定义文件的解析和IOC容器中bean的初始化。

    @Override
         public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
              this.readerContext = readerContext;
              logger.debug("Loading bean definitions");
    //获得Document的根元素
              Element root = doc.getDocumentElement();
    //具体的解析
              doRegisterBeanDefinitions(root);
         }
    protected void doRegisterBeanDefinitions(Element root) {
               //通过代理delegate解析
              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;
         }

使用Spring的Bean规则从Document的根元素开始进行Bean定义的Document对象

    protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
    //Bean定义的Document对象使用了Spring默认的XML命名空间 
    if (delegate.isDefaultNamespace(root)) {
                 //得到xml文件的子节点,比如各个bean节点
                  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)) {
                           //这里是解析过程的调用,对缺省的元素进行分析比如bean元素
                                 parseDefaultElement(ele, delegate);
                            }
                            else {
                 //没有使用Spring默认的XML命名空间,则使用用户自定义的解析规则解析元素节点
                                 delegate.parseCustomElement(ele);
                            }
                       }
                  }
              }
              else {
    //Document的根节点没有使用Spring默认的命名空间,则使用用户自定义的解析规则解析元素节点
                  delegate.parseCustomElement(root);
              }
         }
    private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
    //如果元素节点是<import>导入元素,进行导入解析
    if (delegate.nodeNameEquals(ele, "import")) {
    this.importBeanDefinitionResource(ele);
    }
    //如果元素节点是<alias >别名元素,进行别名解析
      else if (delegate.nodeNameEquals(ele, "alias")) {
    this.processAliasRegistration(ele);
    }
     //如果元素节点是普通<bean>元素,按照Spring的Bean规则解析元素
    else if (delegate.nodeNameEquals(ele, "bean")) {
    this.processBeanDefinition(ele, delegate);
    } else if (delegate.nodeNameEquals(ele, "beans")) {
    this.doRegisterBeanDefinitions(ele);
    }
    }

解析Bean定义资源Documnet对象的普通元素

    protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
    //BeanDefinitionHolder是对BeanDefinitionParserDelegate实现,
    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));
    }

BeanDefinitionParserDelegate解析Bean定义资源文件中的<Bean>元素

    //解析Bean元素的入口
    public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
    return this.parseBeanDefinitionElement(ele, (BeanDefinition)null);
    }
    //解析Bean定义资源文件中的<Bean>元素,这个方法中主要处理<Bean>元素的id,name和别别名
    public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
    //获取<Bean>元素中的id属性值
    String id = ele.getAttribute("id");
    //获取<Bean>元素中的name属性值
    String nameAttr = ele.getAttribute("name");
    //获取<Bean>元素中的alias属性值
    List<String> aliases = new ArrayList();
    //将<Bean>元素中的所有name属性值存放到别名中
    if (StringUtils.hasLength(nameAttr)) {
    String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, ",; ");
    aliases.addAll(Arrays.asList(nameArr));
    }

    String beanName = id;
    //如果<Bean>元素中没有配置id属性,将别名中的第一个值赋值给beanName
    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");
    }
    }
    //检查<Bean>元素所配置的id或者name的唯一性,containingBean标识<Bean>元素中是否包含子<Bean>元素
    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) {
    //如果<Bean>元素中没有配置id,别名或者name,且没有包含子<Bean>元素,为解析的Bean生成一个唯一的beanName并注册
    beanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, this.readerContext.getRegistry(), true);
    } else {
    //如果<Bean>元素中没有配置id,别名或者name,且包含了子<Bean>元素,为解析的Bean使用别名向IOC容器注册
    beanName = this.readerContext.generateBeanName(beanDefinition);
    //为解析的Bean使用别名注册时,为兼容,。给别名添加类名后缀
    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 {
    //解析出错返回Null
    return null;
    }
    }

    //详细对<Bean>元素中配置的Bean定义其他属性进行解析
    public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean) {
    //记录解析的<Bean>
    this.parseState.push(new BeanEntry(beanName));
    //制度去<Bean>元素中配置的class名字,然后载入到BeanDefinition中,知识记录配置的class名字,不做实例化,对象的实例化在依赖注入时完成
    String className = null;
    if (ele.hasAttribute("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>元素中配置的一些属性进行解析和设置,如配置的单例属性等
    this.parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
    //为<Bean>元素解析的Bean设置description信息
    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);
    //为当前解析的Bean设置所需的资源和依赖对象
    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();
    }
    //解析<Bean>元素出错时,返回null
    return null;
    }

BeanDefinitionParserDelegate解析<property>元素:

    //解析<Bean>元素中的<property子元素>
    public void parsePropertyElements(Element beanEle, BeanDefinition bd) {
    //获取<Bean>元素中子元素
    NodeList nl = beanEle.getChildNodes();

    for(int i = 0; i < nl.getLength(); ++i) {
    Node node = nl.item(i);
    //如果这个子元素是<property>子元素,则调用parsePropertyElement方法解析
    if (this.isCandidateElement(node) && this.nodeNameEquals(node, "property")) {
    this.parsePropertyElement((Element)node, bd);
    }
    }
    }
    public void parsePropertyElement(Element ele, BeanDefinition bd) {
    //取<property>的name
    String propertyName = ele.getAttribute("name");
    if (!StringUtils.hasLength(propertyName)) {
    this.error("Tag 'property' must have a 'name' attribute", ele);
    } else {
    this.parseState.push(new PropertyEntry(propertyName));
    try {
    //只有一个Bean中没有同名的property存在,才进行解析
    if (!bd.getPropertyValues().contains(propertyName)) {
    //解析获取property的值
    Object val = this.parsePropertyValue(ele, bd, propertyName);
    //根据property的name和val创建property实例
    PropertyValue pv = new PropertyValue(propertyName, val);
    //解析<property>元素中的属性
    this.parseMetaElements(ele, pv);
    pv.setSource(this.extractSource(ele));
    bd.getPropertyValues().addPropertyValue(pv);
    return;
    }
    this.error("Multiple 'property' definitions for property '" + propertyName + "'", ele);
    } finally {
    this.parseState.pop();
    }
    }
    }

    //解析获取property的值
    public Object parsePropertyValue(Element ele, BeanDefinition bd, String propertyName) {
    String elementName = propertyName != null ? "<property> element for property '" + propertyName + "'" : "<constructor-arg> element";
    //获取<property>所有的子元素
    NodeList nl = ele.getChildNodes();
    Element subElement = null;
    for(int i = 0; i < nl.getLength(); ++i) {
    Node node = nl.item(i);
    //子元素不是description和meta属性
    if (node instanceof Element && !this.nodeNameEquals(node, "description") && !this.nodeNameEquals(node, "meta")) {
    if (subElement != null) {
    this.error(elementName + " must not contain more than one sub-element", ele);
    } else {
    //当前<property>元素包含有子元素
    subElement = (Element)node;
    }
    }
    }
    //判断property的属性值是ref还是value,不允许既是ref又是value
    boolean hasRefAttribute = ele.hasAttribute("ref");
    boolean hasValueAttribute = ele.hasAttribute("value");
    if (hasRefAttribute && hasValueAttribute || (hasRefAttribute || hasValueAttribute) && subElement != null) {
    this.error(elementName + " is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele);
    }
    //如果是ref,创建一个RuntimeBeanReference对象,这个对象封装了ref信息
    if (hasRefAttribute) {
    String refName = ele.getAttribute("ref");
    if (!StringUtils.hasText(refName)) {
    this.error(elementName + " contains empty 'ref' attribute", ele);
    }
    //一个指向运行时所依赖对象的引用
    RuntimeBeanReference ref = new RuntimeBeanReference(refName);
    //设置这个ref的数据对象是被当前的property对象所引用
    ref.setSource(this.extractSource(ele));
    return ref;
    }
    //如果是value,创建一个TypedStringValue对象
      else if (hasValueAttribute) {
    //一个持有String类型值的对象
    TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute("value"));
    //设置这个value数据对象是被当前的property对象所引用
    valueHolder.setSource(this.extractSource(ele));
    return valueHolder;
    }
    //如果当前<property>元素还有子元素
    else if (subElement != null) {
    //解析<property子元素>
    return this.parsePropertySubElement(subElement, bd);
    } else {
    //解析出错返回null
    this.error(elementName + " must specify a ref or value", ele);
    return null;
    }
    }

在Spring配置文件中,元素中元素的相关配置是这样处理的
1.ref被封装为指向依赖对象的一个引用
2.value配置都会封装成一个字符串类型的对象
3.ref和value都通过 解析的数据类型属性值.setSource(extractSource(ele)); 这个方法将属性值(引用)与所引用的属性关联起来

继续来看在BeanDefinitionPareserDelegate类中的paresePropertySubElement方法对中的子元素解析

    public Object parsePropertySubElement(Element ele, BeanDefinition bd) {
    return this.parsePropertySubElement(ele, bd, (String)null);
    }
    //解析<property>元素中的ref,value或者集合等子元素
    public Object parsePropertySubElement(Element ele, BeanDefinition bd, String defaultValueType) {
    //如果<property>没有使用Spring默认的命名空间则使用用户自定义的规则解析内嵌元素
    if (!this.isDefaultNamespace((Node)ele)) {
    return this.parseNestedCustomElement(ele, bd);
    } 
    //如果子元素是bean,则使用<Bean>元素的方法解析
    else if (this.nodeNameEquals(ele, "bean")) {
    BeanDefinitionHolder nestedBd = this.parseBeanDefinitionElement(ele, bd);
    if (nestedBd != null) {
    nestedBd = this.decorateBeanDefinitionIfRequired(ele, nestedBd, bd);
    }
    return nestedBd;
    }
    //如果子元素是ref,ref中只能有3个属性:bean,local,parent 
    else if (this.nodeNameEquals(ele, "ref")) {
    //获取<property>元素中的bean属性值,引用其他解析的Bean的名称,可以不在同一个Spring配置文件中,参考Spring对ref的配置规则
    String refName = ele.getAttribute("bean");
    boolean toParent = false;
    if (!StringUtils.hasLength(refName)) {
    //获取<property>中的local属性值,引用同一个XML文件中配置的Bean的id,local和ref不同,local只能引用同一个配置文件中Bean
    refName = ele.getAttribute("local");
    if (!StringUtils.hasLength(refName)) {
    //获取<property>元素中parent属性值,引用父级容器中的Bean
    refName = ele.getAttribute("parent");
    toParent = true;
    if (!StringUtils.hasLength(refName)) {
    this.error("'bean', 'local' or 'parent' is required for <ref> element", ele);
    return null;
    }
    }
    }
    //没有配置ref的目标属性值
    if (!StringUtils.hasText(refName)) {
    this.error("<ref> element contains empty target attribute", ele);
    return null;
    } else {
    //创建ref类型数据,指向被引用的对象
    RuntimeBeanReference ref = new RuntimeBeanReference(refName, toParent);
    //设置用用类型值是被当前子元素所引用
    ref.setSource(this.extractSource(ele));
    return ref;
    }
    }
     //如果子元素是<idref>,使用解析ref元素的方法解析
    else if (this.nodeNameEquals(ele, "idref")) {
    return this.parseIdRefElement(ele);
    }
     //如果子元素是<value>,使用解析value元素的方法解析 
    else if (this.nodeNameEquals(ele, "value")) {
    return this.parseValueElement(ele, defaultValueType);
    } 
    //如果子元素是null,为<property>设置一个封装null值的字符串数据 
    else if (this.nodeNameEquals(ele, "null")) {
    TypedStringValue nullHolder = new TypedStringValue((String)null);
    nullHolder.setSource(this.extractSource(ele));
    return nullHolder;
    } 
     //如果子元素是<array>,使用解析arry集合子元素的方法解析 
    else if (this.nodeNameEquals(ele, "array")) {
    return this.parseArrayElement(ele, bd);
    } 
    else if (this.nodeNameEquals(ele, "list")) {
    return this.parseListElement(ele, bd);
    } else if (this.nodeNameEquals(ele, "set")) {
    return this.parseSetElement(ele, bd);
    } else if (this.nodeNameEquals(ele, "map")) {
    return this.parseMapElement(ele, bd);
    } else if (this.nodeNameEquals(ele, "props")) {
    return this.parsePropsElement(ele);
    } else {
    this.error("Unknown property sub-element: [" + ele.getNodeName() + "]", ele);
    return null;
    }
    }

在Spring配置文件中,对<property>元素中配置的Array,List,Set,Map,Prop等各种集合子元素的都通过上述方法解析,生成对应的数据对象, 比如ManagedList、ManagedArray、ManagedSet等,这些Managed类是Spring对象BeanDefinition的数据封装,对集合数据类型的具体解析有各自的解析方法实现,解析方法的命名规范,下面对<list>集合元素的解析方法进行源码分析,了解其实现过程


    解析<list>结合子元素
    public List<Object> parseListElement(Element collectionEle, BeanDefinition bd) {
    //获取<list>元素中的value-type属性,即获取集合元素的数据类型
    String defaultElementType = collectionEle.getAttribute("value-type");
    //获取<list>集合元素中的所有子节点
    NodeList nl = collectionEle.getChildNodes();
    //Spring中将List封装为ManagedList
    ManagedList<Object> target = new ManagedList(nl.getLength());
    target.setSource(this.extractSource(collectionEle));
    //设置集合目标数据类型
    target.setElementTypeName(defaultElementType);
    target.setMergeEnabled(this.parseMergeAttribute(collectionEle));
    //具体的<list>元素解析
    this.parseCollectionElements(nl, target, bd, defaultElementType);
    return target;
    }
    //具体解析<list>集合元素,<array>、<list>和<set>都使用该方法解析
    protected void parseCollectionElements(NodeList elementNodes, Collection<Object> target, BeanDefinition bd, String defaultElementType) {
    //遍历集合所有节点
    for(int i = 0; i < elementNodes.getLength(); ++i) {
    Node node = elementNodes.item(i);
    //如果节点不是description节点
    if (node instanceof Element && !this.nodeNameEquals(node, "description")) {
    //将解析的元素加入集合中,递归调用下一个元素
    target.add(this.parsePropertySubElement((Element)node, bd, defaultElementType));
    }
    }
    }

经过对Spring Bean定义资源文件转换的Document对象中的元素层层解析,Spring IOC已经将XML形式定义的Bean定义资源文件转换为Spring Ioc所识别的数据结构 :BeanDefinition,是Bean定义资源文件中配置的POJO对象在Spring IOC 容器中的映射,可以通过AbstractBeanDefinition为入口,对IOC容器进行索引,查询和操作
通过Spring IOC容器对Bean定义资源的解析后,IOC容器大致完成了管理Bean对象的准备工作,就是初始化过程,但是最重要的依赖注入还没有发生,现在在IOC容器中BeanDefinition存储的只是一些静态信息,接下来需要向容器注册Bean定义信息才能全部完成Ioc容器的初始化过程

解析过后的BeanDefinition在IOC容器中的注册
在DefaultBeanDeifinitionDocumnetReader对Bean定义转换的Document对象解析的流程中,在其 parseDefaultElement方法中完成对Document对象解析后得到封装BeanDefinition的BeanDefinitionHold对象,然后调用BeanDefinitionReaderUtils的registerBeanDefinition方法想IOC容器注册解析的Bean,方法源码如下

    //将解析的BeanDefinitionHold注册到容器中
    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) {
    String[] var4 = aliases;
    int var5 = aliases.length;
    for(int var6 = 0; var6 < var5; ++var6) {
    String alias = var4[var6];
    registry.registerAlias(beanName, alias);
    }
    }
    }

当调用registerBeanDefinition这个方法向IOC容器注册解析的BeanDefinition时,追踪发现完成注册功能的是DefaultListableBeanFactory

    //存储注册的BeanDefinition
    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap(256);

    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");
    //校验解析的BeanDefinition
    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);
    //检查是否有同名的BeanDefinition已经在IOC容器中注册,如果已经注册,并不允许覆盖已经注册的Bean,则注册失败
    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保持数据的一致性
    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;
    if (this.manualSingletonNames.contains(beanName)) {
    Set<String> updatedSingletons = new LinkedHashSet(this.manualSingletonNames);
    updatedSingletons.remove(beanName);
    this.manualSingletonNames = updatedSingletons;
    }
    }
    } else {
    //注册过程
    //注册BeanDefinition,将解析后BeanDefinition放入Map,key为Bean name,value为BeanDefinition对象
    this.beanDefinitionMap.put(beanName, beanDefinition);
    this.beanDefinitionNames.add(beanName);
    this.manualSingletonNames.remove(beanName);
    }

    this.frozenBeanDefinitionNames = null;
    }

    if (oldBeanDefinition != null || this.containsSingleton(beanName)) {
    //重置所有已经注册过的BeanDefinition的缓存
    this.resetBeanDefinition(beanName);
    }
    }

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


来源:[]()

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » Spring源码分析

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏