之前介绍 ConfigurationClassPostProcessor时很关键的类,解析@Configuration的类
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {
...................................
其中:public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
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));
}
}
其实对于Appconfig类,加不加@Configuration无所谓,后面有@ComponentScan,。。。同样可以,加了便是FullConfigurationClass, 不加是isLiteConfigurationClass
ConfigurationClassPostProcessor会调用ConfigurationClassUtils来判断
abstract class ConfigurationClassUtils {
private static final String CONFIGURATION_CLASS_FULL = "full"; //全注解
private static final String CONFIGURATION_CLASS_LITE = "lite"; //部分注解类,
........................................................
if (isFullConfigurationCandidate(metadata)) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
}
else if (isLiteConfigurationCandidate(metadata)) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
}
else {
return false;
@import引入类有三种形式,帮助把importClass注册到beanfactory,以bd形式,这里先说明实现ImportSelector的形式
@Configuration
@ComponentScan("com.lmq.BaseService")
//@Import(MyImportBeanDefinitionRegistrar.class)
@Import(MyImportSelector.class)
public class AppConfig {
}
import org.springframework.core.type.AnnotationMetadata;
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{LmqService2.class.getName()};
}
}
这里在ConfigurationClassPostProcessor中,new ConfigurationClassParser,
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
调用
ConfigurationClassParser的方法:
// Process any @Import annotations
processImports(configClass, sourceClass, getImports(sourceClass), true);
具体怎么处理可查看源码,判断一组类是不是import(三种,比如这里是MyImportSelector,便是)
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, 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) {
if (candidate.isAssignable(ImportSelector.class)) {
// Candidate class is an ImportSelector -> delegate to it to determine imports
Class<?> candidateClass = candidate.loadClass();
ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
ParserStrategyUtils.invokeAwareMethods(
selector, this.environment, this.resourceLoader, this.registry);
if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {
this.deferredImportSelectors.add(
new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector));
}
else {
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
processImports(configClass, currentSourceClass, importSourceClasses, false);//递归调用,因为
//importclass可能也有@import注解
}
}
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 =
BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
ParserStrategyUtils.invokeAwareMethods(
registrar, this.environment, this.resourceLoader, this.registry);
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
}
else {
// 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));
}
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);
}
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());//反射invok额方法获取要引入的类
最后吧import中的class(比如上面的LmqService2.class)放在this.configurationClasses.put(configClass, configClass);
然后再合并到beanFactory中的bd map,具体就是parser完,回到ConfigurationClassPostProcessor中
do {
parser.parse(candidates);
parser.validate();
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());//就是上面放置的包括处理@import得到的class,也包括@Config的类
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());
}
this.reader.loadBeanDefinitions(configClasses);//把没有加到bd map中的加入,比如包括myimportselecotr的lmqservice2
alreadyParsed.addAll(configClasses);
........................................
对于ImportBeanDefinitionRegistrar.class的·import类似,没有递归
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 =
BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
ParserStrategyUtils.invokeAwareMethods(
registrar, this.environment, this.resourceLoader, this.registry);
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
}
不过提前放的map不一样
public void addImportBeanDefinitionRegistrar(ImportBeanDefinitionRegistrar registrar, AnnotationMetadata importingClassMetadata) {
this.importBeanDefinitionRegistrars.put(registrar, importingClassMetadata);
}
那么什么时候把这些importBeanDefinitionRegistrar.class impor的·类注册到bd map中?
还是上面的loadBeanDefinitions,
this.reader.loadBeanDefinitions(configClasses);//
进入,如下,在里面处理了,所以importBeanDefinitionRegistrar.class impor的·类注册到bd map
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
其中的configClass.getImportBeanDefinitionRegistrars()就是上面的 this.importBeanDefinitionRegistrars.put(registrar, importingClassMetadata);然后循环注册到this.registry(等同于beanfactory的applictionConetxt),如下
private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
registrars.forEach((registrar, metadata) ->
registrar.registerBeanDefinitions(metadata, this.registry));//
}
总结:bd注册流程,1,解析config 2,扫描得到所有@component的普通类 3,处理Import,注册imported 的bd
至此,所有
BeanDefinitionRegistryPostProcessor(BeanFactoryPostProcessor的子类接口)
处理完后,回到最初的起点
往后面处理继续处理回调invokeBeanFactoryPostProcessors,使用BeanFactoryPostProcessor处理,
} sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); } // Now, invoke the postProcessBeanFactory callback of all processors handled so far. invokeBeanFactoryPostProcessors(registryProcessors, beanFactory); //回调处理同时继承BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor的,比如ConfigurarionClassPostProcessor invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);//回调BeanFactoryPostProcessor的