天天看点

Spring 之 IOC 详解(基于注解方式)

概念

IOC(Inversion of Control)控制反转:所谓控制反转,就是应用本身不负责依赖对象的创建和维护,依赖对象的创建及维护是由外部容器负责的。这样控制权就有应用转移到了外部容器,控制权的转移就是控制反转。

初始化过程

Spring IOC容器的初始化简单的可以分为三个过程:

  • 第一个过程是Resource资源定位。这个Resouce指的是BeanDefinition的资源定位。这个过程就是容器找数据的过程,就像水桶装水需要先找到水一样。
  • 第二个过程是BeanDefinition的载入过程。这个载入过程是把用户定义好的Bean表示成Ioc容器内部的数据结构,而这个容器内部的数据结构就是BeanDefition。
  • 第三个过程是向IOC容器注册这些BeanDefinition的过程,这个过程就是将前面的BeanDefition保存到HashMap中的过程。

注解

从 Spring2.0 以后的版本中,Spring 也引入了基于注解(Annotation)方式的配置,注解(Annotation)是 JDK1.5 中引入的一个新特性,用于简化 Bean 的配置,可以取代 XML 配置文件。Spring IOC 容器对于类级别的注解和类内部的注解分以下两种处理策略:

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

主要类

核心容器

Spring Bean 的创建是典型的工厂模式,这一系列的 Bean 工厂,也即 IOC 容器为开发者管理对象间的依赖关系提供了很多便利和基础服务,在 Spring 中有许多的 IOC 容器的实现供用户选择和使用,其相互关系如下:

Spring 之 IOC 详解(基于注解方式)

其中 BeanFactory 作为最顶层的一个接口类,它定义了 IOC 容器的基本功能规范,BeanFactory 有三个重要的子类:ListableBeanFactory、HierarchicalBeanFactory 和 AutowireCapableBeanFactory。但是从类图中我们可以发现最终的默认实现类是 DefaultListableBeanFactory,它实现了所有的接口。同时 DefaultListableBeanFactory 也是一个注册器,向工厂注册 Bean 按照封装完的数据结构注册信息。

数据结构

Spring IOC 容器管理了我们定义的各种 Bean 对象及其相互的关系,Bean 对象在 Spring 实现中是以 BeanDefinition 来描述的,其继承体系如下:

Spring 之 IOC 详解(基于注解方式)

资源扫描器

基于注解的方式需要将指定路径下的所有类都加载进来,在 Spring 中主要是在 ClassPathBeanDefinitionScanner 类中进行实现。类图如下:

Spring 之 IOC 详解(基于注解方式)

原理

接下来我们就来根据源码的方式了解 Spring 注解方式的实现原理。

在 Spring 中 管 理 注 解 Bean 定 义 的 容 器 有 两 个 : AnnotationConfigApplicationContext 和 AnnotationConfigWebApplicationContex。这两个类是专门处理 Spring 注解方式配置的容器,直接依赖于注解作为容器配置信息来源的 IOC 容器。AnnotationConfigWebApplicationContext 是 AnnotationConfigApplicationContext 的 Web 版本,两者的用法以及对注解的处理方式几乎没有差别。现在我们以 AnnotationConfigApplicationContext 为例,从构造方法为入口进行分析:

public AnnotationConfigApplicationContext(String... basePackages) {
	this();
	scan(basePackages);
	refresh();
}
           

该构造函数会自动扫描已给定的包及其子包下的所有类,并自动识别所有的Spring Bean 将其注册到容器中。

扫描

我们先来看看 Spring 是如何扫描指定路径下的 Bean 并注册到容器中。

public void scan(String... basePackages) {
	Assert.notEmpty(basePackages, "At least one base package must be specified");
	this.scanner.scan(basePackages);
}
           

跳转到ClassPathBeanDefinitionScanner.scanner() 方法上,调用类路径扫描器入口方法。

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);
}
           

