Spring ioc源码分析

Spring源码分析

核心容器类图

BeanFactory

​ 是典型的工厂模式,为ioc容器开发者管理对象之间的依赖关系提供了很多遍历和基础服务。

Spring ioc源码分析_第1张图片

用的比较多的beanfactory

FileSystemXmlApplicationContext

ListableBeanFactory

接口表示这些 Bean 是可列表化的

HierarchicalBeanFactory

这些 Bean 是有继承关系的,也就是每个 Bean 有可能有父 Bean

AutowireCapableBeanFactory

定义 Bean 的自动装配规则

Spring ioc源码分析_第2张图片

工厂生产对象

​ Spring有很多IOC容器实现。ApplicationContext是Spring提供的一个高级的IOC容器。

  • GenericApplicationContext
  • ClasspathApplicationContext

通过其接口实现可看出其特点:

  • 支持信息源,可以实现国际化。(实现 MessageSource 接口)
  • 访问资源。(实现 ResourcePatternResolver 接口)
  • 支持应用事件。(实现 ApplicationEventPublisher 接口)

BeanDefinition

​ SpringIOC容器管理了我们定义的各种Bean对象及其相互的关系,Bean对象在Spring中是通过BeanDefinition来描述的

Spring ioc源码分析_第3张图片

BeanDefinitionReader

用来读取配置文件信息

Spring ioc源码分析_第4张图片

初始化

定位: 定位配置文件和扫描相关的注解

加载: 把配置信息载入到内存中

注册: 根据载入的信息,把对象初始化到IOC容器中

基于Xml的IOC容器初始化

​ IOC容器的初始化包括BeanDefinition的Resource定位,加载和注册这三个基本过程。我们从ApplicationContext为例切入,ApplicationContext系列容器或许使我们最熟悉的,因为Web项目中使用的XmlWebApplicationContext就属于此基础体系,还有ClasspathXmlApplicationContext等,继承体系如下所示:

Spring ioc源码分析_第5张图片

​ ApplicationContext允许上下文嵌套,通过保持其父上下文可以维持一个上下文体系,对于Bean查找可以在此上下文体系中发生,首先检查上下文,期次是父上下文,逐级向上,这样为不同的Spring应用提供了一个共享额Bean定义环境。

1、寻找入口

​ 有一个我们用的比较多的ClaassPathXmlApplicationContext通过main()方法启动:

ApplicationContext app =new ClassPathXmlApplicationContext("application.xml");

​ 先看其构造函数的调用:​

public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
   this(new String[] {configLocation}, true, null);
}

其实际调用的构造函数为

public ClassPathXmlApplicationContext(
      String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
      throws BeansException {

   super(parent);
   setConfigLocations(configLocations);
   if (refresh) {
      refresh();
   }
}

还有像AnnotationConfigApplicationContextFileSystemXmlApplicationContextXmlWebApplicationContext等都继承自父容器AbstractApplicationContext主要用到了装饰器模式和策略模式,最终都是调用refresh()方法

2、获得配置路径

​ 通过分析ClassPathXmlApplicationContext的源代码可以知道,在创建ClassPathXmlApplicationContext容器时,构造方法做一下两个操作:

​ 首先调用父类容器的构造方法为容器设置好Bean资源加载器。

​ 然后,调用父类AbstractRefreshableConfigApplicationContextsetConfigLocations(configLocations) 方法设置Bean配置信息的定位路径。

​ 通过追踪ClassPathXmlApplicationContext的继承体系,发现其父类的父AbstractApplicationContext中初始化IOC容器所做的主要源码如下:

public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
  //静态初始化块,在整个容器创建过程中只执行一次 
  static {
    //为了避免应用程序在 Weblogic8.1 关闭时出现类加载异常加载问题,加载 IOC 容器关闭事件(ContextClosedEvent)类 
    ContextClosedEvent.class.getName();
  }
  public AbstractApplicationContext() {
    this.resourcePatternResolver = getResourcePatternResolver();
  }
  public AbstractApplicationContext(@Nullable ApplicationContext parent) { 
    this();
    setParent(parent);
  }
  //获取一个 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"); //设置 Spring 的资源加载器
  this.resourceLoader = resourceLoader;
}

​ 在设置容器的资源加载器之后,接下来ClassPathXmlApplicationContext执行setConfigLocation的方法通过调用其父类AbstractRefreshableConfigApplicationContext的方法进行对Bean配置信息的定位,该方法的源码如下

/**
* Set the config locations for this application context in init-param style, * i.e. with distinct locations separated by commas, semicolons or whitespace. * 

If not set, the implementation may use a default as appropriate. */ //处理单个资源文件路径为一个字符串的情况 public void setConfigLocation(String location) { //String CONFIG_LOCATION_DELIMITERS = ",; /t/n"; //即多个资源文件路径之间用” ,; \t\n”分隔,解析成数组形式 setConfigLocations(StringUtils.tokenizeToStringArray(location, CONFIG_LOCATION_DELIMITERS)); } /** * Set the config locations for this application context. *

If not set, the implementation may use a default as appropriate. */ //解析 Bean 定义资源文件的路径,处理多个资源文件字符串数组 public void setConfigLocations(@Nullable 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; } }

​ 通过这两个方法的源码我们可以看出,我们既可以使用一个字符串来配置多个Spring Bean配置信息,也可以使用字符串数组,,即下面两种方式都是可以的:

ClassPathResouce res=new ClassPathResource("a.xml,b.xml")

多个资源文件路径之间可以用",;\t\n"等分隔

ClassPathResource res =new ClassPathResource(new String[]{"a.xml","b.xml"});

至此,SpringIOC容器在初始化时将配置的Bean配置信息定位为Spring封装的Resource.

3、开始启动

​ SpringIOC容器对Bean配置资源的载入是从refresh()函数开始的,refresh()是一个模板方法,规定了IOC容器的启动流程,有些逻辑要交给其子类去实现。它对Bean配置资源进行载入ClassPathXmlApplicationContext通过调用其父类AbstractApplicationContextrefresh()函数启动整个IOC容器对Bean定义的载入过程,现在我们来详细看看refresh()中的逻辑处理:

public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {
@Override
public void refresh() throws BeansException, IllegalStateException { 
  synchronized (this.startupShutdownMonitor) {

    // Prepare this context for refreshing. 
    //1、调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识 
    prepareRefresh();

    // Tell the subclass to refresh the internal bean factory. 
    //2、告诉子类启动 refreshBeanFactory()方法,Bean 定义资源文件的载入从子类的 refreshBeanFactory()方法启动
    ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

    // Prepare the bean factory for use in this context.
    //3、为 BeanFactory 配置容器特性,例如类加载器、事件处理器等 
    prepareBeanFactory(beanFactory);
    try {

      // Allows post-processing of the bean factory in context subclasses.
      //4、为容器的某些子类指定特殊的 BeanPost 事件处理器 
      postProcessBeanFactory(beanFactory);

      // Invoke factory processors registered as beans in the context. 
      //5、调用所有注册的 BeanFactoryPostProcessor 的 Bean 
      invokeBeanFactoryPostProcessors(beanFactory);

      // Register bean processors that intercept bean creation. 
      //6、为 BeanFactory 注册 BeanPost 事件处理器. 
      //BeanPostProcessor 是 Bean 后置处理器,用于监听容器触发的事件 
      registerBeanPostProcessors(beanFactory);

      // Initialize message source for this context. 
      //7、初始化信息源,和国际化相关. 
      initMessageSource();

      // Initialize event multicaster for this context. 
      //8、初始化容器事件传播器. 
      initApplicationEventMulticaster();

      // Initialize other special beans in specific context subclasses.
      //9、调用子类的某些特殊 Bean 初始化方法
      onRefresh();

      // Check for listener beans and register them.
      //10、为事件传播器注册事件监听器.
      registerListeners();

      // Instantiate all remaining (non-lazy-init) singletons. 
      //11、初始化所有剩余的单例 Bean 
      finishBeanFactoryInitialization(beanFactory);

      // Last step: publish corresponding event. 
      //12、初始化容器的生命周期事件处理器,并发布容器的生命周期事件 
      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. 
      //13、销毁已创建的 Bean
      destroyBeans();

      // Reset 'active' flag.
      //14、取消 refresh 操作,重置容器的同步标识. 
      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... 
      //15、重设公共缓存
      resetCommonCaches();
    }
  }
}
	/**
	 * Prepare this context for refreshing, setting its startup date and
	 * active flag as well as performing any initialization of property sources.
	 */
	protected void prepareRefresh() {
		this.startupDate = System.currentTimeMillis();
		this.closed.set(false);
		this.active.set(true);

		if (logger.isInfoEnabled()) {
			logger.info("Refreshing " + this);
		}

		// Initialize any placeholder property sources in the context environment
		initPropertySources();

		// Validate that all properties marked as required are resolvable
		// see ConfigurablePropertyResolver#setRequiredProperties
		getEnvironment().validateRequiredProperties();

		// Allow for the collection of early ApplicationEvents,
		// to be published once the multicaster is available...
		this.earlyApplicationEvents = new LinkedHashSet<>();
	}
}

​ refresh()方法主要为IOC容器Bean的生命周期管理提供条件,Spring IOC容器载入Bean配置信息,从其子类容器的refreshBeanFactory()方法启动,所以整个refresh()

    ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

这句话之后,代码的都是注册容器的信息源和生命周期时间,我们前面说的载入就是从这句代码开始启动。

refresh()方法的主要作用是:在注册IOC容器前,如果已经有容器存在,则需要把已有的容器销毁和关闭,以保障在refresh之后使用的是新建立起来的IOC容器。它类似于对IOC容器的重启,在新建立好的容器中对容器进行初始化,对Bean配置资源进行载入。

4、创建容器

ObtainFreshBeanFactory()方法调用子类容器refreshBeanFactory()方法,启动容器载入Bean配置信息的过程,代码如下:

public abstract class AbstractApplicationContext extends DefaultResourceLoader
            implements ConfigurableApplicationContext {

	protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
      //这里使用了委派设计模式,父类定义了抽象的 refreshBeanFactory()方法,具体实现调用子类容器的 refreshBeanFactory()方法
      refreshBeanFactory();

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

AbstractApplicationContext中只抽象定义了refreshBeanFactory()方法,容器真正调用的是其子类AbstractRefreshableApplicationContext实现的refreshBeanFactory()方法,方法的源代码如下

public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {
  /**
	 * This implementation performs an actual refresh of this context's underlying
	 * bean factory, shutting down the previous bean factory (if any) and
	 * initializing a fresh bean factory for the next phase of the context's lifecycle.
	 */
  @Override
  protected final void refreshBeanFactory() throws BeansException {
    //如果已经有容器,销毁容器中的bean,关闭容器
    if (hasBeanFactory()) {
      destroyBeans();
      closeBeanFactory();
    }
    try {
      //创建IOC容器
      DefaultListableBeanFactory beanFactory = createBeanFactory();
      beanFactory.setSerializationId(getId());
      //对IOC容器进行定制化,如设置启动参数,开启注解的自动装配等
      customizeBeanFactory(beanFactory);
      //调用载入Bean定义的方法,主要这里又使用了一个委派模式,在当前类中只定义了抽象的loadBeanDefinitions方法,具体的实现调用子类容器
      loadBeanDefinitions(beanFactory);
      synchronized (this.beanFactoryMonitor) {
        this.beanFactory = beanFactory;
      }
    }
    catch (IOException ex) {
      throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    }
  }
  protected DefaultListableBeanFactory createBeanFactory() {
    return new DefaultListableBeanFactory(getInternalParentBeanFactory());
  }
  /**
	 * Customize the internal bean factory used by this context.
	 * Called for each {@link #refresh()} attempt.
	 * 

The default implementation applies this context's * {@linkplain #setAllowBeanDefinitionOverriding "allowBeanDefinitionOverriding"} * and {@linkplain #setAllowCircularReferences "allowCircularReferences"} settings, * if specified. Can be overridden in subclasses to customize any of * {@link DefaultListableBeanFactory}'s settings. * @param beanFactory the newly created bean factory for this context * @see DefaultListableBeanFactory#setAllowBeanDefinitionOverriding * @see DefaultListableBeanFactory#setAllowCircularReferences * @see DefaultListableBeanFactory#setAllowRawInjectionDespiteWrapping * @see DefaultListableBeanFactory#setAllowEagerClassLoading */ protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) { if (this.allowBeanDefinitionOverriding != null) { beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding); } if (this.allowCircularReferences != null) { //设置是否允许循环引用 beanFactory.setAllowCircularReferences(this.allowCircularReferences); } } }

​ 在这个方法中,先判断BeanFactory是否存在,如果存在,则先销毁beans并关闭beanFactory,急着创建DefaultListableBeanFactory,并调用loadBeanDefinitions(beanFactory)装载bean定义

5、载入配置路径

AbstractRefreshableApplicationContext中只定义了抽象的loadBeanDefinitions方法,容器真正调用的是其子类AbstractXmlApplicationContext对该方法的实现,AbstractXmlApplicationContext的主要源码如下:

public abstract class AbstractXmlApplicationContext extends AbstractRefreshableConfigApplicationContext {
  //实现父类抽象的载入Bean定义方法
  @Override
  protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
    // Create a new XmlBeanDefinitionReader for the given BeanFactory.
    //创建XmlBeanDefinitionReader,即创建Bean读取器,并通过回调设置到容器中去,容器使用该读取器读取Bean定义资源
    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

    // Configure the bean definition reader with this context's
    // resource loading environment.
    //为Bean读取器设置Spring资源加载器,AbstractXmlApplicationContext的
    //祖先父类AbstractApplicationContext继承DefaultResourceLoader,因此,容器本身也是一个资源加载器
    beanDefinitionReader.setEnvironment(this.getEnvironment());
    beanDefinitionReader.setResourceLoader(this);
    //为Bean读取器设置SAX xml解析器
    beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

    // Allow a subclass to provide custom initialization of the reader,
    // then proceed with actually loading the bean definitions.
    //当Bean读取器读取Bean定义的Xml资源文件时,启用Xml的校验机制
    initBeanDefinitionReader(beanDefinitionReader);
    //Bean读取器真正实现加载的方法
    loadBeanDefinitions(beanDefinitionReader);
  }

  protected void initBeanDefinitionReader(XmlBeanDefinitionReader reader) {
    reader.setValidating(this.validating);
  }

  //Xml Bean读取器加载Bean定义资源
  protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
    //获取Bean定义资源的定位
    Resource[] configResources = getConfigResources();
    if (configResources != null) {
      //Xml Bean读取器调用其父类AbstractBeanDefinitionReader读取定位
      //的Bean定义资源
      reader.loadBeanDefinitions(configResources);
    }
    //如果子类中获取的Bean定义资源定位为空,则获取FileSystemXmlApplicationContext构造方法中setConfigLocations方法设置的资源
    String[] configLocations = getConfigLocations();
    if (configLocations != null) {
      //Xml Bean读取器调用其父类AbstractBeanDefinitionReader读取定位
      //的Bean定义资源
      reader.loadBeanDefinitions(configLocations);
    }
  }
  //这里又使用了一个委托模式,调用子类的获取Bean定义资源定位的方法
	//该方法在ClassPathXmlApplicationContext中进行实现,对于我们
	//举例分析源码的FileSystemXmlApplicationContext没有使用该方法
	@Nullable
	protected Resource[] getConfigResources() {
		return null;
	}
}

