配置类解析与扫描简单介绍
- 本文源码基于spring-framework-5.3.10。
- 源码入口:org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(BeanDefinitionRegistry)
- 调用位置:spring启动的时候会执行BeanFactoryPostProcessor重写的方法的时候。
FULL配置类与LITE配置类
- FULL配置类:存在@Configuration(proxyBeanMethods = false)的时候。
- LITE配置类:除了proxyBeanMethods = false的时候,只要加了@Configuration就是配置类;不加@Configuration,存在@Component、@ComponentScan、@Import、@ImportResource四种的一个,或者存在@Bean注解了的方法也是配置类。
- 除了上述的俩种类型,其余的类对于spring来说都不是配置类。
解析配置类整体思路
- 配置类上是否存在@Component、检查内部类是不是配置类、解析该新配置类。
- 配置类上是否有@ComponentScan、扫描并注册BeanDefinition、检查是否存在配置类、解析该新配置类。
- 配置类上是否有@Import、调用processImports()处理所导入的类、是ImportSelector类型、是DeferredImportSelector类型、表示推迟的ImportSelector,它会在当前配置类所属的批次中所有配置类都解析完了之后执行。
- 配置类上是否有@Import、调用processImports()处理所导入的类、是ImportSelector类型、是普通ImportSelector类型、把selectImports()方法所返回的类再次调用processImports()进行处理。
- 配置类上是否有@Import、调用processImports()处理所导入的类、是ImportBeanDefinitionRegistrar类型、将ImportBeanDefinitionRegistrar实例对象添加到当前配置类的importBeanDefinitionRegistrars属性中。
- 配置类上是否有@Import、调用processImports()处理所导入的类、是普通类型、当作新配置类进行解析
- 配置类上是否有@ImportResource、将所导入的xml文件路径添加到当前配置类的importedResources属性中。
- 配置类中是否有@Bean、将@Bean修饰的方法封装为BeanMethod对象,并添加到当前配置类的beanMethods属性中。
- 配置类所实现的接口中是否有@Bean、将@Bean修饰的方法封装为BeanMethod对象,并添加到当前配置类的beanMethods属性中
- 把配置类的父类当作配置类进行解析
源码分析
/**
* 一个实现了BeanDefinitionRegistryPostProcessor的子类
*/
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
int registryId = System.identityHashCode(registry);
if (this.registriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
}
if (this.factoriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + registry);
}
this.registriesPostProcessed.add(registryId);
// 解析配置类
processConfigBeanDefinitions(registry);
}
获取配置类的过程:processConfigBeanDefinitions源码分析
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
// 得到所有的BeanDefinition名称,首次这里只能拿到传入的配置类、以及一些系统默认的BeanDefinition。
// 比如首次可以拿到:AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、ConfigurationClassPostProcessor、自己传入的配置类...
String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
// 判断哪个是配置类
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;
}
// Sort by previously determined @Order value, if applicable
// 通过@Order可以排序,升序排序,order越小越靠前
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) {
// 可以预先往单例池中添加一个CONFIGURATION_BEAN_NAME_GENERATOR的BeanNameGenerator类型的bean
// 可以用来作为扫描得到的Bean和import导入进来的Bean的beanName
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
if (generator != null) {
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
}
// 配置环境变量的为null,初始化一个
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
// Parse each @Configuration class
// 构建一个配置类的解析器
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());
// 递归解析配置类,有可能通过解析一个配置类,得到了其他的配置类,比如扫描和Importt
do {
StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
// 解析配置类,会把每个BeanDefinitionHolder首先封装为ConfigurationClass
// 在这个过程中会进行扫描、导入等步骤,从而会找到其他的ConfigurationClass
// 解析配置类的结果是什么?
parser.parse(candidates); // AppConfig.class--->BeanDefinition
parser.validate();
// configClasses相当于就是解析之后的结果
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加载成BeanDefinition,通过情况下一个配置类会对应一个BeanDefinition,不过也有可能一个配置类对应多个BeanDefinition
// 比如一个配置类中有多个@Bean,一个配置配置了@ImportResource
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();
// candidates中存的是BeanDefinition,configClasses中存的是ConfigurationClass
candidates.clear();
// 如果发现BeanDefinition增加了,则有可能增加了配置类
if (registry.getBeanDefinitionCount() > candidateNames.length) {
String[] newCandidateNames = registry.getBeanDefinitionNames();
Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(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);
// 检查多出来的BeanDefinition是不是配置类,需不需要解析
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());
}
if (this.metadataReaderFactory instanceof 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) this.metadataReaderFactory).clearCache();
}
}
什么样的类是配置类:checkConfigurationClassCandidate源码分析
public static boolean checkConfigurationClassCandidate(
BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
// @Bean定义的配置类Bean是不起作用的
String className = beanDef.getBeanClassName();
if (className == null || beanDef.getFactoryMethodName() != null) {
return false;
}
// AnnotationMetadata表示某个类的注解信息,但是并一定要加载这个类
AnnotationMetadata metadata;
// 如果AnnotatedBeanDefinition,则直接取AnnotationMetadata
if (beanDef instanceof AnnotatedBeanDefinition &&
className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {
// Can reuse the pre-parsed metadata from the given BeanDefinition...
metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata();
}
// 如果是AbstractBeanDefinition,则解析beanClass得到AnnotationMetadata
else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {
// Check already loaded Class if present...
// since we possibly can't even load the class file for this Class.
Class<?> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass();
if (BeanFactoryPostProcessor.class.isAssignableFrom(beanClass) ||
BeanPostProcessor.class.isAssignableFrom(beanClass) ||
AopInfrastructureBean.class.isAssignableFrom(beanClass) ||
EventListenerFactory.class.isAssignableFrom(beanClass)) {
return false;
}
metadata = AnnotationMetadata.introspect(beanClass);
}
else {
try {
MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className);
metadata = metadataReader.getAnnotationMetadata();
}
catch (IOException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Could not find class file for introspecting configuration annotations: " +
className, ex);
}
return false;
}
}
// 得到当前类上加了@Configuration的注解信息
Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
// 存在@Configuration,并且proxyBeanMethods不为false(为true或为null)时,就是Full配置类,直接翻译是满的
// 这里主要处理@Configuration(proxyBeanMethods = false)的逻辑。默认当前属性为true
if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
}
// 存在@Configuration,并且proxyBeanMethods为false时,是lite配置类,直接翻译是轻的
// 或者不存在@Configuration,但是只要存在@Component、@ComponentScan、@Import、@ImportResource四个中的一个,就是lite配置类
// 或者不存在@Configuration,只要存在@Bean注解了的方法,就是lite配置类
else if (config != null || isConfigurationCandidate(metadata)) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
}
else {
return false;
}
// It's a full or lite configuration candidate... Let's determine the order value, if any.
Integer order = getOrder(metadata);
if (order != null) {
beanDef.setAttribute(ORDER_ATTRIBUTE, order);
}
return true;
}
解析配置类:parse源码分析
public void parse(Set<BeanDefinitionHolder> configCandidates) {
// 遍历每个配置类
for (BeanDefinitionHolder holder : configCandidates) {
// 得到配置类对应的BeanDefinition
BeanDefinition bd = holder.getBeanDefinition();
try {
// 解析BeanDefinition所对应的类
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);
}
}
// 处理deferredImportSelectors,表示当前所有配置类解析完了之后才执行
// deferredImportSelector表示推迟的ImportSelector,正常的ImportSelector是在解析配置类的过程中执行的
this.deferredImportSelectorHandler.process();
}
/**
* 解析之前的封装
*/
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
// 把类的元信息和beanName封装为ConfigurationClass
processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
}
/**
* 配置类处理的方法
*/
protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
// 条件注解,就是看有没有类上是否有@Conditional注解,如果有,则进行条件匹配
if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
return;
}
ConfigurationClass existingClass = this.configurationClasses.get(configClass);
if (existingClass != null) {
if (configClass.isImported()) {
// 重复导入:OrderService导入了AccountService,UserService也导入了AccountService,就会符合这个条件
// 当前配置类有@Import,之前解析过,不解析!
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.
// 当前配置类没有@Import,覆盖之前的
this.configurationClasses.remove(configClass);
this.knownSuperclasses.values().removeIf(configClass::equals);
}
}
// Recursively process the configuration class and its superclass hierarchy.
SourceClass sourceClass = asSourceClass(configClass, filter);
// 这个循环是找到这个配置类的所有父类进行解析!
do {
// 真正解析配置类的核心方法
sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
}
while (sourceClass != null);
// ConfigurationClass重写了equals方法,只要两个ConfigurationClass对应的className相等就可以
this.configurationClasses.put(configClass, configClass);
}
/**
* 真正解析配置类的核心方法
*/
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
// 处理内部类
// 在解析一个配置类时,如果类上有@Component,则会判断内部类是不是lite配置类并进行解析,并且会记录为被导入的
processMemberClasses(configClass, sourceClass, filter);
}
// Process any @PropertySource annotations
// 这里处理@PropertySource注解。读取配置文件,放入environment中
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");
}
}
// Process any @ComponentScan annotations
// 会进行扫描,得到的BeanDefinition会注册到Spring容器中,并且会检查是不是配置类并进行解析
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
// 这里就会进行扫描,得到的BeanDefinition会注册到Spring容器中
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();
}
// 检查扫描出来的BeanDefinition是不是配置类(full和lite)
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
// Process any @Import annotations
// getImports(sourceClass)会拿到@Import导入的类
// 如果导入的是普通类,那么会直接把它当做配置类来解析
// 如果导入的是普通ImportSelector,那么会将返回的类再次调用processImports()
// 如果导入的是特殊ImportSelector,DeferredImportSelector,那么暂时不会处理,会在解析完所有当前这轮配置类后进行导入,将返回的类再次调用processImports()
// 如果导入的是ImportBeanDefinitionRegistrar,那么暂时不会处理,会在解析完所有当前这轮配置类后,将配置类解析成为BeanDefinition之后进行调用
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
// 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);
}
}
// Process individual @Bean methods
// 解析配置类中的@Bean,但并没有真正处理@Bean,只是暂时找出来
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// Process default methods on interfaces
// 解析配置类所实现的接口中的@Bean,但并没有真正处理@Bean,只是暂时找出来
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;
}
/**
* 内部类的处理
*/
private void processMemberClasses(ConfigurationClass configClass, SourceClass sourceClass,
Predicate<String> filter) throws IOException {
// 得到所有的内部类
Collection<SourceClass> memberClasses = sourceClass.getMemberClasses();
if (!memberClasses.isEmpty()) {
List<SourceClass> candidates = new ArrayList<>(memberClasses.size());
for (SourceClass memberClass : memberClasses) {
// 内部类是不是lite配置类
if (ConfigurationClassUtils.isConfigurationCandidate(memberClass.getMetadata()) &&
!memberClass.getMetadata().getClassName().equals(configClass.getMetadata().getClassName())) {
candidates.add(memberClass);
}
}
// 排序
OrderComparator.sort(candidates);
for (SourceClass candidate : candidates) {
// AppConfig中有一个内部类A, A上用@Import导入AppConfig.class,就出现了循环import
if (this.importStack.contains(configClass)) {
// 就是直接抛异常
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
}
else {
this.importStack.push(configClass);
try {
// 配置类进行处理
processConfigurationClass(candidate.asConfigClass(configClass), filter);
}
finally {
this.importStack.pop();
}
}
}
}
}
结束语
- 获取更多本文的前置知识文章,以及新的有价值的文章,让我们一起成为架构师!
- 关注公众号,可以让你对MySQL、并发编程、spring源码有深入的了解!
- 关注公众号,后续持续高效的学习JVM!
- 这个公众号,无广告!!!每日更新!!!