简单看一下Spring容器创建时,如何解析@Configuration配置类。
此处以SpringBoot2.1.8版本新建的一个简单HelloWorld Web项目为例学习相关源码。
大致路径如下:
- 创建容器时(构造方法或者父类的构造方法中)会创建一个AnnotatedBeanDefinitionReader,在其初始化的时候会调用AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry)方法为容器注册一些内部的组件。
ConfigurationClassPostProcessor就是在此处注册。 - ConfigurationClassPostProcessor根据源码可以看出其实现了BeanDefinitionRegistryPostProcessor接口(该接口实现了BeanFactoryPostProcessor接口)。主要有两个方法postProcessBeanFactory(后执行,仅加了@Configuration注解的配置类会创建代理类CGLIB)和postProcessBeanDefinitionRegistry,两个方法中都有这一段逻辑:processConfigBeanDefinitions(registry);在此方法中实例化了一个ConfigurationClassParser
- ConfigurationClassParser类的parse方法正式处理我们的@Configuration配置类
从启动类开始:
SpringApplication.run(PracticeApplication.class, args);
------->进入run方法
SpringApplication 308行
context = createApplicationContext();
由于该项目添加了Web模块,所以创建的为AnnotationConfigServletWebServerApplicationContext;
看一下构造函数:
public AnnotationConfigServletWebServerApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
进入AnnotatedBeanDefinitionReader构造函数:
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
this(registry, getOrCreateEnvironment(registry));
}
最终调用到
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
AnnotationConfigUtils
来看一下AnnotationConfigUtils的该方法做了什么,取出默认的DefaultListableBeanFactory ,为其注册相关组件。组件org.springframework.context.annotation.internalConfigurationAnnotationProcessor=ConfigurationClassPostProcessor就是在此处注册的,还有其他的一些组件。
public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalConfigurationAnnotationProcessor";
.....
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) {
//获取DefaultListableBeanFactory
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
.......
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
//注册org.springframework.context.annotation.internalConfigurationAnnotationProcessor=ConfigurationClassPostProcessor
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
.......
return beanDefs;
}
ConfigurationClassPostProcessor
看一下简单类图和源码
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {
...
}
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
...
}
以上可以看出,ConfigurationClassPostProcessor 实现了BeanDefinitionRegistryPostProcessor接口(该接口继承自BeanFactoryPostProcessor),该接口继承自BeanFactoryPostProcessor 。这样在容器创建刷新时将会调用ConfigurationClassPostProcessor 的postProcessBeanFactory(后执行,仅加了@Configuration注解的配置类会创建代理类CGLIB)和postProcessBeanDefinitionRegistry方法。
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
实际调用在这
public void processConfigBeanDefinitions (BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
//此处获取的candidateNames:-->register的配置类名和在初始化时注册的Spring内部处理类
String[] candidateNames = registry.getBeanDefinitionNames();
//for循环的目的是找出未被处理过的加了@Configuration等注解的bean
for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
//如果beanDef是full或者lite则表明是已经被处理过的
// full为加了@Configuration注解的,
// lite为未加@Configuration,@Component、@ComponentScan、@Import、@ImportResource和方法上是否有@Bean注解
if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) || ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
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));
}
}
//如果没有找到配置类,则立即返回
if (configCandidates.isEmpty()) {
return;
}
//根据优先级排序
// Sort by previously determined @Order value, if applicable
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
//设置BeanName的生成策略
SingletonBeanRegistry sbr = null;
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry) registry;
if (!this.localBeanNameGeneratorSet) {
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
if (generator != null) {
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
}
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
// Parse each @Configuration class
/*
* 新建一个ConfigurationClassParser去解析每个加了@Configuration的类,registry=DefaultListableBeanFactory
*/
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 {
//实际处理逻辑
parser.parse(candidates);
************************
最终会调用到:
源码如下:
@Nullable
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
throws IOException {
//处理@Component注解
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
// Recursively process any member (nested) classes first
processMemberClasses(configClass, sourceClass);
}
//处理 @PropertySource注解
// 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");
}
}
//处理@ComponentScan注解
// 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());
}
}
}
}
//处理@Import注解
// Process any @Import annotations
processImports(configClass, sourceClass, getImports(sourceClass), 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);
}
}
//处理@Bean的方法
// 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);
// 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;
}