​ 以XmlBean读取器中的一种策略XmlBeanDefinitionReader为例,XmlBeanDefinitionReader调用其父类AbstractBeanDefinitionReaderread.loadBeanDefinition()方法读取Bean配置资源。由于我们使用ClassPathXmlApplicationContext作为例子分析,因为getResources的返回为空,所以程序执行reader.loadBeanDefinition(configLocations)分支。

6、分配路径处理策略

​ 在XmlBeanDefinitionReader的抽象父类AbstractBeanDefinitionReader中定义了载入过程。

AbstractBeanDefinitionReaderloadBeanDefinitions()方法源码如下:

public abstract class AbstractBeanDefinitionReader implements EnvironmentCapable, BeanDefinitionReader {
  
  //重载方法,调用loadBeanDefinitions(String);
  @Override
  public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
    Assert.notNull(locations, "Location array must not be null");
    int counter = 0;
    for (String location : locations) {
      counter += loadBeanDefinitions(location);
    }
    return counter;
  }
  
  //重载方法,调用下面的loadBeanDefinitions(String, Set);方法
  @Override
  public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
    return loadBeanDefinitions(location, null);
  }
  
  public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
    //获取在IoC容器初始化过程中设置的资源加载器
    ResourceLoader resourceLoader = getResourceLoader();
    if (resourceLoader == null) {
      throw new BeanDefinitionStoreException(
        "Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
    }
    if (resourceLoader instanceof ResourcePatternResolver) {
      // Resource pattern matching available.
      try {
        //将指定位置的Bean定义资源文件解析为Spring IOC容器封装的资源
        //加载多个指定位置的Bean定义资源文件
        Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
        //委派调用其子类XmlBeanDefinitionReader的方法,实现加载功能
        int loadCount = loadBeanDefinitions(resources);
        if (actualResources != null) {
          for (Resource resource : resources) {
            actualResources.add(resource);
          }
        }
        if (logger.isDebugEnabled()) {
          logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
        }
        return loadCount;
      }
      catch (IOException ex) {
        throw new BeanDefinitionStoreException(
          "Could not resolve bean definition resource pattern [" + location + "]", ex);
      }
    }
    else {
      // Can only load single resources by absolute URL.
      //将指定位置的Bean定义资源文件解析为Spr ing IOC容器封装的资源
      //加载单个指定位置的Bean定义资源文件
      Resource resource = resourceLoader.getResource(location);
      //委派调用其子类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;
    }
  }
}

AbstractRefreshableConfigApplicationContextloadBeanDefinitions(Resource ... resources)方法实际调用的是AbstractBeanDefinitionReaderloadBeanDefinitions()方法.

​ 从对AbstractBeanDefinitionReaderloadBeanDefinitions()方法源码分析可以看出该方法就做了两件事:

​ 1.调用资源加载器获取资源方法resourceLoader.getResouce(location),获取到要加载的资源。

2.真正加载功能的是其子类XmlBeanDefinitionReaderloadBeanDefinitions()方法,在loadBeanDefinition()方法中调用了AbstractApplicationContextgetResouces()方法,跟进去之后发现getResouces()方法其实是定义在ResourcePatternResolver中,此时,我们来查看ResoucePatternResolver的全类图:

Spring ioc源码分析_第6张图片

​ 从上面可以看到ResouceLoaderApplicationContext的继承关系,可以看出其实际调用的是DefaultResouceLoader中的getSource()方法定位ResouceClassPathXmlApplicationContext本身就是DefaultResouceLoader的实现类

,所以此时回到了ClassPathXmlApplicationContext中来。

​ 因为在初始化ResourceLoader的时候设置了resourceLoader是自身,所以resourceLoader就是ClassPathXmlApplicationContext

    beanDefinitionReader.setResourceLoader(this);

7、解析配置文件路径

XmlBeanDefinitionReader通过调用ClassPathXmlApplicationContextDefaultResouceLoadergetResource()方法获取要加载的资源,其源码如下

public class DefaultResourceLoader implements ResourceLoader {

  @Override
  public Resource getResource(String location) {
    Assert.notNull(location, "Location must not be null");

    for (ProtocolResolver protocolResolver : this.protocolResolvers) {
      Resource resource = protocolResolver.resolve(location, this);
      if (resource != null) {
        return resource;
      }
    }
    //如果是类路径的方式,那需要使用 ClassPathResource 来得到 bean 文件的资源对象
    if (location.startsWith("/")) {
      return getResourceByPath(location);
    }
    else if (location.startsWith(CLASSPATH_URL_PREFIX)) {
      return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());
    }
    else {
      try {
        // 如果是 URL 方式,使用 UrlResource 作为 bean 文件的资源对象
        // Try to parse the location as a URL...
        URL url = new URL(location);
        return new UrlResource(url);
      }
      catch (MalformedURLException ex) {
        //如果既不是 classpath 标识,又不是 URL 标识的 Resource 定位,则调用 //容器本身的 getResourceByPath 方法获取 Resource
        // No URL -> resolve as resource path.
        return getResourceByPath(location);
      }
    }
  }
}

DefaultResourceLoader提供了getResourceByPath()方法实现,就是为了处理既不是ClassPath标识,又不是URL标识的Resource定位的情况

protected Resource getResourceByPath(String path) {
  return new ClassPathContextResource(path, getClassLoader());
}

​ 在ClassPathResource中完成了对整个路径的解析。这样,就可以从类路径上对IOC配置文件进行加载,当然我们可以按照此逻辑从任何地方加载,在Spring中我们看到他提供的各种资源抽象ClassPathResourceURLRsourceFileSystemResource等来供我们使用。

​ 上述我们看到的是定位Resource的一个过程,而这只是加载过程的一部分。FileSystemXmlApplication容器就重写了getResourceByPath()方法:

@Override
protected Resource getResourceByPath(String path) { 
  if (path.startsWith("/")) {
    path = path.substring(1); }
  //这里使用文件系统资源对象来定义 bean 文件
  return new FileSystemResource(path);
}

通过子类的覆盖,巧妙的完成了将类路径转化为文件路径的转化。

8、开始读取配置内容

继续回到XmlBeanDefinitionReaderloadBeanDefinitions(Resource ..)方法看到代表bean文件的资源定义以后的载入过程

public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {

  //XmlBeanDefinitionReader加载资源的入口方法
  @Override
  public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
    //将读入的XML资源进行特殊编码处理
    return loadBeanDefinitions(new EncodedResource(resource));
  }

  //这里是载入XML形式Bean定义资源文件方法
  public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
    Assert.notNull(encodedResource, "EncodedResource must not be null");
    if (logger.isInfoEnabled()) {
      logger.info("Loading XML bean definitions from " + encodedResource.getResource());
    }

    Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
    if (currentResources == null) {
      currentResources = new HashSet<>(4);
      this.resourcesCurrentlyBeingLoaded.set(currentResources);
    }
    if (!currentResources.add(encodedResource)) {
      throw new BeanDefinitionStoreException(
        "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
    }
    try {
      //将资源文件转为InputStream的IO流
      InputStream inputStream = encodedResource.getResource().getInputStream();
      try {
        //从InputStream中得到XML的解析源
        InputSource inputSource = new InputSource(inputStream);
        if (encodedResource.getEncoding() != null) {
          inputSource.setEncoding(encodedResource.getEncoding());
        }
        //这里是具体的读取过程
        return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
      }
      finally {
        //关闭从Resource中得到的IO流
        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();
      }
    }
  }
  
  	//从特定XML文件中实际载入Bean定义资源的方法
	protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
			throws BeanDefinitionStoreException {
		try {
			//将XML文件转换为DOM对象,解析过程由documentLoader实现
			Document doc = doLoadDocument(inputSource, resource);
			//这里是启动对Bean定义解析的详细过程,该解析过程会用到Spring的Bean配置规则
			return registerBeanDefinitions(doc, resource);
		}
		catch (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);
		}
	}
}

9、准备文档对象

DocumentLoader把Bean资源转化为Document对象的源码如下:

public class DefaultDocumentLoader implements DocumentLoader {

  //使用标准的JAXP将载入的Bean定义资源转换成document对象
  @Override
  public Document loadDocument(InputSource inputSource, EntityResolver entityResolver,
                               ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {

    //创建文件解析器工厂
    DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);
    if (logger.isDebugEnabled()) {
      logger.debug("Using JAXP provider [" + factory.getClass().getName() + "]");
    }
    //创建文档解析器
    DocumentBuilder builder = 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);

    //设置解析XML的校验
    if (validationMode != XmlValidationModeDetector.VALIDATION_NONE) {
      factory.setValidating(true);
      if (validationMode == XmlValidationModeDetector.VALIDATION_XSD) {
        // Enforce namespace aware for XSD...
        factory.setNamespaceAware(true);
        try {
          factory.setAttribute(SCHEMA_LANGUAGE_ATTRIBUTE, XSD_SCHEMA_LANGUAGE);
        }
        catch (IllegalArgumentException ex) {
          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(ex);
          throw pcex;
        }
      }
    }

    return factory;
  }
}

​ 上述解析过程调用JavaEE标准的JAXP标准进行处理,至此Spring IOC容器根据定位的Bean配置信息,将其加载读入并且转化为Document对象过程完成。接下来我们要继续分析Spring IOC容器如何将载入的Bean配置信息转化为Document对象之后,是如何将其解析为Spring IOC管理的Bean并将其注册到容器中的

10、分配解析策略

XmlBeanDefinitionReaderdoLoadBeanDefinitions方法是从特定XMl文件中实际载入Bean配置资源的方法,此方法在载入Bean配置资源之后将其转化为Document对象,之后再registerBeanDefinitions启动Spring IOC容器对Bean定义的解析过程