扫描给定包及子包,并将扫描到的 BeanDefinition 进行初始属性设置后注册到容器中。源码如下:

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) {
		//扫描给定类路径,获取符合条件的BeanDefinition
		Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
		//遍历扫描到的Bean
		for (BeanDefinition candidate : candidates) {
			//获取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);
			}
			//如果是Spring的注解Bean,则处理通用的注解
			if (candidate instanceof AnnotatedBeanDefinition) {
				AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
			}
			//根据Bean名称检查指定Bean是否已在容器中注册过,如果注册过则判断两个BeanDefinition是否兼容,不兼容则抛出异常
			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;
}
           

扫描给定路径的包下的所有资源数据,读取元数据封装成 BeanDefinition 集合返回。

public Set<BeanDefinition> findCandidateComponents(String basePackage) {
	if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
		return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
	}
	else {
		return scanCandidateComponents(basePackage);
	}
}
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 {
					//为指定资源获取元数据读取器,元数据读取器通过ASM读取资源的元信息
					MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
					//判断元信息读取器读取的类是否符合容器定义的注解过滤规则
					if (isCandidateComponent(metadataReader)) {
						//通过元数据读取器获得一个通用扫描的BeanDefinition
						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;
}
           

判断元信息读取器读取的类是否符合容器定义的注解过滤规则

protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
	//如果读取的类的注解在排除规则中,返回false
	for (TypeFilter tf : this.excludeFilters) {
		if (tf.match(metadataReader, getMetadataReaderFactory())) {
			return false;
		}
	}
	//如果读取的类的注解在包含的注解过滤规则中,则返回true
	for (TypeFilter tf : this.includeFilters) {
		if (tf.match(metadataReader, getMetadataReaderFactory())) {
			return isConditionMatch(metadataReader);
		}
	}
	//如果读取的类的注解既不在排除规则中,也不在包含规则中,则返回false
	return false;
}
           

至此扫描完成,扫描指定路径下的所有包并封装成 BeanDefinition 集合。

注册

先来看下获取 Bean 作用域的方法,因为作用域对 Spring 创建 Bean 代理对象产生很大的影响。AnnotationScopeMetadataResolver 通过 resolveScopeMetadata() 方法解析注解 Bean 定义类的作用域元信息,即判断注册的 Bean 是原生类型(prototype)还是单态(singleton)类型。源码如下:

public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
	ScopeMetadata metadata = new ScopeMetadata();
	if (definition instanceof AnnotatedBeanDefinition) {
		AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
		//从注解Bean定义类的属性中查找属性为Scope的值,即@Scope注解的值
		//annDef.getMetadata()将Bean中所有的注解和注解的值存放在map中
		AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(
				annDef.getMetadata(), this.scopeAnnotationType);
		//将获取的scope注解的值设置到要返回的对象中
		if (attributes != null) {
			metadata.setScopeName(attributes.getString("value"));
			//获取ProxyMode属性值,在创建代理对象的时候回用
			ScopedProxyMode proxyMode = attributes.getEnum("proxyMode");
			//设置proxyMode的属性值
			if (proxyMode == ScopedProxyMode.DEFAULT) {
				proxyMode = this.defaultProxyMode;
			}
			//为返回的元数据设置proxyMode
			metadata.setScopedProxyMode(proxyMode);
		}
	}
	return metadata;
}
           

AnnotationConfigUtils 类的 processCommonDefinitionAnnotations() 在向容器注册 Bean 之前,先对 Spring 的注解 Bean 通用注解进行处理。源码如下:

static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
	//设置Lazy注解属性的值
	AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);
	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"));
		}
	}

	//判断是否有@Primary注解,如果有则设置为依赖注入装配的首选对象
	if (metadata.isAnnotated(Primary.class.getName())) {
		abd.setPrimary(true);
	}
	//如果有@DependsOn注解,则设置需要依赖的Bean名称
	//容器确保在实例化该bean前先实例化所依赖的bean
	AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);
	if (dependsOn != null) {
		abd.setDependsOn(dependsOn.getStringArray("value"));
	}

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

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

