spring 源码(二) 注解扫描的过程

在之前的博客中,分析bean扫描的时候,看到这个过程是在ConfigurationClassPostProcessor这个后置处理器中执行的,这里来仔细分析一下其中的过程。

首先进入ConfigurationClassPostProcessor这个类,找到processConfigBeanDefinitions方法,在这个方法中,会创建一个ConfigurationClassParser类,调用paser方法,传入javaconfig的配置类,这个配置类在spring容器最开始的代码register方法中生成BeanDefinition。

public void parse(Set<BeanDefinitionHolder> configCandidates) {
		for (BeanDefinitionHolder holder : configCandidates) {
			BeanDefinition bd = holder.getBeanDefinition();
			try {
				if (bd instanceof AnnotatedBeanDefinition) {
					parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
				}
				else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
					parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
				}
				else {
					parse(bd.getBeanClassName(), holder.getBeanName());
				}
			}
			catch (BeanDefinitionStoreException ex) {
				throw ex;
			}
			catch (Throwable ex) {
				throw new BeanDefinitionStoreException(
						"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
			}
		}

		this.deferredImportSelectorHandler.process();
	}

从上面的代码中看出,会去判断BeanDefinition的类型,这里分析注解扫描,所以会是一个AnnotatedBeanDefinition ,接着会去调用processConfigurationClass方法

protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
		processConfigurationClass(new ConfigurationClass(metadata, beanName));
	}

这里先判断了一下conditional,先跳过,接着处理了重复导入的情况,如果都是import导入的,那就合并,否则覆盖。

再往下创建一个SourceClass,接着执行doProcessConfigurationClass方法,最后将configClass放入configurationClasses这个map中,如果下次再进来这个方法,就能获取到,就能进入if条件中了

protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
		if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
			return;
		}

		ConfigurationClass existingClass = this.configurationClasses.get(configClass);
		if (existingClass != null) {
			if (configClass.isImported()) {
				if (existingClass.isImported()) {
					existingClass.mergeImportedBy(configClass);
				}
				// Otherwise ignore new imported config class; existing non-imported class overrides it.
				return;
			}
			else {
				// Explicit bean definition found, probably replacing an import.
				// Let's remove the old one and go with the new one.
				this.configurationClasses.remove(configClass);
				this.knownSuperclasses.values().removeIf(configClass::equals);
			}
		}

		// Recursively process the configuration class and its superclass hierarchy.
		SourceClass sourceClass = asSourceClass(configClass);
		do {
			sourceClass = doProcessConfigurationClass(configClass, sourceClass);
		}
		while (sourceClass != null);

		this.configurationClasses.put(configClass, configClass);
	}

这里有个do ,while循环,这个是当有这个class的父类返回,会继续执行,先分析一下doProcessConfigurationClass方法做了什么。

首先判断一下当前类是否有@Component注解,有的话,调用processMemberClasses方法

	if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
			// Recursively process any member (nested) classes first
			processMemberClasses(configClass, sourceClass);
		}

这个方法在当前的注解扫描情况下,就是处理当前扫描的Class的内部类,如果有内部类,判断内部类是否有 @Component @ComponentScan  @Import     @ImportResource这样四个注解,或者有@Bean注解的方法,如果是的话,就会为这个类创建一个ConfigClass,最后还是会调用processConfigurationClass方法

	/**
	 * Check the given metadata for a configuration class candidate
	 * (or nested component class declared within a configuration/component class).
	 * @param metadata the metadata of the annotated class
	 * @return {@code true} if the given class is to be registered for
	 * configuration class processing; {@code false} otherwise
	 */
	public static boolean isConfigurationCandidate(AnnotationMetadata metadata) {
		// Do not consider an interface or an annotation...
		if (metadata.isInterface()) {
			return false;
		}

		// Any of the typical annotations found?
		// 判断是否有这四个注解  @Component @ComponentScan  @Import 	@ImportResource
		for (String indicator : candidateIndicators) {
			if (metadata.isAnnotated(indicator)) {
				return true;
			}
		}

		// Finally, let's look for @Bean methods...
		// 查看是否有@Bean的方法
		try {
			return metadata.hasAnnotatedMethods(Bean.class.getName());
		}
		catch (Throwable ex) {
			if (logger.isDebugEnabled()) {
				logger.debug("Failed to introspect @Bean methods on class [" + metadata.getClassName() + "]: " + ex);
			}
			return false;
		}
	}

