Spring的IOC注解

定位 Bean 扫描路径

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

//保存一个读取注解的 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);
}

   //为容器的注解 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);
}

   //扫描指定包路径及其子包下的注解类,为了使新添加的类被处理,必须手动调用 
   //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 定义类
public void registerBean(Class<?> annotatedClass, String name, Class<? extends Annotation>... qualifiers) {
	doRegisterBean(annotatedClass, null, name, qualifiers);
}

/**
 * Register a bean from the given bean class, deriving its metadata from
 * class-declared annotations.
 * @param annotatedClass the class of the bean
 * @param instanceSupplier a callback for creating an instance of the bean
 * (may be {@code null})
 * @param name an explicit name for the bean
 * @param qualifiers specific qualifier annotations to consider, if any,
 * in addition to qualifiers at the bean class level
 * @param definitionCustomizers one or more callbacks for customizing the
 * factory's {@link BeanDefinition}, e.g. setting a lazy-init or primary flag
 * @since 5.0
 */
    //Bean 定义读取器向容器注册注解 Bean 定义类
<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
		@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {

	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 定义时,使用了额外的限定符注解,则解析限定符注解。
       //主要是配置的关于 autowiring 自动依赖注入装配的限定条件,即@Qualifier 注解 
       //Spring 自动依赖注入装配默认是按类型装配,如果使用@Qualifier 则按名称
	AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
	if (qualifiers != null) {
		for (Class<? extends Annotation> qualifier : qualifiers) {
			if (Primary.class == qualifier) {
				abd.setPrimary(true);
			}else if (Lazy.class == qualifier) {
				abd.setLazyInit(true);
			}else {
                   //如果使用了除@Primary 和@Lazy 以外的其他注解,则为该 Bean 添加一 
                   //个 autowiring 自动依赖注入装配限定符,该 Bean 在进 autowiring 
                   //自动依赖注入装配时,根据名称装配限定符指定的 Bean
				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 定义类的基本步骤:

  1. 需要使用注解元数据解析器解析注解 Bean 中关于作用域的配置。
  2. 使用 AnnotationConfigUtils 的 processCommonDefinitionAnnotations()方法处理注解 Bean 定 义类中通用的注解。
  3. 使用 AnnotationConfigUtils 的 applyScopedProxyMode()方法创建对于作用域的代理对象。
  4. 通过 BeanDefinitionReaderUtils 向容器注册 Bean。
  • AnnotationScopeMetadataResolver 解析作用域元数据

AnnotationScopeMetadataResolver 通过 resolveScopeMetadata()方法解析注解 Bean 定义类的作 用域元信息,即判断注册的 Bean 是原生类型(prototype)还是单态(singleton)类型

@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 = this.defaultProxyMode;
			}
			metadata.setScopedProxyMode(proxyMode);
		}
	}
	return metadata;
}
  • AnnotationConfigUtils 处理注解 Bean 定义类中的通用注解

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

		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 根据注解 Bean 定义类中配置的作用域为其应用相应的代理策略

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


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

  • BeanDefinitionReaderUtils 向容器注册 Bean
public static void registerBeanDefinition(
			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
			throws BeanDefinitionStoreException {

		// Register bean definition under primary name.
		String beanName = definitionHolder.getBeanName();
		registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

		// Register aliases for bean name, if any.
		String[] aliases = definitionHolder.getAliases();
		if (aliases != null) {
			for (String alias : aliases) {
				registry.registerAlias(beanName, alias);
			}
		}
	}
	
	//这里注册BeanDefinition 和 xml方式注册方式一模一样
	@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");

		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) {
			if (!isAllowBeanDefinitionOverriding()) {
				throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
			}
			else if (existingDefinition.getRole() < beanDefinition.getRole()) {
				// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
				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()) {
				// 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;
					removeManualSingletonName(beanName);
				}
			}
			else {
				// Still in startup registration phase
				this.beanDefinitionMap.put(beanName, beanDefinition);
				this.beanDefinitionNames.add(beanName);
				removeManualSingletonName(beanName);
			}
			this.frozenBeanDefinitionNames = null;
		}

		if (existingDefinition != null || containsSingleton(beanName)) {
			resetBeanDefinition(beanName);
		}
		else if (isConfigurationFrozen()) {
			clearByTypeCache();
		}
	}

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

扫描指定包并解析为 BeanDefinition

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

  • ClassPathBeanDefinitionScanner 扫描给定的包及其子包

ClassPathBeanDefinitionScanner与ClassPathScanningCandidateComponentProvider是父子关系

入口在AnnotationConfigApplicationContext类中,扫描指定的包路径。

@Override
public void scan(String... basePackages) {
	Assert.notEmpty(basePackages, "At least one base package must be specified");
	this.scanner.scan(basePackages);
}
public int scan(String... basePackages) {
		int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
		doScan(basePackages);
		// Register annotation config processors, if necessary.
		if (this.includeAnnotationConfig) {
			AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
		}
		return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
	}

	/**
	 * Perform a scan within the specified base packages,
	 * returning the registered bean definitions.
	 * <p>This method does <i>not</i> register an annotation config processor
	 * but rather leaves this up to the caller.
	 * @param basePackages the packages to check for annotated classes
	 * @return set of beans registered if any for tooling registration purposes (never {@code null})
	 */
	 //这里的方式和XML的扫描指定的路径包其实一样。
	 //调用链路,和AnnotationConfigApplicationContext 中的register类似。
	protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
		Assert.notEmpty(basePackages, "At least one base package must be specified");
		Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
		for (String basePackage : basePackages) {
			//ClassPathScanningCandidateComponentProvider中的findCandidateComponents()方法,他们是父子关系
			Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
			for (BeanDefinition candidate : candidates) {
				ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
				candidate.setScope(scopeMetadata.getScopeName());
				String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
				if (candidate instanceof AbstractBeanDefinition) {
					postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
				}
				if (candidate instanceof AnnotatedBeanDefinition) {
					AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
				}
				if (checkCandidate(beanName, candidate)) {
					BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
					definitionHolder =
							AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
					beanDefinitions.add(definitionHolder);
					registerBeanDefinition(definitionHolder, this.registry);
				}
			}
		}
		return beanDefinitions;
	}
  • ClassPathScanningCandidateComponentProvider 扫描给定包及其子包的类
//核心的扫描方法。
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.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

AnnotationConfigWebApplicationContext 是 AnnotationConfigApplicationContext 的 Web 版, 它们对于注解 Bean 的注册和扫描是基本相同的,但是 AnnotationConfigWebApplicationContext 对注解 Bean 定义的载入稍有不同,AnnotationConfigWebApplicationContext 注入注解 Bean 定义


@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");

	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) {
		if (!isAllowBeanDefinitionOverriding()) {
			throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
		}
		else if (existingDefinition.getRole() < beanDefinition.getRole()) {
			// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
			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()) {
			// 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;
	}

	if (existingDefinition != null || containsSingleton(beanName)) {
		resetBeanDefinition(beanName);
	}
}

总结

IOC 容器初始化的基本步骤:

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

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

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


文章作者: 凌云
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 凌云 !
  目录