public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
  private Class<?> documentReaderClass = DefaultBeanDefinitionDocumentReader.class;
  //创建BeanDefinitionDocumentReader对象,解析Document对象
  protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {
    return BeanDefinitionDocumentReader.class.cast(BeanUtils.instantiateClass(this.documentReaderClass));
  }
  //按照Spring的Bean语义要求将Bean定义资源解析并转换为容器内部数据结构
  public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
    //得到BeanDefinitionDocumentReader来对xml格式的BeanDefinition解析
    BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
    //获得容器中注册的Bean数量
    int countBefore = getRegistry().getBeanDefinitionCount();
    //解析过程入口,这里使用了委派模式,BeanDefinitionDocumentReader只是个接口,
    //具体的解析实现过程有实现类DefaultBeanDefinitionDocumentReader完成
    documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
    //统计解析的Bean数量
    return getRegistry().getBeanDefinitionCount() - countBefore;
  }
  /**
	 * Create the {@link XmlReaderContext} to pass over to the document reader.
	 */
  public XmlReaderContext createReaderContext(Resource resource) {
    return new XmlReaderContext(resource, this.problemReporter, this.eventListener,
                                this.sourceExtractor, this, getNamespaceHandlerResolver());
  }

  /**
	 * Lazily create a default NamespaceHandlerResolver, if not set before.
	 * @see #createDefaultNamespaceHandlerResolver()
	 */
  public NamespaceHandlerResolver getNamespaceHandlerResolver() {
    if (this.namespaceHandlerResolver == null) {
      this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver();
    }
    return this.namespaceHandlerResolver;
  }

  /**
	 * Create the default implementation of {@link NamespaceHandlerResolver} used if none is specified.
	 * Default implementation returns an instance of {@link DefaultNamespaceHandlerResolver}.
	 */
  protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() {
    ClassLoader cl = (getResourceLoader() != null ? getResourceLoader().getClassLoader() : getBeanClassLoader());
    return new DefaultNamespaceHandlerResolver(cl);
  }
}

Bean配置资源的载入解析分为以下两个过程:

​ 首先通过,调用XML解析器将Bean配置信息转化得到Document对象,但是这些Document对象没有按照SpringBean规则进行解析。这一步是载入的过程。

​ 其次在完成通用的XMl解析之后,按照Spring Bean定义的规则对Document对象进行解析,其解析过程是在接口BeandefinitionDocumentReader的实现类DefaultBeanDefinitionDocumentReader中实现。

11、将配置载入内存

XmlBeanDefinitionReader接口通过registerBeanDefinitions方法调用其实现类DefaultBeanDefinitionDocumentReader对Document对象进行解析:

Spring IOC 容器对载入的 Bean 定义 Document 解析可以看出,我们使用 Spring 时,在 Spring 配置文件中可以使用元素来导入 IOC 容器所需要的其他资源,Spring IOC 容器在解 析时会首先将指定导入的资源加载进容器中。使用别名时,Spring IOC 容器首先将别名元素所 定义的别名注册到容器中。

对于既不是元素,又不是元素的元素,即 Spring 配置文件中普通的元素的 解析由 BeanDefinitionParserDelegate 类的 parseBeanDefinitionElement方法来实现。

public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {

  //按照Spring的Bean语义要求将Bean定义资源解析并转换为容器内部数据结构
  public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
    //得到BeanDefinitionDocumentReader来对xml格式的BeanDefinition解析
    BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
    //获得容器中注册的Bean数量
    int countBefore = getRegistry().getBeanDefinitionCount();
    //解析过程入口,这里使用了委派模式,BeanDefinitionDocumentReader只是个接口,
    //具体的解析实现过程有实现类DefaultBeanDefinitionDocumentReader完成
    documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
    //统计解析的Bean数量
    return getRegistry().getBeanDefinitionCount() - countBefore;
  }
  	//根据Spring DTD对Bean的定义规则解析Bean定义Document对象
	@Override
	public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
		//获得XML描述符
		this.readerContext = readerContext;
		logger.debug("Loading bean definitions");
		//获得Document的根元素
		Element root = doc.getDocumentElement();
		doRegisterBeanDefinitions(root);
	}
  	/**
	 * Create the {@link XmlReaderContext} to pass over to the document reader.
	 */
	public XmlReaderContext createReaderContext(Resource resource) {
		return new XmlReaderContext(resource, this.problemReporter, this.eventListener,
				this.sourceExtractor, this, getNamespaceHandlerResolver());
	}

	/**
	 * Lazily create a default NamespaceHandlerResolver, if not set before.
	 * @see #createDefaultNamespaceHandlerResolver()
	 */
	public NamespaceHandlerResolver getNamespaceHandlerResolver() {
		if (this.namespaceHandlerResolver == null) {
			this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver();
		}
		return this.namespaceHandlerResolver;
	}

	/**
	 * Create the default implementation of {@link NamespaceHandlerResolver} used if none is specified.
	 * Default implementation returns an instance of {@link DefaultNamespaceHandlerResolver}.
	 */
	protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() {
		ClassLoader cl = (getResourceLoader() != null ? getResourceLoader().getClassLoader() : getBeanClassLoader());
		return new DefaultNamespaceHandlerResolver(cl);
	}
}

public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {
  /**
	 * Register each bean definition within the given root {@code } element.
	 */
  protected void doRegisterBeanDefinitions(Element root) {
    //具体的解析过程由BeanDefinitionParserDelegate实现,
    //BeanDefinitionParserDelegate中定义了Spring Bean定义XML文件的各种元素
    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;
  }

环境判断

​ 首先执行对应Profile标签认证,先取到环境,然后判断环境是否匹配对应的profile,环境获取在

public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {
protected void doRegisterBeanDefinitions(Element root) {
		//具体的解析过程由BeanDefinitionParserDelegate实现,
		//BeanDefinitionParserDelegate中定义了Spring Bean定义XML文件的各种元素
		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;
	}
}

getReaderContext().getEnvironment()其实是通过AbstractBeanDefinitionReader获取到的

在初始化的时候设置了是StandardEnvironment

public class XmlReaderContext extends ReaderContext {
  public XmlReaderContext(
    Resource resource, ProblemReporter problemReporter,
    ReaderEventListener eventListener, SourceExtractor sourceExtractor,
    XmlBeanDefinitionReader reader, NamespaceHandlerResolver namespaceHandlerResolver) {

    super(resource, problemReporter, eventListener, sourceExtractor);
    this.reader = reader;
    this.namespaceHandlerResolver = namespaceHandlerResolver;
  }
  public final Environment getEnvironment() {
    return this.reader.getEnvironment();
  }
}


XmlReaderContextenvironment是从XmlBeanDefinitionReader中获取到的

public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {

  public XmlReaderContext createReaderContext(Resource resource) {
    return new XmlReaderContext(resource, this.problemReporter, this.eventListener,
                                this.sourceExtractor, this, getNamespaceHandlerResolver());
  }
}

XmlBeanDefinitionReaderenvironment是从AbstractBeanDefinitionReader中初始化的

public abstract class AbstractBeanDefinitionReader implements EnvironmentCapable, BeanDefinitionReader {

  protected AbstractBeanDefinitionReader(BeanDefinitionRegistry registry) {
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    this.registry = registry;

    // Determine ResourceLoader to use.
    if (this.registry instanceof ResourceLoader) {
      this.resourceLoader = (ResourceLoader) this.registry;
    }
    else {
      this.resourceLoader = new PathMatchingResourcePatternResolver();
    }

    // Inherit Environment if possible
    if (this.registry instanceof EnvironmentCapable) {
      this.environment = ((EnvironmentCapable) this.registry).getEnvironment();
    }
    else {
      this.environment = new StandardEnvironment();
    }
  }
}

Spring ioc源码分析_第7张图片

PropertyPlaceholderHelper中记录了对应的读取配置文件的规则,以及解析的方式

public class PropertyPlaceholderHelper {
	public PropertyPlaceholderHelper(String placeholderPrefix, String placeholderSuffix,
			@Nullable String valueSeparator, boolean ignoreUnresolvablePlaceholders) {

		Assert.notNull(placeholderPrefix, "'placeholderPrefix' must not be null");
		Assert.notNull(placeholderSuffix, "'placeholderSuffix' must not be null");
		this.placeholderPrefix = placeholderPrefix;
		this.placeholderSuffix = placeholderSuffix;
		String simplePrefixForSuffix = wellKnownSimplePrefixes.get(this.placeholderSuffix);
		if (simplePrefixForSuffix != null && this.placeholderPrefix.endsWith(simplePrefixForSuffix)) {
			this.simplePrefix = simplePrefixForSuffix;
		}
		else {
			this.simplePrefix = this.placeholderPrefix;
		}
		this.valueSeparator = valueSeparator;
		this.ignoreUnresolvablePlaceholders = ignoreUnresolvablePlaceholders;
	}
  protected String parseStringValue(
			String value, PlaceholderResolver placeholderResolver, Set<String> visitedPlaceholders) {

		StringBuilder result = new StringBuilder(value);

		int startIndex = value.indexOf(this.placeholderPrefix);
		while (startIndex != -1) {
			int endIndex = findPlaceholderEndIndex(result, startIndex);
			if (endIndex != -1) {
				String placeholder = result.substring(startIndex + this.placeholderPrefix.length(), endIndex);
				String originalPlaceholder = placeholder;
				if (!visitedPlaceholders.add(originalPlaceholder)) {
					throw new IllegalArgumentException(
							"Circular placeholder reference '" + originalPlaceholder + "' in property definitions");
				}
				// Recursive invocation, parsing placeholders contained in the placeholder key.
				placeholder = parseStringValue(placeholder, placeholderResolver, visitedPlaceholders);
				// Now obtain the value for the fully resolved key...
				String propVal = placeholderResolver.resolvePlaceholder(placeholder);
				if (propVal == null && this.valueSeparator != null) {
					int separatorIndex = placeholder.indexOf(this.valueSeparator);
					if (separatorIndex != -1) {
						String actualPlaceholder = placeholder.substring(0, separatorIndex);
						String defaultValue = placeholder.substring(separatorIndex + this.valueSeparator.length());
						propVal = placeholderResolver.resolvePlaceholder(actualPlaceholder);
						if (propVal == null) {
							propVal = defaultValue;
						}
					}
				}
				if (propVal != null) {
					// Recursive invocation, parsing placeholders contained in the
					// previously resolved placeholder value.
					propVal = parseStringValue(propVal, placeholderResolver, visitedPlaceholders);
					result.replace(startIndex, endIndex + this.placeholderSuffix.length(), propVal);
					if (logger.isTraceEnabled()) {
						logger.trace("Resolved placeholder '" + placeholder + "'");
					}
					startIndex = result.indexOf(this.placeholderPrefix, startIndex + propVal.length());
				}
				else if (this.ignoreUnresolvablePlaceholders) {
					// Proceed with unprocessed value.
					startIndex = result.indexOf(this.placeholderPrefix, endIndex + this.placeholderSuffix.length());
				}
				else {
					throw new IllegalArgumentException("Could not resolve placeholder '" +
							placeholder + "'" + " in value \"" + value + "\"");
				}
				visitedPlaceholders.remove(originalPlaceholder);
			}
			else {
				startIndex = -1;
			}
		}

		return result.toString();
	}
}

元素解析

解析

 public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {

 //创建BeanDefinitionParserDelegate,用于完成真正的解析过程
  protected BeanDefinitionParserDelegate createDelegate(
    XmlReaderContext readerContext, Element root, @Nullable BeanDefinitionParserDelegate parentDelegate) {

    BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);
    //BeanDefinitionParserDelegate初始化Document根元素
    delegate.initDefaults(root, parentDelegate);
    return delegate;
  }

  /**
	 * Parse the elements at the root level in the document:
	 * "import", "alias", "bean".
	 * @param root the DOM root element of the document
	 */
  //使用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规则解析元素节点
            parseDefaultElement(ele, delegate);
          }
          else {
            //没有使用Spring默认的XML命名空间,则使用用户自定义的解//析规则解析元素节点
            delegate.parseCustomElement(ele);
          }
        }
      }
    }
    else {
      //Document的根节点没有使用Spring默认的命名空间,则使用用户自定义的
      //解析规则解析Document根节点
      delegate.parseCustomElement(root);
    }
  }


  //使用Spring的Bean规则解析Document元素节点
  private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
    //如果元素节点是导入元素,进行导入解析
    if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
      importBeanDefinitionResource(ele);
    }
    //如果元素节点是别名元素,进行别名解析
    else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
      processAliasRegistration(ele);
    }
    //元素节点既不是导入元素,也不是别名元素,即普通的元素,
    //按照Spring的Bean规则解析元素
    else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
      processBeanDefinition(ele, delegate);
    }
    else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
      // recurse
      doRegisterBeanDefinitions(ele);
    }
  }


  /**
	 * Process the given alias element, registering the alias with the registry.
	 */
  //解析别名元素,为Bean向Spring IoC容器注册别名
  protected void processAliasRegistration(Element ele) {
    //获取别名元素中name的属性值
    String name = ele.getAttribute(NAME_ATTRIBUTE);
    //获取别名元素中alias的属性值
    String alias = ele.getAttribute(ALIAS_ATTRIBUTE);
    boolean valid = true;
    //别名元素的name属性值为空
    if (!StringUtils.hasText(name)) {
      getReaderContext().error("Name must not be empty", ele);
      valid = false;
    }
    //别名元素的alias属性值为空
    if (!StringUtils.hasText(alias)) {
      getReaderContext().error("Alias must not be empty", ele);
      valid = false;
    }
    if (valid) {
      try {
        //向容器的资源读入器注册别名
        getReaderContext().getRegistry().registerAlias(name, alias);
      }
      catch (Exception ex) {
        getReaderContext().error("Failed to register alias '" + alias +
                                 "' for bean with name '" + name + "'", ele, ex);
      }
      //在解析完元素之后,发送容器别名处理完成事件
      getReaderContext().fireAliasRegistered(name, alias, extractSource(ele));
    }
  }

  /**
	 * Process the given bean element, parsing the bean definition
	 * and registering it with the registry.
	 */
  //解析Bean定义资源Document对象的普通元素
  protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
    BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
    // BeanDefinitionHolder是对BeanDefinition的封装,即Bean定义的封装类
    //对Document对象中元素的解析由BeanDefinitionParserDelegate实现
    // BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
    if (bdHolder != null) {
      bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
      try {
        // Register the final decorated instance.
        //向Spring IOC容器注册解析得到的Bean定义,这是Bean定义向IOC容器注册的入口
        BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
      }
      catch (BeanDefinitionStoreException ex) {
        getReaderContext().error("Failed to register bean definition with name '" +
                                 bdHolder.getBeanName() + "'", ele, ex);
      }
      // Send registration event.
      //在完成向Spring IOC容器注册解析得到的Bean定义之后,发送注册事件
      getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
    }
  }
}
}

