Spring创建Bean源码 - 解析配置类(一)
发现所有的配置类
主要作用发现BeanDefinitionRegistry
对象中的配置类**(带有****@Configuration**
**注解的类),**利用配置类中的特定注解信息派生出更多的BeanDefinition
。
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
//获取已经注册进来的Bean名称
String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
//判断某个类中是否存在 configurationClass属性
if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
//判断BeanDefinition是否是一个配置类
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
//配置类加入配置集合
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
// Return immediately if no @Configuration classes were found
if (configCandidates.isEmpty()) {
return;
}
//按照@Order指定的顺序排序BeanDefinition
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
});
// Detect any custom bean name generation strategy supplied through the enclosing application context
SingletonBeanRegistry sbr = null;
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry) registry;
if (!this.localBeanNameGeneratorSet) {
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
if (generator != null) {
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
}
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
//创建解析配置类解析对象
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
//开始解析配置类
//该API包含向Spring中注册springboot的AutoConfiguration自动装配类,并将自动装配类放入org.springframework.context.annotation.ConfigurationClassParser.importStack数据结构中
parser.parse(candidates);
parser.validate();
//去重
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
// 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());
}
//加载所有的配置类,并注册到注册器中
//读取的配置类ConfigurationClass,将该配置类以及该配置类中@Bean方法中创建的对象封装成BeanDefinition,然后注册到BeanDefinitionRegister中
//加载带有@ConfigurationProperties注解的类,并封装成BeanDefinition注册到BeanDefinitionRegister中
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();
candidates.clear();
if (registry.getBeanDefinitionCount() > candidateNames.length) {
String[] newCandidateNames = registry.getBeanDefinitionNames();
Set<String> oldCandidateNames = Set.of(candidateNames);
Set<String> alreadyParsedClasses = new HashSet<>();
for (ConfigurationClass configurationClass : alreadyParsed) {
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
for (String candidateName : newCandidateNames) {
if (!oldCandidateNames.contains(candidateName)) {
BeanDefinition bd = registry.getBeanDefinition(candidateName);
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
!alreadyParsedClasses.contains(bd.getBeanClassName())) {
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
candidateNames = newCandidateNames;
}
}
while (!candidates.isEmpty());
// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
// Store the PropertySourceDescriptors to contribute them Ahead-of-time if necessary
this.propertySourceDescriptors = parser.getPropertySourceDescriptors();
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory cachingMetadataReaderFactory) {
// Clear cache in externally provided MetadataReaderFactory; this is a no-op
// for a shared cache since it'll be cleared by the ApplicationContext.
cachingMetadataReaderFactory.clearCache();
}
}
详细步骤如下:
- 从
BeanDefinitionRegistry
中获取所有的BeanDefinition
- 挑选出所有的配置类
- 按照配置类的Order配置的顺序,对所有的配置类进行排序
- 创建配置类解析器
ConfigurationClassParser
,解析每一个配置类并生成ConfigurationClass
对象,将每个配置类解析到的数据封装到对应的ConfigurationClass
对象中。- 使用
ConfigurationClassBeanDefinitionReader
对象,将每一个ConfigurationClass
中需要派生出来的类加载进来,封装成BeanDefinition
,注册到BeanDefinitionRegistry
中。
解析所有的配置类
public void parse(Set<BeanDefinitionHolder> configCandidates) {
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {
//是否是基于注解的BeanDefinition,实现了AnnotatedBeanDefinition接口的BeanDefinition。
if (bd instanceof AnnotatedBeanDefinition annotatedBeanDef) {
parse(annotatedBeanDef.getMetadata(), holder.getBeanName());
} else if (bd instanceof AbstractBeanDefinition abstractBeanDef && abstractBeanDef.hasBeanClass()) {
parse(abstractBeanDef.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);
}
}
//Springboot AutoConfiguration自动装配的入口方法
// @see org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.AutoConfigurationGroup#process
// @see org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#getAutoConfigurationEntry
this.deferredImportSelectorHandler.process();
}
详细步骤如下:
- 根据
BeanDefinition
的实际类型,调用不同的解析方法- 调用
deferredImportSelectorHandler.process()
方法,导入其他的BeanDefinition
。该方法也是**Springboot AutoConfiguration**
自动装配的入口方法。请看《Springboot自动装配源码(一) - 自动装配》
解析配置类
开始解析给定的配置类信息,为每个配置类生成一个ConfigurationClass
,然后将所有解析到的配置类信息都填充到ConfigurationClass
对象中。
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
}
protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) 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);
}
}
//包含注解元数据的Class的简单包装器,
SourceClass sourceClass = asSourceClass(configClass, filter);
do {
//开始处理配置类
sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
}
// Recursively process the configuration class and its superclass hierarchy.
while (sourceClass != null);
//将扫描到的所有类放入内存
this.configurationClasses.put(configClass, configClass);
}
/**
* 通过从SourceClass读取注解、Member和方法来构建一个完整的{@link ConfigurationClass}。
* <p>
* 1.处理配置类上的@Component注解
* 2.处理配置类上的@PropertySource注解
* 3.处理配置类上的@ComponentScan注解
* 4.处理配置类上的Import注解
* 5.处理配置类上的ImportResource注解
* 6.处理配置类中标记@Bean注解的方法
* <p>
* 以上所有步骤得处理结果都会封装到ConfigurationClass对象中,供后续创建Bean的时候使用
*
* @param configClass 被构建的配置类
* @param sourceClass 自动配置类的注解元数据的简单包装类
* @return 父类或者null
*/
@Nullable
protected final SourceClass doProcessConfigurationClass(
ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
throws IOException {
//配置类是否被@Component注解标记
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
// Recursively process any member (nested) classes first
//递归处理任何Member类
processMemberClasses(configClass, sourceClass, filter);
}
// Process any @PropertySource annotations
//处理任何@PropertySource注解
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class,
org.springframework.context.annotation.PropertySource.class)) {
if (this.propertySourceRegistry != null) {
//处理
this.propertySourceRegistry.processPropertySource(propertySource);
} else {
logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
"]. Reason: Environment must implement ConfigurableEnvironment");
}
}
// Process any @ComponentScan annotations
//处理@ComponentScan注解
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) {
//带有@ComponentScan注解的类就是配置类,立即执行扫描
//扫描@ComponentScan注解中basePackages值对应的包,获取包里的所有class,并封装成BeanDefinition加载注册注册器中
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());
}
}
}
}
//处理所有 @Import注解
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
//处理所有 @ImportResource 注解
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);
}
}
// Process individual @Bean methods
//处理带有@Bean注解的方法
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
//加入配置类
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// 处理接口上的默认方法
processInterfaces(configClass, sourceClass);
// 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();
}
}
// No superclass -> processing is complete
return null;
}
详细步骤如下:
- 处理配置类上的
@Component
注解:如果自动配置类上标有@Component
注解,则递归处理嵌套在配置类中嵌套的类。- 处理配置类上的
@PropertySource
注解:解析@PropertySource
注解中的元数据,将@PropertySource
注解配置的属性资源加载到Environment
中。请看《Spring创建Bean源码 - 解析配置类 (三): 处理PropertySource注解》- 处理配置类上的@ComponentScan注解,请看
- 处理配置类上的Import注解
- 处理配置类上的ImportResource注解
- 处理配置类中标记@Bean注解的方法
- 处理接口上的默认方法
处理配置类的@Component
注解
略。。。。。
处理配置类的@PropertySource
注解
解析@PropertySource
注解信息,将注解中配置的属性资源加载到Environment
中。
/**
* 处理@PropertySource注解的元数据
* @param propertySource metadata for the <code>@PropertySource</code> annotation found
* @throws IOException if loading a property source failed
*/
void processPropertySource(AnnotationAttributes propertySource) throws IOException {
//获取name属性值
String name = propertySource.getString("name");
if (!StringUtils.hasLength(name)) {
name = null;
}
//获取encoding属性值
String encoding = propertySource.getString("encoding");
if (!StringUtils.hasLength(encoding)) {
encoding = null;
}
//获取value属性值
String[] locations = propertySource.getStringArray("value");
Assert.isTrue(locations.length > 0, "At least one @PropertySource(value) location is required");
//获取ignoreResourceNotFound属性值
boolean ignoreResourceNotFound = propertySource.getBoolean("ignoreResourceNotFound");
//获取factory属性值
Class<? extends PropertySourceFactory> factoryClass = propertySource.getClass("factory");
Class<? extends PropertySourceFactory> factorClassToUse =
(factoryClass != PropertySourceFactory.class ? factoryClass : null);
//将@PropertySource注解的元数据封装成PropertySourceDescriptor
PropertySourceDescriptor descriptor = new PropertySourceDescriptor(Arrays.asList(locations), ignoreResourceNotFound, name,
factorClassToUse, encoding);
//将@PropertySource注解配置的属性资源加载到Environment中。
this.propertySourceProcessor.processPropertySource(descriptor);
this.descriptors.add(descriptor);
}
/**
* 通过PropertySourceDescriptor实例的所在的环境处理指定的{@link PropertySourceDescriptor}对象
* @param descriptor 待处理的PropertySourceDescriptor
* @throws IOException if loading the properties failed
*/
public void processPropertySource(PropertySourceDescriptor descriptor) throws IOException {
String name = descriptor.name();
String encoding = descriptor.encoding();
List<String> locations = descriptor.locations();
Assert.isTrue(locations.size() > 0, "At least one @PropertySource(value) location is required");
boolean ignoreResourceNotFound = descriptor.ignoreResourceNotFound();
PropertySourceFactory factory = (descriptor.propertySourceFactory() != null ?
instantiateClass(descriptor.propertySourceFactory()) : DEFAULT_PROPERTY_SOURCE_FACTORY);
for (String location : locations) {
try {
//value属性配置的资源文件的位置
String resolvedLocation = this.environment.resolveRequiredPlaceholders(location);
//加载属性资源
Resource resource = this.resourceLoader.getResource(resolvedLocation);
//将属性资源加入到environment中
addPropertySource(factory.createPropertySource(name, new EncodedResource(resource, encoding)));
}
catch (IllegalArgumentException | FileNotFoundException | UnknownHostException | SocketException 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;
}
}
}
}
详细步骤如下:
- 解析name、encoding、value、factory属性。
- 使用value属性配置的资源文件位置加载属性资源,然后将属性加入到Environment中。
处理配置类的@Import
注解
解析配置类上的@Import
,并将注解中指定的类注册进来。
/**
* 获取基于@Import注解配导入的类集合
*/
private Set<SourceClass> getImports(SourceClass sourceClass) throws IOException {
Set<SourceClass> imports = new LinkedHashSet<>();
Set<SourceClass> visited = new LinkedHashSet<>();
collectImports(sourceClass, imports, visited);
return imports;
}
//递归收集基于@Import注解配导入的类集合
private void collectImports(SourceClass sourceClass, Set<SourceClass> imports, Set<SourceClass> visited)
throws IOException {
if (visited.add(sourceClass)) {
for (SourceClass annotation : sourceClass.getAnnotations()) {
String annName = annotation.getMetadata().getClassName();
if (!annName.equals(Import.class.getName())) {
collectImports(annotation, imports, visited);
}
}
imports.addAll(sourceClass.getAnnotationAttributes(Import.class.getName(), "value"));
}
}
/**
* 处理@Import注解中的导入类
*
* @param configClass 带有@Configuration注解的配置类
* @param currentSourceClass 带有@Configuration注解配置类对应的带有注解元数据的简单包装类
* @param importCandidates @Configuration注解的配置类上@Import注解中的导入类集合
* @param exclusionFilter
* @param checkForCircularImports
*/
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
boolean checkForCircularImports) {
if (importCandidates.isEmpty()) {
return;
}
if (checkForCircularImports && isChainedImportOnStack(configClass)) {
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
} else {
this.importStack.push(configClass);
try {
for (SourceClass candidate : importCandidates) {
//当前导入类实现了ImportSelector接口
if (candidate.isAssignable(ImportSelector.class)) {
Class<?> candidateClass = candidate.loadClass();
//反射实例化当前导入类
ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
this.environment, this.resourceLoader, this.registry);
Predicate<String> selectorFilter = selector.getExclusionFilter();
if (selectorFilter != null) {
exclusionFilter = exclusionFilter.or(selectorFilter);
}
//当前导入类的对象是否是一个DeferredImportSelector
//Springboot的自动装配机制就是基于DeferredImportSelector实现的
if (selector instanceof DeferredImportSelector deferredImportSelector) {
this.deferredImportSelectorHandler.handle(configClass, deferredImportSelector);
}
else {
//调用ImportSelector的selectImports方法,将方法返回的类集合注册进来
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
}
}
//当前导入类实现了ImportBeanDefinitionRegistrar接口
else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
//Class实现了ImportBeanDefinitionRegistrar这个接口,称Class是一个ImportBeanDefinitionRegistrar
//委托ImportBeanDefinitionRegistrar来注册BeanDefinition
//ImportBeanDefinitionRegistrar功能是将@Import注解中的类的BeanDefinition注册到Spring中
//configClass上@Import注解中的某一个导入类
Class<?> candidateClass = candidate.loadClass();
ImportBeanDefinitionRegistrar registrar =
ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
this.environment, this.resourceLoader, this.registry);
//4.configClass:带有Import注解的Class
//5.保存ImportBeanDefinitionRegistrar对象与@Import元数据的对应关系到configClass对象中
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
}
//当前导入类是一个普通的类
else {
//@Import注解中的导入类既不是ImportSelector也不是ImportBeanDefinitionRegistrar,就是既没有实现ImportSelector也没有实现ImportBeanDefinitionRegistrar
//就当成普通的配置类处理
this.importStack.registerImport(
currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
}
}
} catch (BeanDefinitionStoreException ex) {
throw ex;
} catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to process import candidates for configuration class [" +
configClass.getMetadata().getClassName() + "]: " + ex.getMessage(), ex);
} finally {
this.importStack.pop();
}
}
}
详细步骤如下:
- 获取配置类上
@Import
注解中配置的导入类的集合- 遍历导入类
- 如果导入类实现了ImportSelector接口则
- 利用反射实例化导入类,如果实例化的对象是一个
DeferredImportSelector
,则调用DeferredImportSelectorHandler#handle
方法,处理以组的方式导入类。(Springboot的自动装配机制就是基于DeferredImportSelector实现的)- 如果实例化的对象是不一个
DeferredImportSelector
,则调用ImportSelector#selectImports
方法,将方法返回的类注册进来。- 如果导入类实现了
ImportBeanDefinitionRegistrar
接口,则利用反射实例化导入类,委托ImportBeanDefinitionRegistrar
来注册BeanDefinition,然后保存ImportBeanDefinitionRegistrar
对象与@Import
元数据的对应关系到ConfigClass
对象中。- 如果当前导入类既不是ImportSelector也不是ImportBeanDefinitionRegistrar,就是既没有实现ImportSelector也没有实现ImportBeanDefinitionRegistrar就当成普通的配置类处理。
处理配置类的@ComponentScans
注解
解析配置类上的@ComponentScan
注解,并根据其配置的信息,加载指定包下的类并封装成BeanDefinition
注册到BeanDefinitionRegistry
中
public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, String declaringClass) {
//创建ClassPathBeanDefinitionScanner对象,用于扫描和加载Class
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
//获取@Component的nameGenerator属性,用于为BeanDefinition生成Bean名称的类。
Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);
scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator :
BeanUtils.instantiateClass(generatorClass));
//获取@Component的scopedProxy属性,用于确定是否为扫描到的类生成代理,默认false。
ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy");
if (scopedProxyMode != ScopedProxyMode.DEFAULT) {
scanner.setScopedProxyMode(scopedProxyMode);
}
else {
Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");
scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));
}
//获取@Component的resourcePattern属性,用于控制符合组件检测条件的类文件。
scanner.setResourcePattern(componentScan.getString("resourcePattern"));
//获取@Component的includeFilters、excludeFilters属性,用于控制符合组件检测条件的类文件。
for (AnnotationAttributes includeFilterAttributes : componentScan.getAnnotationArray("includeFilters")) {
List<TypeFilter> typeFilters = TypeFilterUtils.createTypeFiltersFor(includeFilterAttributes, this.environment,
this.resourceLoader, this.registry);
for (TypeFilter typeFilter : typeFilters) {
scanner.addIncludeFilter(typeFilter);
}
}
for (AnnotationAttributes excludeFilterAttributes : componentScan.getAnnotationArray("excludeFilters")) {
List<TypeFilter> typeFilters = TypeFilterUtils.createTypeFiltersFor(excludeFilterAttributes, this.environment,
this.resourceLoader, this.registry);
for (TypeFilter typeFilter : typeFilters) {
scanner.addExcludeFilter(typeFilter);
}
}
//是否是懒加载的
boolean lazyInit = componentScan.getBoolean("lazyInit");
if (lazyInit) {
scanner.getBeanDefinitionDefaults().setLazyInit(true);
}
//扫描的包集合
Set<String> basePackages = new LinkedHashSet<>();
//获取@Component注解的basePackages值
String[] basePackagesArray = componentScan.getStringArray("basePackages");
for (String pkg : basePackagesArray) {
String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
Collections.addAll(basePackages, tokenized);
}
for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) {
basePackages.add(ClassUtils.getPackageName(clazz));
}
if (basePackages.isEmpty()) {
basePackages.add(ClassUtils.getPackageName(declaringClass));
}
scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
@Override
protected boolean matchClassName(String className) {
return declaringClass.equals(className);
}
});
//扫描并加载指定packages中的类
return scanner.doScan(StringUtils.toStringArray(basePackages));
}
详细代码逻辑为:
- 创建
ClassPathBeanDefinitionScanner
对象,用于扫描和加载Class- 获取
@Component
的nameGenerator
属性,用于为BeanDefinition
生成Bean名称的类。- 获取
@Component
的scopedProxy
属性,用于确定是否为扫描到的类生成代理,默认false
。- 获取
@Component
的resourcePattern
属性,用于控制符合组件检测条件的类文件。- 获取
@Component
的includeFilters、excludeFilters
属性,用于控制符合组件检测条件的类文件。- 获取
@Component
的lazyInit
,用于控制扫描到的类是否是懒加载。- 获取
@Component
的basePackages
,用于获取组件扫描的包结构。- 开始扫描和加载
扫描指定包下的类,并将其封装成BeanDefinition
注册到BeanDefinitionRegistry
中。
/**
* 1.扫描给定包下的所有Class,封装成BeanDefinitionHolder集合返回
* 2.将所有的BeanDefinition注册到注册器中
* @param basePackages ComponentScan注解中的value值
* @return 并将所有的Class封装成BeanDefinitionHolder集合
*/
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) {
//扫描包,并将扫描的类封装成BeanDefinition对象
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
//设置Scope属性
candidate.setScope(scopeMetadata.getScopeName());
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition abstractBeanDefinition) {
postProcessBeanDefinition(abstractBeanDefinition, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition annotatedBeanDefinition) {
//解析Bean上的特定注解,并丰富BeanDefinition
AnnotationConfigUtils.processCommonDefinitionAnnotations(annotatedBeanDefinition);
}
if (checkCandidate(beanName, candidate)) {
//BeanDefinition封装成BeanDefinitionHolder
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
//将BeanDefinition注册到注册器中
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
- 扫描包,并将扫描的类封装成
BeanDefinition
对象- 设置
BeanDefinition
对应Bean
的Scope
属性- 将默认设置应用于
BeanDefinition
对应Bean
- 默认懒加载属性
- 默认初始化方法
- 默认销毁方法
- 默认依赖检查
- 解析类中的指定注解,并设置到
BeanDefinition
中。
@Lazy
@Primary
@DependsOn
@Role
@Description
/**
* 解析Bean上某些注解的属性值,并修改Bean的定义信息
* @param abd BeanDefinition
* @param metadata 注解元数据
*/
static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
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"));
}
}
if (metadata.isAnnotated(Primary.class.getName())) {
abd.setPrimary(true);
}
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"));
}
}
- 根据
Scope
属性创建BeanDefinitionHolder
,替换普通的BeanDefinitionHolder
static BeanDefinitionHolder applyScopedProxyMode(
ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {
ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
return definition;
}
boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
}
public static BeanDefinitionHolder createScopedProxy(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry, boolean proxyTargetClass) {
return ScopedProxyUtils.createScopedProxy(definitionHolder, registry, proxyTargetClass);
}
/**
* Generate a scoped proxy for the supplied target bean, registering the target
* bean with an internal name and setting 'targetBeanName' on the scoped proxy.
* @param definition the original bean definition
* @param registry the bean definition registry
* @param proxyTargetClass whether to create a target class proxy
* @return the scoped proxy definition
* @see #getTargetBeanName(String)
* @see #getOriginalBeanName(String)
*/
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 abd) {
proxyDefinition.copyQualifiersFrom(abd);
}
// 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());
}
处理配置类的@ImportResource
注解
//处理所有 @ImportResource 注解
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);
}
}
详细代码逻辑:
- 获取配置类上的
@ImportResource
的locations
(资源的位置)和BeanDefinitionReader
(用于读取资源的BeanDefinitionReader
对象)属性信息。- 遍历
locations
,解析资源对应的占位符,并将占位符与BeanDefinitionReader
的对应关系存入ConfigurationClass
对象中的Map<String, Class<? extends BeanDefinitionReader>> importedResources
中。
处理配置类中带有@Bean
注解的方法
找出配置类中所有的@Bean
方法,然后将方法填充到ConfigurationClass
中。
//处理带有@Bean注解的方法
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
//加入配置类
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
/**
* 检索所有带有@Bean注解方法的元数据信息
*/
private Set<MethodMetadata> retrieveBeanMethodMetadata(SourceClass sourceClass) {
AnnotationMetadata original = sourceClass.getMetadata();
Set<MethodMetadata> beanMethods = original.getAnnotatedMethods(Bean.class.getName());
if (beanMethods.size() > 1 && original instanceof StandardAnnotationMetadata) {
// Try reading the class file via ASM for deterministic declaration order...
// Unfortunately, the JVM's standard reflection returns methods in arbitrary
// order, even between different runs of the same application on the same JVM.
try {
AnnotationMetadata asm =
this.metadataReaderFactory.getMetadataReader(original.getClassName()).getAnnotationMetadata();
Set<MethodMetadata> asmMethods = asm.getAnnotatedMethods(Bean.class.getName());
if (asmMethods.size() >= beanMethods.size()) {
Set<MethodMetadata> selectedMethods = new LinkedHashSet<>(asmMethods.size());
for (MethodMetadata asmMethod : asmMethods) {
for (MethodMetadata beanMethod : beanMethods) {
if (beanMethod.getMethodName().equals(asmMethod.getMethodName())) {
selectedMethods.add(beanMethod);
break;
}
}
}
if (selectedMethods.size() == beanMethods.size()) {
// All reflection-detected methods found in ASM method set -> proceed
beanMethods = selectedMethods;
}
}
} catch (IOException ex) {
logger.debug("Failed to read class file via ASM for determining @Bean method order", ex);
// No worries, let's continue with the reflection metadata we started with...
}
}
return beanMethods;
}
详细代码逻辑为:
- 获取配置类中带有
@Bean
的所有方法集合,(返回集合中的方法的顺序是任意的,不是按照声明的顺序排列的,因为JVM中反射获取方法的顺序是任意的,即使同一个JVM,同一个应用程序,不同运行之间也顺序也是不同的)。- 尝试通过 ASM 读取类文件的方式使
@Bean
方法在集合中按照声明顺序排列。