之前介紹 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的