解析自定义元素

在上述 delegate.parseCustomElement(root);中,如果我们没有使用spring默认的命名空间即没有使用http://www.springframework.org/schema/beans此命名空间那么会执行此方法

public class BeanDefinitionParserDelegate {

  public BeanDefinition parseCustomElement(Element ele) {
    return parseCustomElement(ele, null);
  }

  public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
    String namespaceUri = getNamespaceURI(ele);
    NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
    if (handler == null) {
      error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
      return null;
    }
    return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
  }
}

上述getNamespaceHandlerResolverDefaultNamespaceHandlerResolver分析解析策略可见得。

对应resolver方式

public class DefaultNamespaceHandlerResolver implements NamespaceHandlerResolver {
  	public static final String DEFAULT_HANDLER_MAPPINGS_LOCATION = "META-INF/spring.handlers";
  
  	public DefaultNamespaceHandlerResolver(ClassLoader classLoader) {
		this(classLoader, DEFAULT_HANDLER_MAPPINGS_LOCATION);
	}

	public DefaultNamespaceHandlerResolver(ClassLoader classLoader, String handlerMappingsLocation) {
		Assert.notNull(handlerMappingsLocation, "Handler mappings location must not be null");
		this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader());
		this.handlerMappingsLocation = handlerMappingsLocation;
	}
  //匹配对应namespaceUri
  public NamespaceHandler resolve(String namespaceUri) {
    Map<String, Object> handlerMappings = getHandlerMappings();
    Object handlerOrClassName = handlerMappings.get(namespaceUri);
    if (handlerOrClassName == null) {
      return null;
    }
    else if (handlerOrClassName instanceof NamespaceHandler) {
      return (NamespaceHandler) handlerOrClassName;
    }
    else {
      String className = (String) handlerOrClassName;
      try {
        Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
        if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
          throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri +
                                       "] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
        }
        //实例化对应handlerclass对象
        NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
        namespaceHandler.init();
        handlerMappings.put(namespaceUri, namespaceHandler);
        return namespaceHandler;
      }
      catch (ClassNotFoundException ex) {
        throw new FatalBeanException("NamespaceHandler class [" + className + "] for namespace [" +
                                     namespaceUri + "] not found", ex);
      }
      catch (LinkageError err) {
        throw new FatalBeanException("Invalid NamespaceHandler class [" + className + "] for namespace [" +
                                     namespaceUri + "]: problem with handler class file or dependent class", err);
      }
    }
  }
  //加载指定的NamespaceHandler映射。
  private Map<String, Object> getHandlerMappings() {
		if (this.handlerMappings == null) {
			synchronized (this) {
				if (this.handlerMappings == null) {
					try {
						Properties mappings =
								PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader);
						if (logger.isDebugEnabled()) {
							logger.debug("Loaded NamespaceHandler mappings: " + mappings);
						}
						Map<String, Object> handlerMappings = new ConcurrentHashMap<String, Object>(mappings.size());
						CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings);
						this.handlerMappings = handlerMappings;
					}
					catch (IOException ex) {
						throw new IllegalStateException(
								"Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", ex);
					}
				}
			}
		}
		return this.handlerMappings;
	}
}

从上可知,默认读取META-INF/spring.handlers中的文件例如Spring-Context中的spring.handlers

http\://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler
http\://www.springframework.org/schema/jee=org.springframework.ejb.config.JeeNamespaceHandler
http\://www.springframework.org/schema/lang=org.springframework.scripting.config.LangNamespaceHandler
http\://www.springframework.org/schema/task=org.springframework.scheduling.config.TaskNamespaceHandler
http\://www.springframework.org/schema/cache=org.springframework.cache.config.CacheNamespaceHandler

NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);

可知我们对应解析的类需要实现NamespaceHandler接口

最后执行对应的init方法和parse方法

解析

public class BeanDefinitionParserDelegate {

  /**
	 * Parse an "import" element and load the bean definitions
	 * from the given resource into the bean factory.
	 */
  //解析导入元素,从给定的导入路径加载Bean定义资源到Spring IoC容器中
  protected void importBeanDefinitionResource(Element ele) {
    //获取给定的导入元素的location属性
    String location = ele.getAttribute(RESOURCE_ATTRIBUTE);
    //如果导入元素的location属性值为空,则没有导入任何资源,直接返回
    if (!StringUtils.hasText(location)) {
      getReaderContext().error("Resource location must not be empty", ele);
      return;
    }

    // Resolve system properties: e.g. "${user.dir}"
    //使用系统变量值解析location属性值
    location = getReaderContext().getEnvironment().resolveRequiredPlaceholders(location);

    Set<Resource> actualResources = new LinkedHashSet<>(4);

    // Discover whether the location is an absolute or relative URI
    //标识给定的导入元素的location是否是绝对路径
    boolean absoluteLocation = false;
    try {
      absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute();
    }
    catch (URISyntaxException ex) {
      // cannot convert to an URI, considering the location relative
      // unless it is the well-known Spring prefix "classpath*:"
      //给定的导入元素的location不是绝对路径
    }

    // Absolute or relative?
    //给定的导入元素的location是绝对路径
    if (absoluteLocation) {
      try {
        //使用资源读入器加载给定路径的Bean定义资源
        int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources);
        if (logger.isDebugEnabled()) {
          logger.debug("Imported " + importCount + " bean definitions from URL location [" + location + "]");
        }
      }
      catch (BeanDefinitionStoreException ex) {
        getReaderContext().error(
          "Failed to import bean definitions from URL location [" + location + "]", ele, ex);
      }
    }
    else {
      // No URL -> considering resource location as relative to the current file.
      //给定的导入元素的location是相对路径
      try {
        int importCount;
        //将给定导入元素的location封装为相对路径资源
        Resource relativeResource = getReaderContext().getResource().createRelative(location);
        //封装的相对路径资源存在
        if (relativeResource.exists()) {
          //使用资源读入器加载Bean定义资源
          importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource);
          actualResources.add(relativeResource);
        }
        //封装的相对路径资源不存在
        else {
          //获取Spring IOC容器资源读入器的基本路径
          String baseLocation = getReaderContext().getResource().getURL().toString();
          //根据Spring IOC容器资源读入器的基本路径加载给定导入路径的资源
          importCount = getReaderContext().getReader().loadBeanDefinitions(
            StringUtils.applyRelativePath(baseLocation, location), actualResources);
        }
        if (logger.isDebugEnabled()) {
          logger.debug("Imported " + importCount + " bean definitions from relative location [" + location + "]");
        }
      }
      catch (IOException ex) {
        getReaderContext().error("Failed to resolve current resource location", ele, ex);
      }
      catch (BeanDefinitionStoreException ex) {
        getReaderContext().error("Failed to import bean definitions from relative location [" + location + "]",
                                 ele, ex);
      }
    }
    Resource[] actResArray = actualResources.toArray(new Resource[actualResources.size()]);
    //在解析完元素之后,发送容器导入其他资源处理完成事件
    getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele));
  }
}

解析

	/**
	 * Process the given alias element, registering the alias with the registry.
	 */
	//解析别名元素,为Bean向Spring IoC容器注册别名
	protected void processAliasRegistration(Element ele) {
		//获取别名元素中name的属性值
		String name = ele.getAttribute(NAME_ATTRIBUTE);
		//获取别名元素中alias的属性值
		String alias = ele.getAttribute(ALIAS_ATTRIBUTE);
		boolean valid = true;
		//别名元素的name属性值为空
		if (!StringUtils.hasText(name)) {
			getReaderContext().error("Name must not be empty", ele);
			valid = false;
		}
		//别名元素的alias属性值为空
		if (!StringUtils.hasText(alias)) {
			getReaderContext().error("Alias must not be empty", ele);
			valid = false;
		}
		if (valid) {
			try {
				//向容器的资源读入器注册别名
				getReaderContext().getRegistry().registerAlias(name, alias);
			}
			catch (Exception ex) {
				getReaderContext().error("Failed to register alias '" + alias +
						"' for bean with name '" + name + "'", ele, ex);
			}
			//在解析完元素之后,发送容器别名处理完成事件
			getReaderContext().fireAliasRegistered(name, alias, extractSource(ele));
		}
	}
public class SimpleAliasRegistry implements AliasRegistry {

  @Override
  public void registerAlias(String name, String alias) {
    Assert.hasText(name, "'name' must not be empty");
    Assert.hasText(alias, "'alias' must not be empty");
    if (alias.equals(name)) {
      this.aliasMap.remove(alias);
    }
    else {
      String registeredName = this.aliasMap.get(alias);
      if (registeredName != null) {
        if (registeredName.equals(name)) {
          // An existing alias - no need to re-register
          return;
        }
        if (!allowAliasOverriding()) {
          throw new IllegalStateException("Cannot register alias '" + alias + "' for name '" +
                                          name + "': It is already registered for name '" + registeredName + "'.");
        }
      }
      checkForAliasCircle(name, alias);
      this.aliasMap.put(alias, name);
    }
  }
}

解析

Bean 配置信息中的元素解析在 DefaultBeanDefinitionDocumentReader中已
经完成,对 Bean 配置信息中使用最多的元素交由BeanDefinitionParserDelegate来解析,

注册的Beandefinition都注册到了DefalutListAbleFactory

public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {

  //解析Bean定义资源Document对象的普通元素
  protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
    BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
    // BeanDefinitionHolder是对BeanDefinition的封装,即Bean定义的封装类
    //对Document对象中元素的解析由BeanDefinitionParserDelegate实现
    // BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
    if (bdHolder != null) {
      bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
      try {
        // Register the final decorated instance.
        //向Spring IOC容器注册解析得到的Bean定义,这是Bean定义向IOC容器注册的入口
        BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
      }
      catch (BeanDefinitionStoreException ex) {
        getReaderContext().error("Failed to register bean definition with name '" +
                                 bdHolder.getBeanName() + "'", ele, ex);
      }
      // Send registration event.
      //在完成向Spring IOC容器注册解析得到的Bean定义之后,发送注册事件
      getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
    }
  }
  	//将解析的BeanDefinitionHold注册到容器中
	public static void registerBeanDefinition(
			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
			throws BeanDefinitionStoreException {

		// Register bean definition under primary name.
		//获取解析的BeanDefinition的名称
		String beanName = definitionHolder.getBeanName();
		//向IOC容器注册BeanDefinition
		registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

		// Register aliases for bean name, if any.
		//如果解析的BeanDefinition有别名,向容器为其注册别名
		String[] aliases = definitionHolder.getAliases();
		if (aliases != null) {
			for (String alias : aliases) {
				registry.registerAlias(beanName, alias);
			}
		}
	}
}

delegate.parseBeanDefinitionElement使用的是BeanDefinitionParserDelegate

public class BeanDefinitionParserDelegate {

  //解析Bean定义资源文件中的元素,这个方法中主要处理元素的id,name和别名属性
  @Nullable
  public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
    //获取元素中的id属性值
    String id = ele.getAttribute(ID_ATTRIBUTE);
    //获取元素中的name属性值
    String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

    //获取元素中的alias属性值
    List<String> aliases = new ArrayList<>();

    //将元素中的所有name属性值存放到别名中
    if (StringUtils.hasLength(nameAttr)) {
      String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
      aliases.addAll(Arrays.asList(nameArr));
    }