static BeanDefinitionHolder applyScopedProxyMode(
		ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {

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

在上述对 BeanDefinition 完成一系列属性设置后,接下来才是正式注册 BeanDefinition 到容器中。通过 BeanDefinitionReaderUtils.registerBeanDefinition() 方法进行注入,源码如下:

public static void registerBeanDefinition(
		BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
		throws BeanDefinitionStoreException {

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

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

跳转到 DefaultListableBeanFactory.registerBeanDefinition() 方法上,从开始对核心容器进行梳理时就说过 DefaultListableBeanFactory 不仅是一个容器也是一个注册器。注册源码如下:

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
		throws BeanDefinitionStoreException {

	Assert.hasText(beanName, "Bean name must not be empty");
	Assert.notNull(beanDefinition, "BeanDefinition must not be null");

	//检验解析的BeanDefinition
	if (beanDefinition instanceof AbstractBeanDefinition) {
		try {
			((AbstractBeanDefinition) beanDefinition).validate();
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
					"Validation of bean definition failed", ex);
		}
	}

	BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
	if (existingDefinition != null) {
		//是否允许覆盖上一个相同beanName的beanDefinition
		if (!isAllowBeanDefinitionOverriding()) {
			throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
		}
		else if (existingDefinition.getRole() < beanDefinition.getRole()) {
			if (logger.isInfoEnabled()) {
				logger.info("Overriding user-defined bean definition for bean '" + beanName +
						"' with a framework-generated bean definition: replacing [" +
						existingDefinition + "] with [" + beanDefinition + "]");
			}
		}
		else if (!beanDefinition.equals(existingDefinition)) {
			if (logger.isDebugEnabled()) {
				logger.debug("Overriding bean definition for bean '" + beanName +
						"' with a different definition: replacing [" + existingDefinition +
						"] with [" + beanDefinition + "]");
			}
		}
		else {
			if (logger.isTraceEnabled()) {
				logger.trace("Overriding bean definition for bean '" + beanName +
						"' with an equivalent definition: replacing [" + existingDefinition +
						"] with [" + beanDefinition + "]");
			}
		}
		this.beanDefinitionMap.put(beanName, beanDefinition);
	}
	else {
		if (hasBeanCreationStarted()) {
			//注册的过程中需要线程同步,以保证数据的一致性
			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;
				//维护单例名称集合
				removeManualSingletonName(beanName);
			}
		}
		else {
			// 仍处于启动注册阶段
			this.beanDefinitionMap.put(beanName, beanDefinition);
			this.beanDefinitionNames.add(beanName);
			removeManualSingletonName(beanName);
		}
		this.frozenBeanDefinitionNames = null;
	}

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

来看下 DefaultListableBeanFactory 重要的两个属性:

//存储注册信息的BeanDefinition
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
//存储所有已经注册的BeanName
private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
           

至此完成了 IOC 容器注册的整个过程,将指定路径下的所有包的 BeanDefinition 注册到容器中。

刷新容器

在将指定路径扫描注册完成后,会调用 AbstractApplicationContext.refresh 方法完成容器刷新的过程。

public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		// Prepare this context for refreshing.
		// 调用容器准备刷新的方法,获取容器的当前时间,同时给容器设置同步标识
		prepareRefresh();

		// Tell the subclass to refresh the internal bean factory.
		// 从资源路径获取bean信息并封装成beanDefinition注册到beanFactory的beanDefinitionMap中
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

		// Prepare the bean factory for use in this context.
		// beanFactory的预准备工作,对beanFactory配置容器特性,例如类加载器、事件处理器等
		prepareBeanFactory(beanFactory);

		try {
			// Allows post-processing of the bean factory in context subclasses.
			//beanFactory准备工作完成之后要进行的后置处理工作,留给子类扩展使用
			postProcessBeanFactory(beanFactory);

			// Invoke factory processors registered as beans in the context.
			// 执行BeanFactory的后置处理器,在BeanFactory标准初始化之后执行的
			// 调用所有注册的BeanFactoryPostProcessor的postProcessBeanFactory方法
			invokeBeanFactoryPostProcessors(beanFactory);

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

			// Initialize message source for this context.
			//初始化MessageSource信息源,即国际化处理、消息绑定、消息解析
			initMessageSource();

			// Initialize event multicaster for this context.
			//初始化容器事件广播器,并放入applicationEventMulticaster bean中
			initApplicationEventMulticaster();

			// Initialize other special beans in specific context subclasses.
			//留给子类来初始化其他的bean
			onRefresh();

			// Check for listener beans and register them.
			//在所有注册的bean中查找ApplicationListener,为事件广播器注册事件监听器
			registerListeners();

			// Instantiate all remaining (non-lazy-init) singletons.
			//初始化所有剩下的非懒加载单实例bean
			finishBeanFactoryInitialization(beanFactory);

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

			// Reset 'active' flag.
			// 取消刷新操作,重置容器的同步标识
			cancelRefresh(ex);

			// Propagate exception to caller.
			throw ex;
		}

		finally {
			// Reset common introspection caches in Spring's core, since we
			// might not ever need metadata for singleton beans anymore...
			// 重置公共缓存
			resetCommonCaches();
		}
	}
}
           

今天我们主要对 IOC 容器注册过程进行分析,所以只分析其中的 obtainFreshBeanFactory 方法。源码如下:

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
	//重新从资源路径下获取bean信息,刷新beanfactory
	//这里使用了委派设计模式,父类定义了抽象的refreshBeanFactory()方法,具体实现调用子类容器的refreshBeanFactory()方法
	refreshBeanFactory();
	//返回当前实体的beanfactory属性
	return getBeanFactory();
}
           

