Spring源码分析

这里写图片描述
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描述
这里写图片描述
Bean的解析非常复杂,Bean的解析主要是对Spring配置文件的解析,解析过程如图
这里写图片描述
Context组件
ApplicationContext是Context的顶级父类,除了能标识一个应用环境的基本信息,还继承了5个接口,主要是扩展了Context功能
这里写图片描述
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的结构
这里写图片描述

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初始化过程图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值