    String beanName = id;
    //如果元素中没有配置id属性时,将别名中的第一个值赋值给beanName
    if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
      beanName = aliases.remove(0);
      if (logger.isDebugEnabled()) {
        logger.debug("No XML 'id' specified - using '" + beanName +
                     "' as bean name and " + aliases + " as aliases");
      }
    }

    //检查元素所配置的id或者name的唯一性,containingBean标识
    //元素中是否包含子元素
    if (containingBean == null) {
      //检查元素所配置的id、name或者别名是否重复
      checkNameUniqueness(beanName, aliases, ele);
    }

    //详细对元素中配置的Bean定义进行解析的地方
    AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
    if (beanDefinition != null) {
      if (!StringUtils.hasText(beanName)) {
        try {
          if (containingBean != null) {
            //如果元素中没有配置id、别名或者name,且没有包含子元素
            //元素,为解析的Bean生成一个唯一beanName并注册
            beanName = BeanDefinitionReaderUtils.generateBeanName(
              beanDefinition, this.readerContext.getRegistry(), true);
          }
          else {
            //如果元素中没有配置id、别名或者name,且包含了子元素
            //元素,为解析的Bean使用别名向IOC容器注册
            beanName = this.readerContext.generateBeanName(beanDefinition);
            // Register an alias for the plain bean class name, if still possible,
            // if the generator returned the class name plus a suffix.
            // This is expected for Spring 1.2/2.0 backwards compatibility.
            //为解析的Bean使用别名注册时,为了向后兼容
            //Spring1.2/2.0,给别名添加类名后缀
            String beanClassName = beanDefinition.getBeanClassName();
            if (beanClassName != null &&
                beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
                !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
              aliases.add(beanClassName);
            }
          }
          if (logger.isDebugEnabled()) {
            logger.debug("Neither XML 'id' nor 'name' specified - " +
                         "using generated bean name [" + beanName + "]");
          }
        }
        catch (Exception ex) {
          error(ex.getMessage(), ele);
          return null;
        }
      }
      String[] aliasesArray = StringUtils.toStringArray(aliases);
      return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
    }
    //当解析出错时,返回null
    return null;
  }
  //详细对元素中配置的Bean定义其他属性进行解析
	//由于上面的方法中已经对Bean的id、name和别名等属性进行了处理
	//该方法中主要处理除这三个以外的其他属性数据
	@Nullable
	public AbstractBeanDefinition parseBeanDefinitionElement(
			Element ele, String beanName, @Nullable BeanDefinition containingBean) {
		//记录解析的
		this.parseState.push(new BeanEntry(beanName));

		//这里只读取元素中配置的class名字,然后载入到BeanDefinition中去
		//只是记录配置的class名字,不做实例化,对象的实例化在依赖注入时完成
		String className = null;

		//如果元素中配置了parent属性,则获取parent属性的值
		if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
			className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
		}
		String parent = null;
		if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
			parent = ele.getAttribute(PARENT_ATTRIBUTE);
		}

		try {
			//根据元素配置的class名称和parent属性值创建BeanDefinition
			//为载入Bean定义信息做准备
			AbstractBeanDefinition bd = createBeanDefinition(className, parent);

			//对当前的元素中配置的一些属性进行解析和设置,如配置的单态(singleton)属性等
			parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
			//为元素解析的Bean设置description信息
			bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));

			//对元素的meta(元信息)属性解析
			parseMetaElements(ele, bd);
			//对元素的lookup-method属性解析
			parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
			//对元素的replaced-method属性解析
			parseReplacedMethodSubElements(ele, bd.getMethodOverrides());

			//解析元素的构造方法设置
			parseConstructorArgElements(ele, bd);
			//解析元素的设置
			parsePropertyElements(ele, bd);
			//解析元素的qualifier属性
			parseQualifierElements(ele, bd);

			//为当前解析的Bean设置所需的资源和依赖对象
			bd.setResource(this.readerContext.getResource());
			bd.setSource(extractSource(ele));

			return bd;
		}
		catch (ClassNotFoundException ex) {
			error("Bean class [" + className + "] not found", ele, ex);
		}
		catch (NoClassDefFoundError err) {
			error("Class that bean class [" + className + "] depends on not found", ele, err);
		}
		catch (Throwable ex) {
			error("Unexpected failure during bean definition parsing", ele, ex);
		}
		finally {
			this.parseState.pop();
		}

		//解析元素出错时,返回null
		return null;
	}
}

​ 在解析元素过程中没有创建和实例化Bean对象,只是创建了Bean 对象的定义类
BeanDefinition,将元素中的配置信息设置到BeanDefinition 中作为记录,当依赖注入时才
使用这些记录信息创建和实例化具体的Bean对象。

​ 上面方法中一些对一些配置如元信息(meta)、qualifier 等的解析,我们在 Spring 中配置时使用的也不
多,我们在使用 Spring 的元素时,配置最多的是属性,因此我们下面继续分析源
码,了解 Bean 的属性在解析时是如何设置的。

载入元素

BeanDefinitionParserDelegate在解析调用parsePropertyElements()方法解析
素中的属性子元素,解析源码如下:

public class BeanDefinitionParserDelegate {

  /**
	 * Parse property sub-elements of the given bean element.
	 */
  //解析元素中的子元素
  public void parsePropertyElements(Element beanEle, BeanDefinition bd) {
    //获取元素中所有的子元素
    NodeList nl = beanEle.getChildNodes();
    for (int i = 0; i < nl.getLength(); i++) {
      Node node = nl.item(i);
      //如果子元素是子元素,则调用解析子元素方法解析
      if (isCandidateElement(node) && nodeNameEquals(node, PROPERTY_ELEMENT)) {
        parsePropertyElement((Element) node, bd);
      }
    }
  }
  /**
	 * Parse a property element.
	 */
  //解析元素
  public void parsePropertyElement(Element ele, BeanDefinition bd) {
    //获取元素的名字
    String propertyName = ele.getAttribute(NAME_ATTRIBUTE);
    if (!StringUtils.hasLength(propertyName)) {
      error("Tag 'property' must have a 'name' attribute", ele);
      return;
    }
    this.parseState.push(new PropertyEntry(propertyName));
    try {
      //如果一个Bean中已经有同名的property存在,则不进行解析,直接返回。
      //即如果在同一个Bean中配置同名的property,则只有第一个起作用
      if (bd.getPropertyValues().contains(propertyName)) {
        error("Multiple 'property' definitions for property '" + propertyName + "'", ele);
        return;
      }
      //解析获取property的值
      Object val = parsePropertyValue(ele, bd, propertyName);
      //根据property的名字和值创建property实例
      PropertyValue pv = new PropertyValue(propertyName, val);
      //解析元素中的属性
      parseMetaElements(ele, pv);
      pv.setSource(extractSource(ele));
      bd.getPropertyValues().addPropertyValue(pv);
    }
    finally {
      this.parseState.pop();
    }
  }
  //解析获取property值
  @Nullable
  public Object parsePropertyValue(Element ele, BeanDefinition bd, @Nullable String propertyName) {
    String elementName = (propertyName != null) ?
      " element for property '" + propertyName + "'" :
    " element";

    // Should only have one child element: ref, value, list, etc.
    //获取的所有子元素,只能是其中一种类型:ref,value,list,etc等
    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 && !nodeNameEquals(node, DESCRIPTION_ELEMENT) &&
          !nodeNameEquals(node, META_ELEMENT)) {
        // Child element is what we're looking for.
        if (subElement != null) {
          error(elementName + " must not contain more than one sub-element", ele);
        }
        else {
          //当前元素包含有子元素
          subElement = (Element) node;
        }
      }
    }

    //判断property的属性值是ref还是value,不允许既是ref又是value
    boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);
    boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE);
    if ((hasRefAttribute && hasValueAttribute) ||
        ((hasRefAttribute || hasValueAttribute) && subElement != null)) {
      error(elementName +
            " is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele);
    }

    //如果属性是ref,创建一个ref的数据对象RuntimeBeanReference
    //这个对象封装了ref信息
    if (hasRefAttribute) {
      String refName = ele.getAttribute(REF_ATTRIBUTE);
      if (!StringUtils.hasText(refName)) {
        error(elementName + " contains empty 'ref' attribute", ele);
      }
      //一个指向运行时所依赖对象的引用
      RuntimeBeanReference ref = new RuntimeBeanReference(refName);
      //设置这个ref的数据对象是被当前的property对象所引用
      ref.setSource(extractSource(ele));
      return ref;
    }
    //如果属性是value,创建一个value的数据对象TypedStringValue
    //这个对象封装了value信息
    else if (hasValueAttribute) {
      //一个持有String类型值的对象
      TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE));
      //设置这个value数据对象是被当前的property对象所引用
      valueHolder.setSource(extractSource(ele));
      return valueHolder;
    }
    //如果当前元素还有子元素
    else if (subElement != null) {
      //解析的子元素
      return parsePropertySubElement(subElement, bd);
    }
    else {
      // Neither child element nor "ref" or "value" attribute found.
      //propery属性中既不是ref,也不是value属性,解析出错返回null
      error(elementName + " must specify a ref or value", ele);
      return null;
    }
  }

}

通过上述分析,我们可以了解在Spring配置文件中,元素中元素的相关配置是如何处理的:

1、ref被封装为指向依赖对象的一个引用

2、value配置都会封装成一个字符串类型的对象

3、ref和value都通过TypedStringValue.setSource(extractSource(ele));方法将属性值/引用
与所引用的属性关联起来。

此方法的最后对于元素的子元素通过parsePropertySubElement()方法解析,我们继续分析此方法的源码,了解其解析过程

载入子元素

BeanDefinitionParserDelegate类中的 parsePropertySubElement()方法对中的子元
素解析,源码如下

public class BeanDefinitionParserDelegate {
  @Nullable
  public Object parsePropertySubElement(Element ele, @Nullable BeanDefinition bd) {
    return parsePropertySubElement(ele, bd, null);
  }
  //解析元素中ref,value或者集合等子元素
  @Nullable
  public Object parsePropertySubElement(Element ele, @Nullable BeanDefinition bd, @Nullable String defaultValueType) {
    //如果没有使用Spring默认的命名空间,则使用用户自定义的规则解析内嵌元素
    if (!isDefaultNamespace(ele)) {
      return parseNestedCustomElement(ele, bd);
    }
    //如果子元素是bean,则使用解析元素的方法解析
    else if (nodeNameEquals(ele, BEAN_ELEMENT)) {
      BeanDefinitionHolder nestedBd = parseBeanDefinitionElement(ele, bd);
      if (nestedBd != null) {
        nestedBd = decorateBeanDefinitionIfRequired(ele, nestedBd, bd);
      }
      return nestedBd;
    }
    //如果子元素是ref,ref中只能有以下3个属性:bean、local、parent
    else if (nodeNameEquals(ele, REF_ELEMENT)) {
      // A generic reference to any name of any bean.
      //可以不再同一个Spring配置文件中,具体请参考Spring对ref的配置规则
      String refName = ele.getAttribute(BEAN_REF_ATTRIBUTE);
      boolean toParent = false;
      if (!StringUtils.hasLength(refName)) {
        // A reference to the id of another bean in a parent context.
        //获取元素中parent属性值,引用父级容器中的Bean
        refName = ele.getAttribute(PARENT_REF_ATTRIBUTE);
        toParent = true;
        if (!StringUtils.hasLength(refName)) {
          error("'bean' or 'parent' is required for  element", ele);
          return null;
        }
      }
      if (!StringUtils.hasText(refName)) {
        error(" element contains empty target attribute", ele);
        return null;
      }
      //创建ref类型数据,指向被引用的对象
      RuntimeBeanReference ref = new RuntimeBeanReference(refName, toParent);
      //设置引用类型值是被当前子元素所引用
      ref.setSource(extractSource(ele));
      return ref;
    }
    //如果子元素是,使用解析ref元素的方法解析
    else if (nodeNameEquals(ele, IDREF_ELEMENT)) {
      return parseIdRefElement(ele);
    }
    //如果子元素是,使用解析value元素的方法解析
    else if (nodeNameEquals(ele, VALUE_ELEMENT)) {
      return parseValueElement(ele, defaultValueType);
    }
    //如果子元素是null,为设置一个封装null值的字符串数据
    else if (nodeNameEquals(ele, NULL_ELEMENT)) {
      // It's a distinguished null value. Let's wrap it in a TypedStringValue
      // object in order to preserve the source location.
      TypedStringValue nullHolder = new TypedStringValue(null);
      nullHolder.setSource(extractSource(ele));
      return nullHolder;
    }
    //如果子元素是,使用解析array集合子元素的方法解析
    else if (nodeNameEquals(ele, ARRAY_ELEMENT)) {
      return parseArrayElement(ele, bd);
    }
    //如果子元素是,使用解析list集合子元素的方法解析
    else if (nodeNameEquals(ele, LIST_ELEMENT)) {
      return parseListElement(ele, bd);
    }
    //如果子元素是,使用解析set集合子元素的方法解析
    else if (nodeNameEquals(ele, SET_ELEMENT)) {
      return parseSetElement(ele, bd);
    }
    //如果子元素是,使用解析map集合子元素的方法解析
    else if (nodeNameEquals(ele, MAP_ELEMENT)) {
      return parseMapElement(ele, bd);
    }
    //如果子元素是,使用解析props集合子元素的方法解析
    else if (nodeNameEquals(ele, PROPS_ELEMENT)) {
      return parsePropsElement(ele);
    }
    //既不是ref,又不是value,也不是集合,则子元素配置错误,返回null
    else {
      error("Unknown property sub-element: [" + ele.getNodeName() + "]", ele);
      return null;
    }
  }
}