跳转到 AbstractRefreshableApplicationContext.refreshBeanFactory() 方法上。此实现对此上下文的基础 BeanFactory 进行实际刷新,关闭前一个 BeanFactory(如果有),并为上下文生命周期的下一阶段初始化一个新 BeanFactory。

protected final void refreshBeanFactory() throws BeansException {
	// 判断是否有BeanFactory,如果已经有容器,则销毁容器中的Bean,关闭容器
	if (hasBeanFactory()) {
		destroyBeans();
		closeBeanFactory();
	}
	try {
		//创建DefaultListableBeanFactory,IOC容器
		DefaultListableBeanFactory beanFactory = createBeanFactory();
		//设置序列化id
		beanFactory.setSerializationId(getId());
		//定制beanFactory,设置相关属性,如设置启动参数、开启注解的自动装配等
		customizeBeanFactory(beanFactory);
		//调用载入Bean定义的方法,此类只是定义了抽象方法,通过子类容器实现
		loadBeanDefinitions(beanFactory);
		synchronized (this.beanFactoryMonitor) {
			this.beanFactory = beanFactory;
		}
	}
	catch (IOException ex) {
		throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
	}
}
           

接下来主要看如何对加载 BeanDefinition ,并注册到容器中。AnnotationConfigWebApplicationContext.loadBeanDefinitions() 方法源码如下:

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.componentClasses.isEmpty()) {
		if (logger.isDebugEnabled()) {
			logger.debug("Registering component classes: [" +
					StringUtils.collectionToCommaDelimitedString(this.componentClasses) + "]");
		}
		reader.register(ClassUtils.toClassArray(this.componentClasses));
	}

	if (!this.basePackages.isEmpty()) {
		if (logger.isDebugEnabled()) {
			logger.debug("Scanning base packages: [" +
					StringUtils.collectionToCommaDelimitedString(this.basePackages) + "]");
		}
		scanner.scan(StringUtils.toStringArray(this.basePackages));
	}

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

我们可以看到一样调用了 ClassPathBeanDefinitionScanner.sacnner() 方法进行扫描并加载到容器中。跟上面扫描流程一致,就不重复分析。接下来获取容器中 BeanDefinition 的资源路径,并加载到容器中。与上面注册流程一直,也不重复分析。

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

总结

通过注解的方式向 Spring IOC 容器注入指定路径资源下的所有 BeanDefinition,与 XML 配置文件的方式相比。加载资源封装成 BeanDefinition 流程不同,将 BeanDefinition 注册到容器中的流程一致。