返回doProcessConfigurationClass方法中,接下来会获取当前class的PropertySources注解的信息Set,循环遍历,调用processPropertySource方法,处理@PropertySources注解

	// Process any @PropertySource annotations
		for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
				sourceClass.getMetadata(), PropertySources.class,
				org.springframework.context.annotation.PropertySource.class)) {
			if (this.environment instanceof ConfigurableEnvironment) {
				processPropertySource(propertySource);
			}
			else {
				logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
						"]. Reason: Environment must implement ConfigurableEnvironment");
			}
		}

 processPropertySource中的逻辑比较简单,就是根据@PropertySource中的路径加载,通过自定义或者默认的PropertySourceFactory 解析生成一个PropertySource,通过addPropertySource添加进this.environment的MutablePropertySources集合中。

/**
	 * Process the given <code>@PropertySource</code> annotation metadata.
	 * @param propertySource metadata for the <code>@PropertySource</code> annotation found
	 * @throws IOException if loading a property source failed
	 */
	private void processPropertySource(AnnotationAttributes propertySource) throws IOException {
		String name = propertySource.getString("name");
		if (!StringUtils.hasLength(name)) {
			name = null;
		}
		String encoding = propertySource.getString("encoding");
		if (!StringUtils.hasLength(encoding)) {
			encoding = null;
		}
		String[] locations = propertySource.getStringArray("value");
		Assert.isTrue(locations.length > 0, "At least one @PropertySource(value) location is required");
		boolean ignoreResourceNotFound = propertySource.getBoolean("ignoreResourceNotFound");

		Class<? extends PropertySourceFactory> factoryClass = propertySource.getClass("factory");
		PropertySourceFactory factory = (factoryClass == PropertySourceFactory.class ?
				DEFAULT_PROPERTY_SOURCE_FACTORY : BeanUtils.instantiateClass(factoryClass));

		for (String location : locations) {
			try {
				String resolvedLocation = this.environment.resolveRequiredPlaceholders(location);
				Resource resource = this.resourceLoader.getResource(resolvedLocation);
				addPropertySource(factory.createPropertySource(name, new EncodedResource(resource, encoding)));
			}
			catch (IllegalArgumentException | FileNotFoundException | UnknownHostException ex) {
				// Placeholders not resolvable or resource not found when trying to open it
				if (ignoreResourceNotFound) {
					if (logger.isInfoEnabled()) {
						logger.info("Properties location [" + location + "] not resolvable: " + ex.getMessage());
					}
				}
				else {
					throw ex;
				}
			}
		}
	}

接着看@ComponentScans和@ComponentScan注解的处理

调用AnnotationConfigUtils.attributesForRepeatable找出当前class的@ComponentScans和@ComponentScan注解的AnnotationAttributes注解信息集合,循环调用

	// Process any @ComponentScan annotations
		Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
				sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
		if (!componentScans.isEmpty() &&
				!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
			for (AnnotationAttributes componentScan : componentScans) {
				// The config class is annotated with @ComponentScan -> perform the scan immediately
				Set<BeanDefinitionHolder> scannedBeanDefinitions =
						this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
				// Check the set of scanned definitions for any further config classes and parse recursively if needed
				for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
					BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
					if (bdCand == null) {
						bdCand = holder.getBeanDefinition();
					}
					if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
						parse(bdCand.getBeanClassName(), holder.getBeanName());
					}
				}
			}
		}

 第一个重点的方法是this.componentScanParser.parse方法,这里调用的是ComponentScanAnnotationParser的parser方法,先是根据AnnotationAttributes构建相应的ClassPathBeanDefinitionScanner。主要有这么几个属性:useDefaultFilters,nameGenerator,scopedProxy,scopeResolver,resourcePattern,includeFilters,excludeFilters,lazyInit,basePackages,basePackageClasses。而如果没有basePackages,那么就会将当前class所在的包路径添加进集合中。