​ 通过上述源码分析,我们明白了在 Spring 配置文件中,对元素中配置的 arraylistsetmapprop 等各种集合子元素的都通过上述方法解析,生成对应的数据对象,比如 ManagedListManagedArrayManagedSet 等,这些 Managed 类是 Spring 对象 BeanDefiniton 的数据封装,对集合数据类型的具体解析有各自的解析方法实现,解析方法的命名非常规范,一目了然,我们对集合元素的解析方法进行源码分析,了解其实现过程。

载入的子元素
public class BeanDefinitionParserDelegate {

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

解析

如果是Beans则重新调用对应的doRegisterBeanDefinitions方法

public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {
			doRegisterBeanDefinitions(ele);
}

​ 经过对 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 容器的初始化过程

12、分配注册策略

​ 让我们继续跟踪程序的执行顺序,接下来我们来分析 DefaultBeanDefinitionDocumentReader 对 Bean 定义转换的 Document 对象解析的流程中,在其 parseDefaultElement()方法中完成对 Document 对象的解析后得到封装 BeanDefinitionBeanDefinitionHold 对象,然后调用 BeanDefinitionReaderUtilsregisterBeanDefinition()方法向 IOC 容 器 注 册 解 析 的 Bean ,
BeanDefinitionReaderUtils 的注册的源码如下:

public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {

  //解析Bean定义资源Document对象的普通元素
  protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
    BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
    // BeanDefinitionHolder是对BeanDefinition的封装,即Bean定义的封装类
    //对Document对象中元素的解析由BeanDefinitionParserDelegate实现
    // BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
    if (bdHolder != null) {
      bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
      try {
        // Register the final decorated instance.
        //向Spring IOC容器注册解析得到的Bean定义,这是Bean定义向IOC容器注册的入口
        BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
      }
      catch (BeanDefinitionStoreException ex) {
        getReaderContext().error("Failed to register bean definition with name '" +
                                 bdHolder.getBeanName() + "'", ele, ex);
      }
      // Send registration event.
      //在完成向Spring IOC容器注册解析得到的Bean定义之后,发送注册事件
      getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
    }
  }
}

​ 调用BeanDefinitionReaderUtils想IOC容器注册解析的BeanDefinition时,真正完成注册功能的是DefaultListableBeanFactory

13、向容器注册

DefaultListableBeanFactory 中使用一个 HashMap 的集合对象存放 IOC 容器中注册解析的BeanDefinition,向 IOC 容器注册的主要源码如下:

Spring ioc源码分析_第8张图片

@SuppressWarnings("serial")
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
		implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {

/** Map of bean definition objects, keyed by bean name */
	//存储注册信息的BeanDefinition
	private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
//向IOC容器注册解析的BeanDefiniton
	@Override
	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 ex) {
			throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
					"Validation of bean definition failed", ex);
		}
	}

	BeanDefinition oldBeanDefinition;

	oldBeanDefinition = this.beanDefinitionMap.get(beanName);

	if (oldBeanDefinition != null) {
		if (!isAllowBeanDefinitionOverriding()) {
			throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
					"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
					"': There is already [" + oldBeanDefinition + "] bound.");
		}
		else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
			// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
			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 (hasBeanCreationStarted()) {
			// Cannot modify startup-time collection elements anymore (for stable iteration)
			//注册的过程中需要线程同步,以保证数据的一致性
			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 {
			// Still in startup registration phase
			this.beanDefinitionMap.put(beanName, beanDefinition);
			this.beanDefinitionNames.add(beanName);
			this.manualSingletonNames.remove(beanName);
		}
		this.frozenBeanDefinitionNames = null;
	}

	//检查是否有同名的BeanDefinition已经在IOC容器中注册
	if (oldBeanDefinition != null || containsSingleton(beanName)) {
		//重置所有已经注册过的BeanDefinition的缓存
		resetBeanDefinition(beanName);
	}
}

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

基于Annotation的IOC初始化

Annotation的前世今生

​ 从Spring2.0以后的版本中,Spring也引入了基于注解(Annotation)方式的配置,注解(Annotation)是jdk1.5中引入的一个新特性,用于简化Bean的配置,可以取代XMl配置文件。开发人员对注解(Annotation)的态度也是萝卜白菜各有所爱,个人认为注解可以大大简化配置,提高开发速度,但也给后期维护增加了难度。目前来说Xml方式的发展相对成熟,方便于统一管理。随着SpringBoot的兴起,基于注解的开发甚至实现了零配置。但作为个人的习惯而言,还是倾向于XML配置文件和注解(Annotation)相互配合使用。Spring IOC容器对于累计别的注解和类内部的注解分为以下两种策略:

  1. 类级别的注解:@Component,@Repository,@Controller,Service以及JAVAEE6的@ManagedBean@Named注解,都是天价在类上面的类级别注解,Spring容器根据注解的规则扫描读取注解Bean定义类,并将其注册到SPring IOC容器中
  2. 类内部的注解:如Autowire@Value@Resource及EJB和WebService相关的注解等,都是添加在类内部的字段或者方法上的类内部注解,Spring IOC容器通过Bean后置注解处理器解析Bean内部的注解,下面通过这两种处理策略,分别分析Spring处理注解相关的源码。

定位Bean扫描路径

​ 在Spring中管理注解Bean定义的容器由两个:AnnotationConfigApplicationContextAnnotationConfigWebApplicationContext。这两个类时专门处理Spring注解方式配置的容器,直接依赖于注解作为容器配置信息来源的IOC容器。AnnotationConfigWebApplicationContextAnnotationConfigApplicationContext的Web版本,两者的用法以及对注解的处理方式几乎没有差别。

​ 如果我们在xml中这样配置那么会使用 AnnotationConfigApplicationContext,可以参考对应将配置载入内存中的解析自定义元素

通过xml去配置解析annotation


<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"
	xmlns:context="http://www.springframework.org/schema/context">

	<context:annotation-config/>

上述使用 读取对应handler使用的是:org.springframework.context.config.ContextNamespaceHandler

在对应的

注册xml解析器

public class ContextNamespaceHandler extends NamespaceHandlerSupport {

  @Override
  public void init() {
    registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
    registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());
    registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
    registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
    registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());
    registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
    registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());
    registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());
  }
}

中定义解析annotation-config的是AnnotationConfigBeanDefinitionParser

所以我们查看AnnotationConfigBeanDefinitionParserparser方法

public class AnnotationConfigBeanDefinitionParser implements BeanDefinitionParser {

  @Override
  public BeanDefinition parse(Element element, ParserContext parserContext) {
    Object source = parserContext.extractSource(element);

    // Obtain bean definitions for all relevant BeanPostProcessors.
    //获取所有相关BeanPostProcessors的bean定义。
    Set<BeanDefinitionHolder> processorDefinitions =
      AnnotationConfigUtils.registerAnnotationConfigProcessors(parserContext.getRegistry(), source);

    // Register component for the surrounding  element.
    CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), source);
    parserContext.pushContainingComponent(compDefinition);

    // Nest the concrete beans in the surrounding component.
    for (BeanDefinitionHolder processorDefinition : processorDefinitions) {
      parserContext.registerComponent(new BeanComponentDefinition(processorDefinition));
    }

    // Finally register the composite component.
    parserContext.popAndRegisterContainingComponent();

    return null;
  }
}

在其中

声明Processor

public class AnnotationConfigUtils {

  public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
    BeanDefinitionRegistry registry, Object source) {

    DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
    if (beanFactory != null) {
      if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
        beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
      }
      if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
        beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
      }
    }

    Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<BeanDefinitionHolder>(4);

    //增加 ConfigurationClassPostProcessor
    if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
      RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
      def.setSource(source);
      beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    //增加 AutowiredAnnotationBeanPostProcessor
    if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
      RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
      def.setSource(source);
      beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    //增加RequiredAnnotationBeanPostProcessor
    if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
      RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
      def.setSource(source);
      beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
    if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
      RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
      def.setSource(source);
      beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
    if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
      RootBeanDefinition def = new RootBeanDefinition();
      try {
        def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
                                            AnnotationConfigUtils.class.getClassLoader()));
      }
      catch (ClassNotFoundException ex) {
        throw new IllegalStateException(
          "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
      }
      def.setSource(source);
      beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    //增加EventListenerMethodProcessor
    if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
      RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
      def.setSource(source);
      beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
    }
    //增加
    if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
      RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
      def.setSource(source);
      beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
    }

    return beanDefs;
  }
}

在上述默认增加了

AutowiredAnnotationBeanPostProcessor

​ 作用: 使用@autowired

``CommonAnnotationBeanPostProcessor`

​ 作用: 使用@Resource @PostConstruct @PreDestroy

PersistenceAnnotationBeanPostProcessor

​ 作用: 使用@PersistenceContext

RequiredAnnotationBeanPostProcessor

​ 作用: 使用@Required

如果我们使用就可以不适用

image-20190524121205021

因为其都调用了AnnotationConfigUtilsregisterAnnotationConfigProcessors方法

直接使用AnnotationConfigApplicationContext

现在通过AnnotationConfigApplicationContext为例查看其源码

public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {

	//保存一个读取注解的Bean定义读取器,并将其设置到容器中
	private final AnnotatedBeanDefinitionReader reader;

	//保存一个扫描指定类路径中注解Bean定义的扫描器,并将其设置到容器中
	private final ClassPathBeanDefinitionScanner scanner;

	//默认构造函数,初始化一个空容器,容器不包含任何 Bean 信息,需要在稍后通过调用其register()
	//方法注册配置类,并调用refresh()方法刷新容器,触发容器对注解Bean的载入、解析和注册过程
	public AnnotationConfigApplicationContext() {
		this.reader = new AnnotatedBeanDefinitionReader(this);
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}

	/**
	 * Create a new AnnotationConfigApplicationContext with the given DefaultListableBeanFactory.
	 * @param beanFactory the DefaultListableBeanFactory instance to use for this context
	 */
	public AnnotationConfigApplicationContext(DefaultListableBeanFactory beanFactory) {
		super(beanFactory);
		this.reader = new AnnotatedBeanDefinitionReader(this);
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}

	/**
	 * Create a new AnnotationConfigApplicationContext, deriving bean definitions
	 * from the given annotated classes and automatically refreshing the context.
	 * @param annotatedClasses one or more annotated classes,
	 * e.g. {@link Configuration @Configuration} classes
	 */
	//最常用的构造函数,通过将涉及到的配置类传递给该构造函数,以实现将相应配置类中的Bean自动注册到容器中
	public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
		this();
		register(annotatedClasses);
		refresh();
	}

	/**
	 * Create a new AnnotationConfigApplicationContext, scanning for bean definitions
	 * in the given packages and automatically refreshing the context.
	 * @param basePackages the packages to check for annotated classes
	 */
	//该构造函数会自动扫描以给定的包及其子包下的所有类,并自动识别所有的Spring Bean,将其注册到容器中
	public AnnotationConfigApplicationContext(String... basePackages) {
		this();
		scan(basePackages);
		refresh();
	}


	/**
	 * {@inheritDoc}
	 * 

Delegates given environment to underlying {@link AnnotatedBeanDefinitionReader} * and {@link ClassPathBeanDefinitionScanner} members. */ @Override public void setEnvironment(ConfigurableEnvironment environment) { super.setEnvironment(environment); this.reader.setEnvironment(environment); this.scanner.setEnvironment(environment); } //为容器的注解Bean读取器和注解Bean扫描器设置Bean名称产生器 public void setBeanNameGenerator(BeanNameGenerator beanNameGenerator) { this.reader.setBeanNameGenerator(beanNameGenerator); this.scanner.setBeanNameGenerator(beanNameGenerator); getBeanFactory().registerSingleton( AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, beanNameGenerator); } //为容器的注解Bean读取器和注解Bean扫描器设置作用范围元信息解析器 public void setScopeMetadataResolver(ScopeMetadataResolver scopeMetadataResolver) { this.reader.setScopeMetadataResolver(scopeMetadataResolver); this.scanner.setScopeMetadataResolver(scopeMetadataResolver); } //为容器注册一个要被处理的注解Bean,新注册的Bean,必须手动调用容器的 //refresh()方法刷新容器,触发容器对新注册的Bean的处理 public void register(Class<?>... annotatedClasses) { Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified"); this.reader.register(annotatedClasses); } //扫描指定包路径及其子包下的注解类,为了使新添加的类被处理,必须手动调用 //refresh()方法刷新容器 public void scan(String... basePackages) { Assert.notEmpty(basePackages, "At least one base package must be specified"); this.scanner.scan(basePackages); } }

​ 通过上述源码分析,我们可以看到Spring对注解的处理分成两种方式:

  1. 直接把注册Bean注册到容器中

    ​ 可以在初始化容器时注册,也可以在容器创建之后手动调用注册方法像容器注册,然后通过手动刷新容器,是的容器对注册的注解Bean进行处理

  2. 通过扫描指定的包以及其子包下的所有类

    ​ 在初始化注册容器式指定要自动扫描的路径,如果容器创建以后向给定路径动态的添加了注解Bean,则需要手动调用容器扫描的方法,然后手动刷新容器,使得容器对所注册的Bean进行处理。

接下来,对两种方式详细分析其具体实现过程

读取Annotation元数据

​ 当创建构建注解处理容器时,如果传入的初始参数是具体的注解Bean定义类时,注解容器读取并注册。

AnnotationConfigApplicationContext通过调用注解Bean定义读取器

AnnotatedBeanDefinitionReaderregister()方法向容器注册指定的注解Bean,注解Bean定义读取器想容器注册Bean的源码如下:

public class AnnotatedBeanDefinitionReader {

  //注册多个注解Bean定义类
  public void register(Class<?>... annotatedClasses) {
    for (Class<?> annotatedClass : annotatedClasses) {
      registerBean(annotatedClass);
    }
  }


  //注册一个注解Bean定义类
  public void registerBean(Class<?> annotatedClass) {
    doRegisterBean(annotatedClass, null, null, null);
  }


  public <T> void registerBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier) {
    doRegisterBean(annotatedClass, instanceSupplier, null, null);
  }
  //Bean定义读取器向容器注册注解Bean定义类
	<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
			@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {

		//根据指定的注解Bean定义类,创建Spring容器中对注解Bean的封装的数据结构
		AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
		if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
			return;
		}

		abd.setInstanceSupplier(instanceSupplier);
		//解析注解Bean定义的作用域,若@Scope("prototype"),则Bean为原型类型;
		//若@Scope("singleton"),则Bean为单态类型
		ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
		//为注解Bean定义设置作用域
		abd.setScope(scopeMetadata.getScopeName());
		//为注解Bean定义生成Bean名称
		String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

		//处理注解Bean定义中的通用注解
		AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
		//如果在向容器注册注解Bean定义时,使用了额外的限定符注解,则解析限定符注解。
		//主要是配置的关于autowiring自动依赖注入装配的限定条件,即@Qualifier注解
		//Spring自动依赖注入装配默认是按类型装配,如果使用@Qualifier则按名称
		if (qualifiers != null) {
			for (Class<? extends Annotation> qualifier : qualifiers) {
				//如果配置了@Primary注解,设置该Bean为autowiring自动依赖注入装//配时的首选
				if (Primary.class == qualifier) {
					abd.setPrimary(true);
				}
				//如果配置了@Lazy注解,则设置该Bean为非延迟初始化,如果没有配置,
				//则该Bean为预实例化
				else if (Lazy.class == qualifier) {
					abd.setLazyInit(true);
				}
				//如果使用了除@Primary和@Lazy以外的其他注解,则为该Bean添加一
				//个autowiring自动依赖注入装配限定符,该Bean在进autowiring
				//自动依赖注入装配时,根据名称装配限定符指定的Bean
				else {
					abd.addQualifier(new AutowireCandidateQualifier(qualifier));
				}
			}
		}
		for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
			customizer.customize(abd);
		}

		//创建一个指定Bean名称的Bean定义对象,封装注解Bean定义类数据
		BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
		//根据注解Bean定义类中配置的作用域,创建相应的代理对象
		definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
		//向IOC容器注册注解Bean类定义对象
		BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
	}

}

​ 从上述的源码可以看出,注册注解Bean定义类的基本步骤:

  • 需要使用注解元数据解析器AnnotationScopeMetadataResolverresolveScopeMetadata(BeanDefinition definition)解析注解Bean中关于作用域的配置
  • 使用AnnotationConfigUtilsprocessCommonDefinitionAnnotions()方法处理注解Bean定义类中通用的注解
  • 使用AnnotationConfigUtilsapplyScopedProxyMode()方法创建对于作用域的代理对象
  • 通过BeanDefinitionReaderUtils像容器注册Bean

接下来按照此步骤进行分析

AnnotationScopeMetadataResolver解析作用域元数据

AnnotationScopeMetadataResolverresolveScopeMetadata(BeanDefinition definition)解析注解Bean定义类的作用域原信息,即判断注册的Bean是原生类型prototype还是单例singleton类型

public class AnnotationScopeMetadataResolver implements ScopeMetadataResolver {

  //解析注解Bean定义类中的作用域元信息
  @Override
  public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
    ScopeMetadata metadata = new ScopeMetadata();
    if (definition instanceof AnnotatedBeanDefinition) {
      AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
      //从注解Bean定义类的属性中查找属性为”Scope”的值,即@Scope注解的值
      //annDef.getMetadata().getAnnotationAttributes()方法将Bean
      //中所有的注解和注解的值存放在一个map集合中
      AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(
        annDef.getMetadata(), this.scopeAnnotationType);
      //将获取到的@Scope注解的值设置到要返回的对象中
      if (attributes != null) {
        metadata.setScopeName(attributes.getString("value"));
        //获取@Scope注解中的proxyMode属性值,在创建代理对象时会用到
        ScopedProxyMode proxyMode = attributes.getEnum("proxyMode");
        //如果@Scope的proxyMode属性为DEFAULT或者NO
        if (proxyMode == ScopedProxyMode.DEFAULT) {
          //设置proxyMode为NO
          proxyMode = this.defaultProxyMode;
        }
        //为返回的元数据设置proxyMode
        metadata.setScopedProxyMode(proxyMode);
      }
    }
    //返回解析的作用域元信息对象
    return metadata;
  }
}

上述代码中的AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor( annDef.getMetadata(), this.scopeAnnotationType);就是获取对象中指定类型的注解的值

AnnotationConfigUtils处理注释Bean定义类中的通用注解

AnnotationConfigUtilsprocessCommonDefinitionAnnotations在向容器注册bean之前,首先对注解Bean定义类中的通用Spring注解进行处理,源码如下

public class AnnotationConfigUtils {

  public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) {
    processCommonDefinitionAnnotations(abd, abd.getMetadata());
  }

  //处理Bean定义中通用注解
  static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
    AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);
    //如果Bean定义中有@Lazy注解,则将该Bean预实例化属性设置为@lazy注解的值
    if (lazy != null) {
      abd.setLazyInit(lazy.getBoolean("value"));
    }

    else if (abd.getMetadata() != metadata) {
      lazy = attributesFor(abd.getMetadata(), Lazy.class);
      if (lazy != null) {
        abd.setLazyInit(lazy.getBoolean("value"));
      }
    }
    //如果Bean定义中有@Primary注解,则为该Bean设置为autowiring自动依赖注入装配的首选对象
    if (metadata.isAnnotated(Primary.class.getName())) {
      abd.setPrimary(true);
    }
    //如果Bean定义中有@ DependsOn注解,则为该Bean设置所依赖的Bean名称,
    //容器将确保在实例化该Bean之前首先实例化所依赖的Bean
    AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);
    if (dependsOn != null) {
      abd.setDependsOn(dependsOn.getStringArray("value"));
    }

    if (abd instanceof AbstractBeanDefinition) {
      AbstractBeanDefinition absBd = (AbstractBeanDefinition) abd;
      AnnotationAttributes role = attributesFor(metadata, Role.class);
      if (role != null) {
        absBd.setRole(role.getNumber("value").intValue());
      }
      AnnotationAttributes description = attributesFor(metadata, Description.class);
      if (description != null) {
        absBd.setDescription(description.getString("value"));
      }
    }
  }
}

AnnotationConfigUtils根据注解Bean定义类中配置的作用域为其应用相应的代理策略

​ AnnotationConfigUtils 类的 applyScopedProxyMode()方法根据注解 Bean 定义类中配置的作用域
@Scope 注解的值,为 Bean 定义应用相应的代理模式,主要是在 Spring 面向切面编程(AOP)中使用。
源码如下:

public class AnnotationConfigUtils {

  //根据作用域为Bean应用引用的代码模式
  static BeanDefinitionHolder applyScopedProxyMode(
    ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {

    //获取注解Bean定义类中@Scope注解的proxyMode属性值
    ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
    //如果配置的@Scope注解的proxyMode属性值为NO,则不应用代理模式
    if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
      return definition;
    }
    //获取配置的@Scope注解的proxyMode属性值,如果为TARGET_CLASS
    //则返回true,如果为INTERFACES,则返回false
    boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
    //为注册的Bean创建相应模式的代理对象
    return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
  }
}


public abstract class ScopedProxyUtils {

  public static BeanDefinitionHolder createScopedProxy(BeanDefinitionHolder definition,
                                                       BeanDefinitionRegistry registry, boolean proxyTargetClass) {

    String originalBeanName = definition.getBeanName();
    BeanDefinition targetDefinition = definition.getBeanDefinition();
    String targetBeanName = getTargetBeanName(originalBeanName);

    // Create a scoped proxy definition for the original bean name,
    // "hiding" the target bean in an internal target definition.
    RootBeanDefinition proxyDefinition = new RootBeanDefinition(ScopedProxyFactoryBean.class);
    proxyDefinition.setDecoratedDefinition(new BeanDefinitionHolder(targetDefinition, targetBeanName));
    proxyDefinition.setOriginatingBeanDefinition(targetDefinition);
    proxyDefinition.setSource(definition.getSource());
    proxyDefinition.setRole(targetDefinition.getRole());

    proxyDefinition.getPropertyValues().add("targetBeanName", targetBeanName);
    if (proxyTargetClass) {
      targetDefinition.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
      // ScopedProxyFactoryBean's "proxyTargetClass" default is TRUE, so we don't need to set it explicitly here.
    }
    else {
      proxyDefinition.getPropertyValues().add("proxyTargetClass", Boolean.FALSE);
    }

    // Copy autowire settings from original bean definition.
    proxyDefinition.setAutowireCandidate(targetDefinition.isAutowireCandidate());
    proxyDefinition.setPrimary(targetDefinition.isPrimary());
    if (targetDefinition instanceof AbstractBeanDefinition) {
      proxyDefinition.copyQualifiersFrom((AbstractBeanDefinition) targetDefinition);
    }

    // The target bean should be ignored in favor of the scoped proxy.
    targetDefinition.setAutowireCandidate(false);
    targetDefinition.setPrimary(false);

    // Register the target bean as separate bean in the factory.
    registry.registerBeanDefinition(targetBeanName, targetDefinition);

    // Return the scoped proxy definition as primary bean definition
    // (potentially an inner bean).
    return new BeanDefinitionHolder(proxyDefinition, originalBeanName, definition.getAliases());
  }
}

BeanDefinitionReaderUtils向容器注册Bean

BeanDefinitionReaderUtils主要是校验BeanDefinition信息,然后将Bean添加到容器中一个管理BeanDefinition的HashMap中

//将解析的BeanDefinitionHold注册到容器中
public static void registerBeanDefinition(
      BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
      throws BeanDefinitionStoreException {

   // Register bean definition under primary name.
   //获取解析的BeanDefinition的名称
   String beanName = definitionHolder.getBeanName();
   //向IOC容器注册BeanDefinition
   registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

   // Register aliases for bean name, if any.
   //如果解析的BeanDefinition有别名,向容器为其注册别名
   String[] aliases = definitionHolder.getAliases();
   if (aliases != null) {
      for (String alias : aliases) {
         registry.registerAlias(beanName, alias);
      }
   }

扫描指定包并解析为BeanDefinition

​ 当创建注解处理容器时,如果传入的初始参数是注解Bean定义类所在的包是,注解容器将扫描给定的包及其子包,将扫描到的注解Bean定义载入并注册

ClassPathBeanDefinitionScanner扫描给定的包及其子包

	//保存一个扫描指定类路径中注解Bean定义的扫描器,并将其设置到容器中
	private final ClassPathBeanDefinitionScanner scanner;

	//默认构造函数,初始化一个空容器,容器不包含任何 Bean 信息,需要在稍后通过调用其register()
	//方法注册配置类,并调用refresh()方法刷新容器,触发容器对注解Bean的载入、解析和注册过程
	public AnnotationConfigApplicationContext() {
		this.reader = new AnnotatedBeanDefinitionReader(this);
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}
	//该构造函数会自动扫描以给定的包及其子包下的所有类,并自动识别所有的Spring Bean,将其注册到容器中
	public AnnotationConfigApplicationContext(String... basePackages) {
		this();
		scan(basePackages);
		refresh();
	}

//扫描指定包路径及其子包下的注解类,为了使新添加的类被处理,必须手动调用
//refresh()方法刷新容器
public void scan(String... basePackages) {
  Assert.notEmpty(basePackages, "At least one base package must be specified");
  this.scanner.scan(basePackages);
}
public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider {

  //创建一个类路径Bean定义扫描器
  public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
    this(registry, true);
  }

  //为容器创建一个类路径Bean定义扫描器,并指定是否使用默认的扫描过滤规则。
  //即Spring默认扫描配置:@Component、@Repository、@Service、@Controller
  //注解的Bean,同时也支持JavaEE6的@ManagedBean和JSR-330的@Named注解
  public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry,
                                        boolean useDefaultFilters) {
    this(registry, useDefaultFilters, getOrCreateEnvironment(registry));
  }
  public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, 
                                        boolean useDefaultFilters,
                                        Environment environment) {
    this(registry, useDefaultFilters, environment,
         (registry instanceof ResourceLoader ? (ResourceLoader) registry : null));
  }
  public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, 
                                        boolean useDefaultFilters,
                                        Environment environment, 
                                        @Nullable ResourceLoader resourceLoader) {

    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    //为容器设置加载Bean定义的注册器
    this.registry = registry;

    if (useDefaultFilters) {
      registerDefaultFilters();
    }
    setEnvironment(environment);
    //为容器设置资源加载器
    setResourceLoader(resourceLoader);
  }

  //调用类路径Bean定义扫描器入口方法
  public int scan(String... basePackages) {
    //获取容器中已经注册的Bean个数
    int beanCountAtScanStart = this.registry.getBeanDefinitionCount();

    //启动扫描器扫描给定包
    doScan(basePackages);

    // Register annotation config processors, if necessary.
    //注册注解配置(Annotation config)处理器
    if (this.includeAnnotationConfig) {
      AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
    }

    //返回注册的Bean个数
    return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
  }

  //类路径Bean定义扫描器扫描给定包及其子包
  protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
    Assert.notEmpty(basePackages, "At least one base package must be specified");
    //创建一个集合,存放扫描到Bean定义的封装类
    Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
    //遍历扫描所有给定的包
    for (String basePackage : basePackages) {
      //调用父类ClassPathScanningCandidateComponentProvider的方法
      //扫描给定类路径,获取符合条件的Bean定义
      Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
      //遍历扫描到的Bean
      for (BeanDefinition candidate : candidates) {
        //获取Bean定义类中@Scope注解的值,即获取Bean的作用域
        ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
        //为Bean设置注解配置的作用域
        candidate.setScope(scopeMetadata.getScopeName());
        //为Bean生成名称
        String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
        //如果扫描到的Bean不是Spring的注解Bean,则为Bean设置默认值,
        //设置Bean的自动依赖注入装配属性等
        if (candidate instanceof AbstractBeanDefinition) {
          postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
        }
        //如果扫描到的Bean是Spring的注解Bean,则处理其通用的Spring注解
        if (candidate instanceof AnnotatedBeanDefinition) {
          //处理注解Bean中通用的注解,在分析注解Bean定义类读取器时已经分析过
          AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
        }
        //根据Bean名称检查指定的Bean是否需要在容器中注册,或者在容器中冲突
        if (checkCandidate(beanName, candidate)) {
          BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
          //根据注解中配置的作用域,为Bean应用相应的代理模式
          definitionHolder =
            AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
          beanDefinitions.add(definitionHolder);
          //向容器注册扫描到的Bean
          registerBeanDefinition(definitionHolder, this.registry);
        }
      }
    }
    return beanDefinitions;
  }
}

ClassPathScanningCandidateComponentProvider扫描给定包及其子包的类

ClassPathScanningCanididateComponentProvider类的findCandidateComponents()方法具体实现扫描类给定类路径包的功能,主要源码如下:

public class ClassPathScanningCandidateComponentProvider implements EnvironmentCapable, ResourceLoaderAware {
  //向容器注册过滤规则
  @SuppressWarnings("unchecked")
  protected void registerDefaultFilters() {
    //向要包含的过滤规则中添加@Component注解类,注意Spring中@Repository
    //@Service和@Controller都是Component,因为这些注解都添加了@Component注解
    this.includeFilters.add(new AnnotationTypeFilter(Component.class));
    //获取当前类的类加载器
    ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
    try {
      //向要包含的过滤规则添加JavaEE6的@ManagedBean注解
      this.includeFilters.add(new AnnotationTypeFilter(
        ((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
      logger.debug("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
    }
    catch (ClassNotFoundException ex) {
      // JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
    }
    try {
      //向要包含的过滤规则添加@Named注解
      this.includeFilters.add(new AnnotationTypeFilter(
        ((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
      logger.debug("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
    }
    catch (ClassNotFoundException ex) {
      // JSR-330 API not available - simply skip.
    }
  }
  //扫描给定类路径的包
  public Set<BeanDefinition> findCandidateComponents(String basePackage) {
    if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
      return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
    }
    else {
      return scanCandidateComponents(basePackage);
    }
  }
  private Set<BeanDefinition> addCandidateComponentsFromIndex(CandidateComponentsIndex index, String basePackage) {
    //创建存储扫描到的类的集合
    Set<BeanDefinition> candidates = new LinkedHashSet<>();
    try {
      Set<String> types = new HashSet<>();
      for (TypeFilter filter : this.includeFilters) {
        String stereotype = extractStereotype(filter);
        if (stereotype == null) {
          throw new IllegalArgumentException("Failed to extract stereotype from "+ filter);
        }
        types.addAll(index.getCandidateTypes(basePackage, stereotype));
      }
      boolean traceEnabled = logger.isTraceEnabled();
      boolean debugEnabled = logger.isDebugEnabled();
      for (String type : types) {
        //为指定资源获取元数据读取器,元信息读取器通过汇编(ASM)读//取资源元信息
        MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(type);
        //如果扫描到的类符合容器配置的过滤规则
        if (isCandidateComponent(metadataReader)) {
          //通过汇编(ASM)读取资源字节码中的Bean定义元信息
          AnnotatedGenericBeanDefinition sbd = new AnnotatedGenericBeanDefinition(
            metadataReader.getAnnotationMetadata());
          if (isCandidateComponent(sbd)) {
            if (debugEnabled) {
              logger.debug("Using candidate component class from index: " + type);
            }
            candidates.add(sbd);
          }
          else {
            if (debugEnabled) {
              logger.debug("Ignored because not a concrete top-level class: " + type);
            }
          }
        }
        else {
          if (traceEnabled) {
            logger.trace("Ignored because matching an exclude filter: " + type);
          }
        }
      }
    }
    catch (IOException ex) {
      throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
    }
    return candidates;
  }

  private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
    Set<BeanDefinition> candidates = new LinkedHashSet<>();
    try {
      String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
        resolveBasePackage(basePackage) + '/' + this.resourcePattern;
      Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
      boolean traceEnabled = logger.isTraceEnabled();
      boolean debugEnabled = logger.isDebugEnabled();
      for (Resource resource : resources) {
        if (traceEnabled) {
          logger.trace("Scanning " + resource);
        }
        if (resource.isReadable()) {
          try {
            MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
            if (isCandidateComponent(metadataReader)) {
              ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
              sbd.setResource(resource);
              sbd.setSource(resource);
              if (isCandidateComponent(sbd)) {
                if (debugEnabled) {
                  logger.debug("Identified candidate component class: " + resource);
                }
                candidates.add(sbd);
              }
              else {
                if (debugEnabled) {
                  logger.debug("Ignored because not a concrete top-level class: " + resource);
                }
              }
            }
            else {
              if (traceEnabled) {
                logger.trace("Ignored because not matching any filter: " + resource);
              }
            }
          }
          catch (Throwable ex) {
            throw new BeanDefinitionStoreException(
              "Failed to read candidate component class: " + resource, ex);
          }
        }
        else {
          if (traceEnabled) {
            logger.trace("Ignored because not readable: " + resource);
          }
        }
      }
    }
    catch (IOException ex) {
      throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
    }
    return candidates;
  }
}

注册注解BeanDefinition

AnnotationConfigWebApplicationContextAnnotationConfigApplicationContext的WEB版,他们对于注解Bean的注册和扫描是基本相同的,但是AnnotationConfigWebApplicationContext对注解Bean定义的载入稍有不同,AnnotationConfigWebApplicationContext注入注解Bean定义源码如下

@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) {
   //为容器设置注解Bean定义读取器
   AnnotatedBeanDefinitionReader reader = getAnnotatedBeanDefinitionReader(beanFactory);
   //为容器设置类路径Bean定义扫描器
   ClassPathBeanDefinitionScanner scanner = getClassPathBeanDefinitionScanner(beanFactory);

   //获取容器的Bean名称生成器
   BeanNameGenerator beanNameGenerator = getBeanNameGenerator();
   //为注解Bean定义读取器和类路径扫描器设置Bean名称生成器
   if (beanNameGenerator != null) {
      reader.setBeanNameGenerator(beanNameGenerator);
      scanner.setBeanNameGenerator(beanNameGenerator);
      beanFactory.registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, beanNameGenerator);
   }

   //获取容器的作用域元信息解析器
   ScopeMetadataResolver scopeMetadataResolver = getScopeMetadataResolver();
   //为注解Bean定义读取器和类路径扫描器设置作用域元信息解析器
   if (scopeMetadataResolver != null) {
      reader.setScopeMetadataResolver(scopeMetadataResolver);
      scanner.setScopeMetadataResolver(scopeMetadataResolver);
   }

   if (!this.annotatedClasses.isEmpty()) {
      if (logger.isInfoEnabled()) {
         logger.info("Registering annotated classes: [" +
               StringUtils.collectionToCommaDelimitedString(this.annotatedClasses) + "]");
      }
      reader.register(this.annotatedClasses.toArray(new Class<?>[this.annotatedClasses.size()]));
   }

   if (!this.basePackages.isEmpty()) {
      if (logger.isInfoEnabled()) {
         logger.info("Scanning base packages: [" +
               StringUtils.collectionToCommaDelimitedString(this.basePackages) + "]");
      }
      scanner.scan(this.basePackages.toArray(new String[this.basePackages.size()]));
   }

   //获取容器定义的Bean定义资源路径
   String[] configLocations = getConfigLocations();
   //如果定位的Bean定义资源路径不为空
   if (configLocations != null) {
      for (String configLocation : configLocations) {
         try {
            //使用当前容器的类加载器加载定位路径的字节码类文件
            Class<?> clazz = ClassUtils.forName(configLocation, getClassLoader());
            if (logger.isInfoEnabled()) {
               logger.info("Successfully resolved class for [" + configLocation + "]");
            }
            reader.register(clazz);
         }
         catch (ClassNotFoundException ex) {
            if (logger.isDebugEnabled()) {
               logger.debug("Could not load class for config location [" + configLocation +
                     "] - trying package scan. " + ex);
            }
            //如果容器类加载器加载定义路径的Bean定义资源失败
            //则启用容器类路径扫描器扫描给定路径包及其子包中的类
            int count = scanner.scan(configLocation);
            if (logger.isInfoEnabled()) {
               if (count == 0) {
                  logger.info("No annotated classes found for specified class/package [" + configLocation + "]");
               }
               else {
                  logger.info("Found " + count + " annotated classes in package [" + configLocation + "]");
               }
            }
         }
      }
   }
}

IOC容器初始化小结

​ 现在通过上面的代码,总结一下IOC容器初始化的基本步骤:

​ 1.初始化的入口在容器实现中的refresh()调用来完成

​ 2.对Bean定义载入IOC容器使用的方式是loadBeanDefinition()

​ 其中的大致过程如下:

​ 通过ResouceLoader来完成资源文件位置的定位,DefaultResourceLoader是默认的实现,同时上下文本身就给出了ResourceLoader的实现,可以从类路径,文件系统,URL等方式来定位资源文件,如果是XmlBeanFactory作为IOC容器,那么需要为它指定Bean定义的资源,也就是说Bean定义文件是通过抽象成Resouce来呗IOC容器处理的,容器通过BeanDefinitionReader来完成定义信息的解析和Bean信息的注册,往往使用的是XmlBeanDefintionReader来解析Bean的XML定义文件,实际处理过程是委托给BeanDefinitionParserDelegate来完成的,从而得到Bean的定义信息,这些信息在Spring中使用BeanDefinition对象来表示,这个名字可以让我们想到loadBeanDefinition(),registerBeanDefinition()这些相关方法,他们都是为处理BeanDefinition服务的,容器解析得到BeanDefiniton以后,需要把它在IOC容器中注册,这由IOC实现BeanDefinitionRegistry接口来实现。注册过程就是在IOC容器内部维护的一个HashMap来保存得到的BeanDefinition的过程,这个HashMap是IOC容器持有的Bean信息的场所,以后对Bean的操作都是围绕这个HashMap来实现的。

​ 然后我们就可以使用BeanFactoryApplicationContext来享受到SpringIOC的服务了,在使用IOC容器的时候,我们注意到除了少量粘合代码,绝大多数以正确IOC风格编写的应用程序代码完全不用关心如何到达工厂,因为容器把这些对象和容器管理的其他对象关联在一起,基本的策略是把工厂放到已知的地方,最好是放在对预期使用的上下文有意义的地方,以及代码将实际需要访问工厂的地方。Spring本身提供了对声明式载入web应用程序用法的应用程序上下文,将其存储在ServletContext的框架实现。

Spring ioc源码分析_第9张图片

你可能感兴趣的:(Spring)