而在ClassPathBeanDefinitionScanner的构造方法中,注册了一个默认的include过滤器AnnotationTypeFilter,用来过滤@Component的,还会尝试去注册ManagedBean和Named的过滤器,这两个比较少用。

protected void registerDefaultFilters() {
		this.includeFilters.add(new AnnotationTypeFilter(Component.class));
		ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
		try {
			this.includeFilters.add(new AnnotationTypeFilter(
					((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
			logger.trace("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 {
			this.includeFilters.add(new AnnotationTypeFilter(
					((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
			logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
		}
		catch (ClassNotFoundException ex) {
			// JSR-330 API not available - simply skip.
		}
	}

接着调用doScan方法,依次循环扫描basePackages集合,首先通过findCandidateComponents方法查询出所有当前需要的类,先忽略使用索引加载的情况,接着将会调用scanCandidateComponents方法,方法中将当前包路径下的所有类资源加载成一个Resource数组集合,接着循环Resource数组,

先说明过滤器的过滤规则是不会被任何excludeFilters匹配,但必须匹配一个includeFilters的不被过滤。所以根据当前的过滤规则,找出所需要的类就是有着@component注解,或者@ManagedBean注解,或者@Named,主要看最熟悉的@component,@component注解的注解还有着@Configration,@Controller,@Service等这几个比较熟悉的注解,这些注解的类都满足条件,都会被生成一个ScannedGenericBeanDefinition,接着再判断一次,这次是判断有没有依赖,是不是抽象类,如果是抽象类有没有@lookup注解,符合条件的添加进candidates这个BeanDefinition的Set集合,最后返回

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

接着再依次循环这个candidates,最后会生成一个BeanDefinitionHolder ,添加到beanDefinitions集合中,最后返回,并且注册到了registry中。

for (BeanDefinition candidate : candidates) {
                                  //从类的各个注解上获取各种属性数据 
                                  //设置scope
				ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
				candidate.setScope(scopeMetadata.getScopeName());
                                 //生成beanName
				String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
                                //设置默认的属性
				if (candidate instanceof AbstractBeanDefinition) {
					postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
				}
                               //设置Lazy,Primary,DependsOn,Role,Description
				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);
				}
			}

返回到doProcessConfigurationClass,这里会循环之前得到的BeanDefinitionHolder集合,执行parse方法,最后看到每一个BeanDefinition又会调用processConfigurationClass方法,变成一个递归的调用。

	protected final void parse(@Nullable String className, String beanName) throws IOException {
		Assert.notNull(className, "No bean class name for configuration class bean definition");
		MetadataReader reader = this.metadataReaderFactory.getMetadataReader(className);
		processConfigurationClass(new ConfigurationClass(reader, beanName));
	}

接着往下看,@Import注解的处理

// Process any @Import annotations
processImports(configClass, sourceClass, getImports(sourceClass), true);

先从当前类上获取所有的@Import注解的类,然后依次循环,先放入importStack中,这个是用来判断是否有两个类循环Import了,是的话会抛异常。

接着判断@Import注解的类是不是继承了ImportSelector接口,或是继承了ImportBeanDefinitionRegistrar接口,还是什么也没继承。

先看什么也没继承的情况,如果仅仅是一个普通的类,那就会把这个类当成一个Configuration的class去处理,这里可以看到又去调用了processConfigurationClass方法

// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
// process it as an @Configuration class
this.importStack.registerImport(
		currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
processConfigurationClass(candidate.asConfigClass(configClass));

接着看继承了ImportSelector接口的处理,这里又判断了是不是继承了DeferredImportSelector接口,先看不是的情况,如果不是DeferredImportSelector接口,那么就会调用ImportSelector的selectImports方法,然后根据自定义的代码逻辑返回一个class的数组,接着继续调用当前的processImports方法,将之前得到的class数组当成import的class集合传入,最后的最后就又会进入到processConfigurationClass方法

if (candidate.isAssignable(ImportSelector.class)) {
	// Candidate class is an ImportSelector -> delegate to it to determine imports
	Class<?> candidateClass = candidate.loadClass();
	ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
			this.environment, this.resourceLoader, this.registry);
	if (selector instanceof DeferredImportSelector) {
		this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
	}
	else {
		String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
		Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
		processImports(configClass, currentSourceClass, importSourceClasses, false);
	}
}

如果是继承了DeferredImportSelector的情况,那么就会将当前类生成一个DeferredImportSelectorHolder并放入到deferredImportSelectors这个集合中,这里要注意的是,从代码上看还有一种情况,那就是deferredImportSelectors ==null的时候,不过deferredImportSelectors初始化了一个空集合,并不会等于null,这个null的情况就是在另一个process的这个真正处理的方法中一开始就设置成了null,这就表明null的情况就是process方法正在执行,所以当这种情况,就会去直接处理这个DeferredImportSelectorHolder

if (selector instanceof DeferredImportSelector) {
	this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
}
	/**
		 * Handle the specified {@link DeferredImportSelector}. If deferred import
		 * selectors are being collected, this registers this instance to the list. If
		 * they are being processed, the {@link DeferredImportSelector} is also processed
		 * immediately according to its {@link DeferredImportSelector.Group}.
		 * @param configClass the source configuration class
		 * @param importSelector the selector to handle
		 */
		public void handle(ConfigurationClass configClass, DeferredImportSelector importSelector) {
			DeferredImportSelectorHolder holder = new DeferredImportSelectorHolder(
					configClass, importSelector);
			if (this.deferredImportSelectors == null) {
				DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
				handler.register(holder);
				handler.processGroupImports();
			}
			else {
				this.deferredImportSelectors.add(holder);
			}
		}

接着看最后一种情况,继承了ImportBeanDefinitionRegistrar接口,会将这个类生成实例,接着注册到configClass,也就是注解的那个类的ConfigurationClass中。而这个注册其实就是往map里面添加对象,在这里ImportBeanDefinitionRegistrar的实现类并没有去实现具体的逻辑

else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
	// Candidate class is an ImportBeanDefinitionRegistrar ->
	// delegate to it to register additional bean definitions
	Class<?> candidateClass = candidate.loadClass();
	ImportBeanDefinitionRegistrar registrar =
			ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
					this.environment, this.resourceLoader, this.registry);
	configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
}

再回到doProcessConfigurationClass,往下看@ImportResource注解的处理

这里逻辑比较明了,就是取出注解中的locations以及reader,read默认是BeanDefinitionReader,然后放入到configClass的一个map集合中。

	// Process any @ImportResource annotations
		AnnotationAttributes importResource =
				AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
		if (importResource != null) {
			String[] resources = importResource.getStringArray("locations");
			Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
			for (String resource : resources) {
				String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
				configClass.addImportedResource(resolvedResource, readerClass);
			}
		}

再往下,这个方法先跳过,只会处理StandardAnnotationMetadata的情况,当前注解扫描暂时没看到什么情况下会被使用到

// Process individual @Bean methods
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
	configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}

// Process default methods on interfaces
processInterfaces(configClass, sourceClass);

最后,找出父类,如果没处理过,就返回,外层继续调用doProcessConfigurationClass方法

	// Process superclass, if any
		if (sourceClass.getMetadata().hasSuperClass()) {
			String superclass = sourceClass.getMetadata().getSuperClassName();
			if (superclass != null && !superclass.startsWith("java") &&
					!this.knownSuperclasses.containsKey(superclass)) {
				this.knownSuperclasses.put(superclass, configClass);
				// Superclass found, return its annotation metadata and recurse
				return sourceClass.getSuperClass();
			}
		}

最后返回到parse方法中,这里处理了继承了DeferredImportSelector的@Import

this.deferredImportSelectorHandler.process();
	public void process() {
			List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
			this.deferredImportSelectors = null;
			try {
				if (deferredImports != null) {
					DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
					deferredImports.sort(DEFERRED_IMPORT_COMPARATOR);
					deferredImports.forEach(handler::register);
					handler.processGroupImports();
				}
			}
			finally {
				this.deferredImportSelectors = new ArrayList<>();
			}
		}

这里首先创建了一个DeferredImportSelectorGroupingHandler ,接着排序

再接着,根据DeferredImportSelectorHolder集合循环,依次调用刚才创建的DeferredImportSelectorGroupingHandler的register方法,参数是DeferredImportSelectorHolder,在register方法中,根据当前的group的实际class,创建实例对象,作为DeferredImportSelectorGrouping构造方法的参数,传入,接着将DeferredImportSelectorHolder 也放入到这个DeferredImportSelectorGrouping中,最后放入到groupings集合中

	public void register(DeferredImportSelectorHolder deferredImport) {
			Class<? extends Group> group = deferredImport.getImportSelector()
					.getImportGroup();
			DeferredImportSelectorGrouping grouping = this.groupings.computeIfAbsent(
					(group != null ? group : deferredImport),
					key -> new DeferredImportSelectorGrouping(createGroup(group)));
			grouping.add(deferredImport);
			this.configurationClasses.put(deferredImport.getConfigurationClass().getMetadata(),
					deferredImport.getConfigurationClass());
		}

接着调用processGroupImports方法,这里最重要的就是getImports方法,和普通的@import不同,继承了DeferredImportSelector接口的类,只会调用process,以及selectImports方法,最后根据selectImports返回的集合对象,循环调用processImports方法,processImports方法之前说明过

	public void processGroupImports() {
			for (DeferredImportSelectorGrouping grouping : this.groupings.values()) {
				grouping.getImports().forEach(entry -> {
					ConfigurationClass configurationClass = this.configurationClasses.get(
							entry.getMetadata());
					try {
						processImports(configurationClass, asSourceClass(configurationClass),
								asSourceClasses(entry.getImportClassName()), false);
					}
					catch (BeanDefinitionStoreException ex) {
						throw ex;
					}
					catch (Throwable ex) {
						throw new BeanDefinitionStoreException(
								"Failed to process import candidates for configuration class [" +
										configurationClass.getMetadata().getClassName() + "]", ex);
					}
				});
			}
		}
/**
		 * Return the imports defined by the group.
		 * @return each import with its associated configuration class
		 */
		public Iterable<Group.Entry> getImports() {
			for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {
				this.group.process(deferredImport.getConfigurationClass().getMetadata(),
						deferredImport.getImportSelector());
			}
			return this.group.selectImports();
		}

最后返回

至此为止,所有spring体系中的类都被转化成了ConfigurationClass

 

往下,是一个验证方法,就是验证@Configuration注解的类的@Bean方法满不满足要求,这里主要是不能是fianl,必须能被重写,不满足则验证不通过

	public void validate(ProblemReporter problemReporter) {
		// A configuration class may not be final (CGLIB limitation) unless it declares proxyBeanMethods=false
		Map<String, Object> attributes = this.metadata.getAnnotationAttributes(Configuration.class.getName());
		if (attributes != null && (Boolean) attributes.get("proxyBeanMethods")) {
			if (this.metadata.isFinal()) {
				problemReporter.error(new FinalConfigurationProblem());
			}
			for (BeanMethod beanMethod : this.beanMethods) {
				beanMethod.validate(problemReporter);
			}
		}
	}

然后构建一个ConfigurationClassBeanDefinitionReader,这个类负责解析之前的@ImportResource,@Import的ImportBeanDefinitionRegistrar,@Bean,@Import导入的类

	// Read the model and create bean definitions based on its content
			if (this.reader == null) {
				this.reader = new ConfigurationClassBeanDefinitionReader(
						registry, this.sourceExtractor, this.resourceLoader, this.environment,
						this.importBeanNameGenerator, parser.getImportRegistry());
			}
			this.reader.loadBeanDefinitions(configClasses);
			alreadyParsed.addAll(configClasses);

ImportResource的解析,主要是解析@importResource导入的资源文件,默认一般是xml,或者是groovy的文件,也可以实现自定义的reader的类,这里细节比较多,跳过。

至于@Import的ImportBeanDefinitionRegistrar的处理非常简单,就是去调用@import的那个类的registerBeanDefinitions方法。

再看@Bean的处理,会把之前生成好的BeanMethods取出,循环,生成一个个ConfigurationClassBeanDefinition,注册到registry中。

接着之前一些通过@import导入的类,都会解析成AnnotatedGenericBeanDefinition,注册到registry中。

到此,扫描基本就结束了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值