这篇文章是继《Spring之启动过程源码解析之后》,对Spring启动过程中用到的几个重要的方法进行详细的解读
目录
一、invokeBeanFactoryPostProcessors(),执行BeanFactoryPostProcessor
1. 方法说明
2. invokeBeanFactoryPostProcessors()内部执行流程
二、registerBeanPostProcessors(),向BeanFactory中注册BeanPostProcessor
1.方法说明
2. registerBeanPostProcessors()内部执行流程
三、postProcessBeanDefinitionRegistry()解析
1. 方法总览
2. 处理流程
四、关于@Configuration注解
1. 生成代理类
2. 代理类的作用
3. 总结
在Spring启动过程中,当执行到invokeBeanFactoryPostProcessors()这个方法的时候,就意味着要执行BeanFactoryPostProcessor了,此时在BeanFactory中会存在一个BeanFactoryPostProcessor: ConfigurationClassPostProcessor,它也是一个BeanDefinitionRegistryPostProcessor;
2.1. 获取BeanFactoryPostProcessors,并且执行通过ApplicationContext添加进来的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry()方法,注意:这里获取到的是通过ApplicationContext的addBeanFactoryPostProcessor()添加的BeanFactoryPostProcessor,我们自己定义的BeanFactoryPostProcessor如果没有像这样设置,在这里是获取不到的,因为Spring也得通过扫描才能发现;
2.2. 从BeanFactory中找到类型为BeanDefinitionRegistryPostProcessor的beanName, 匹配实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor,这里匹配到的是ConfigurationClassPostProcessor,同时会调用BeanFactory的getBean方法,将ConfigurationClassPostProcessor的对象创建出来,并执行它的postProcessBeanDefinitionRegistry()方法,在这一步会得到BeanDefinition;
注意:在ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry()方法会进行扫描,得到BeanDefinition并注册,下面会有关于这个方法的详细分析;
2.3. 从BeanFactory中找到类型为BeanDefinitionRegistryPostProcessor的beanName,匹配实现了Ordered接口的BeanDefinitionRegistryPostProcessor,执行BeanFactory中实现了Ordered接口的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry()方法;
说明:因为在上面那一步中,Spring就会进行扫描,所以这里从BeanFactory中找到类型为BeanDefinitionRegistryPostProcessor的beanName也包括我们自定义的;
2.4. 执行那些没有实现了PriorityOrdered或Ordered接口的普通BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry()方法;
2.5. 执行上面所有的BeanDefinitionRegistryPostProcessor的postProcessBeanFactory()方法;
2.6. 执行通过ApplicationContext添加进来的BeanFactoryPostProcessor的 postProcessBeanFactory()方法;
2.7. 执行BeanFactory中实现了PriorityOrdered接口的BeanFactoryPostProcessor的 postProcessBeanFactory()方法;
2.8. 执行BeanFactory中实现了Ordered接口的BeanFactoryPostProcessor的 postProcessBeanFactory()方法;
2.9. 执行BeanFactory中其他的BeanFactoryPostProcessor的postProcessBeanFactory()方法;
因为上面的步骤完成了扫描,这个过程中开发者可能自己定义了一些BeanPostProcessor,在这一步就会把BeanFactory中所有的BeanPostProcessor找出来并实例化得到一个对象,并添加到BeanFactory中去(属性beanPostProcessors),最后再重新添加一个ApplicationListenerDetector对象(之前其实就添加过了,这里是为了把ApplicationListenerDetector移动到最后);
2.1. 获取BeanFactory中所有实现了BeanPostProcessor接口的beanName;
2.2. 声明不同的集合并初始化,以便后面对BeanPostProcessor进行分类;
2.3. 遍历2.1 获取的beanName集合,对BeanPostProcessor进行分类:
① 首先根据beanName,匹配实现了PriorityOrdered接口的BeanPostProcessor, 并得到其实例对象,如果这个实例对象同时实现了MergedBeanDefinitionPostProcessor,还需要将它单独记录;
② 否则,匹配实现了Ordered接口的BeanPostProcessor,但是这里并没有去beanFactory中获取实例对象,而是将符合条件的beanName存到了一个集合中;
③ 如果不满足①②,则将没有实现任何排序接口的beanName也存到了一个集合中;
2.4. 对实现了PriorityOrdered接口的BeanPostProcessor实例进行排序,然后注册到beanFactory中(会存到beanPostProcessors这个List中);
2.5. 遍历实现了Ordered接口的BeanPostProcessor的beanName ,获取其实例,并添加到相应的集合中,如果实现了MergedBeanDefinitionPostProcessor则存放到相应的集合中,然后排序注册到beanFactory中;
2.6. 遍历剩余实现了BeanPostProcessor接口beanName ,获取其实例添加到相应的集合中,如果实现了MergedBeanDefinitionPostProcessor则存放到相应的集合中 , 然后注册到beanFactory中;
2.7. 将前面收集到的实现了MergedBeanDefinitionPostProcessor的BeanPostProcessor实例进行排序,重新注册到beanFactory中;
2.8. 将ApplicationListenerDetector注册到beanFactory中,在prepareBeanFactory(beanFactory)方法中,Spring其实就已经将ApplicationListenerDetector注册到了beanFactory中,这里重新注册,目的是将它放到最后;
说明:Spring将MergedBeanDefinitionPostProcessor排在最后,是因为Spring把这些MergedBeanDefinitionPostProcessor当做是Spring内部的BeanPostProcessors,这里可能存在一个用户优先的原则;
/**
* 向BeanFactory中注册BeanPostProcessor
*/
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
/**
* 获取BeanFactory中所有实现了BeanPostProcessor接口的beanName
* 不包括prepareBeanFactory(beanFactory)这一步添加到beanFactory中的三个BeanPostProcessor实例对象
* 这三个实例对象在Spring进行扫描之前就已经添加到了beanPostProcessors这个list中
*/
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
// Register BeanPostProcessorChecker that logs an info message when
// a bean is created during BeanPostProcessor instantiation, i.e. when
// a bean is not eligible for getting processed by all BeanPostProcessors.
//beanProcessorTargetCount表示BeanFactory中所有的BeanPostProcessor数量,+1表示BeanPostProcessorChecker
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// Separate between BeanPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
/**
* 存放实现了PriorityOrdered接口的BeanPostProcessor实例
*/
List priorityOrderedPostProcessors = new ArrayList<>();
/**
* 存放实现了MergedBeanDefinitionPostProcessor接口的BeanPostProcessor实例
* 主要是Spring内部的BeanPostProcessor,例如:AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor
*/
List internalPostProcessors = new ArrayList<>();
/**
* 存放实现了Ordered接口的BeanPostProcessor实例
*/
List orderedPostProcessorNames = new ArrayList<>();
/**
* 存放剩余的BeanPostProcessor实例
*/
List nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
/**
* 实现了PriorityOrdered接口的话就获取实例存放到集合中
* 如果实例实现了MergedBeanDefinitionPostProcessor中存放到相应的集合中
*/
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
/**
* 实现了Ordered接口的话就将beanName存放到相应集合中
*/
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
/**
* 没有实现任何排序接口的话就将beanName存放到相应集合中
*/
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, register the BeanPostProcessors that implement PriorityOrdered.
/**
* 升序排序
* 对实现了PriorityOrdered接口的BeanPostProcessor实例进行排序,然后注册到容器中
*/
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// Next, register the BeanPostProcessors that implement Ordered.
/**
* 遍历实现了Ordered接口的BeanPostProcessor的beanName
* 获取其实例添加到相应的集合中,如果实现了MergedBeanDefinitionPostProcessor则存放到相应的集合中
* 然后排序注册到容器中
*/
List orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
// Now, register all regular BeanPostProcessors.
/**
* 遍历剩余实现了BeanPostProcessor接口beanName
* 获取其实例添加到相应的集合中,如果实现了MergedBeanDefinitionPostProcessor则存放到相应的集合中
* 然后注册到容器中
*/
List nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
// Finally, re-register all internal BeanPostProcessors.
/**
* MergedBeanDefinitionPostProcessor排在最后
* 最后排序实现了MergedBeanDefinitionPostProcessor接口的BeanPostProcessor
* 然后注册到容器中
*/
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
// Re-register post-processor for detecting inner beans as ApplicationListeners,
// moving it to the end of the processor chain (for picking up proxies etc).
// ApplicationListenerDetector放在所有BeanPostProcessor之后,注意ApplicationListenerDetector的equals()方法实现
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
在执行invokeBeanFactoryPostProcessors()方法的过程中,会获取Spring内部提供的ConfigurationClassPostProcessor,执行其中的postProcessBeanDefinitionRegistry()以及postProcessBeanFactory()方法;
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);
}
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List configCandidates = new ArrayList<>();
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)) {
//BeanDefinitionHolder顾明思义就是对BeanDefinition的持有,作用是根据名称或者别名持有beanDefination,承载了name和BeanDefination的映射信息
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) {
// BeanNameGenerator,bean名字生成器
// 可以预先往单例池中添加一个beanName为CONFIGURATION_BEAN_NAME_GENERATOR的BeanNameGenerator类型的bean
// 用来作为bean名字生成器,生成扫描得到的Bean和import导入进来的Bean的beanName
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();
}
//上面已经找到配置类了,接下来就是去解析配置类,所以这里会构造一个配置类的解析器
// Parse each @Configuration class
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
Set candidates = new LinkedHashSet<>(configCandidates);
Set alreadyParsed = new HashSet<>(configCandidates.size());
// 递归解析配置类,有可能通过解析一个配置类,得到了其他的配置类,比如扫描和Import
do {
StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
// 解析配置类,会把每个BeanDefinitionHolder首先封装为ConfigurationClass
// 在这个过程中会进行扫描、导入等步骤,从而会找到其他的ConfigurationClass
// 解析配置类的结果是什么?
parser.parse(candidates); // AppConfig.class--->BeanDefinition
parser.validate();
//由于解析配置类有可能会得到其它配置类,这里获取到的是目前为止所有的配置类,而且这些配置类是被解析过了的,但并不表示整个Spring容器只有这些配置类
//例如解析AppConfig.class后,会得到其它的一些配置类
// configClasses相当于就是解析之后的结果
Set 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注解的方法,会对应多个BeanDefination,一个配置类配置了@ImportResource,基本也会得到多个BeanDefintion
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 oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
Set 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();
}
}
1. 从BeanFactory中,获取已经添加到Bean工厂中的BeanDefination
这里获取到的通常是在容器启动过程中Spring添加到BeanFactory中的BeanDefination,以及通过ApplicationContext的register()方法注册的类对应的BeanDefination;
2. 找配置类
2.1. 获取BeanDefination对应的类上面的注解的元数据,AnnotationMetadata表示某个类的注解信息;
2.2. 判断这个类上面有没有加@Configuration注解,进一步确定当前的类是不是配置类;
那什么样的类才算是配置类呢?这是才确定配置类的关键,符号以下条件的都会被判断为是配置类:
① 加了@Configuration注解,并且proxyBeanMethods不为false(为true或为null)时,就是full配置类;
② 加了@Configuration注解,并且proxyBeanMethods为false时,是lite配置类;
③ 没有加@Configuration注解,但是只要存在@Component、@ComponentScan、@Import、 @ImportResource四个中的一个,就是lite配置类;
④没有加@Configuration注解,只要存在加了@Bean注解的方法,就是lite配置类;
3.解析配置类
配置类思维脑图:ProcessOn Mindmap
3.1. 首先会把类的元信息和beanName封装为ConfigurationClass;
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
// 把类的元信息和beanName封装为ConfigurationClass
processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
}
3.2. 处理配置类,配置类解析过后,最终会将解析过的配置类放到configurationClasses这个map中;
protected void processConfigurationClass(ConfigurationClass configClass, Predicate 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,就会符合这个条件
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, filter);
do {
//有可能配置类还有父类,所以这里会有一个循环处理
sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
}
while (sourceClass != null);
// ConfigurationClass重写了equals方法,只要两个ConfigurationClass对应的className相等就可以
this.configurationClasses.put(configClass, configClass);
}
3.3 如果配置类上有@Component注解,就要进一步判断加了@Component注解的配置类,有没有内部类,如果有,则判断内部类是不是配置类,如果是,就要解析内部类;
/**
* 这样配置最终也会被Spring解析为配置类
*/
@Component
public class AppConfig implements AppInterface {
// 内部类
class User{
@Bean
public UserService userService(){
return new UserService();
}
}
}
3.4. 如果配置类上加了@PropertySource注解,读取注解中指定的配置文件,将文件中的内容解析出来,放到environment中,例如@PropertySource("spring.properties");
3.5. 如果配置类上加了@ComponentScan注解,Spring就会进行扫描,得到的BeanDefinition会注册到Spring容器中,并且会检查扫描出来的BeanDefinition是不是配置类并进行解析;
说明:从定义来看,@Configuration 注解本质上还是@Component,因此,
3.6. 如果配置类上加了@Import()注解,解析注解中导入的类,那就要分情况了:
① 如果import的类实现了ImportSelector接口,将这个类实例化出来,又会分为两种情况:
如果这个实例是DeferredImportSelector类型的,表示推迟的ImportSelector,它会在当前这一批配置类都解析完了之后执行;
public void parse(Set configCandidates) {
for (BeanDefinitionHolder holder : configCandidates) {
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();
}
如果这个实例不是DeferredImportSelector类型的,就会执行selectImports()方法,处理它返回的 类,这些返回的类会被当认为是导入进来的类,进而继续调用processImports()方法;
② 如果import的类实现了ImportBeanDefinitionRegistrar接口,将这个类实例化出来,然后将实例作为属性添加到configClass里面;
③ 如果导入的类是普通类,那就把它当做配置类来解析;
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection importCandidates, Predicate 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) {
// 如果import的类实现了ImportSelector接口
if (candidate.isAssignable(ImportSelector.class)) {
// Candidate class is an ImportSelector -> delegate to it to determine imports
Class> candidateClass = candidate.loadClass();
//将这个类实例化出来
ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
this.environment, this.resourceLoader, this.registry);
Predicate selectorFilter = selector.getExclusionFilter();
if (selectorFilter != null) {
exclusionFilter = exclusionFilter.or(selectorFilter);
}
// 如果import的是DeferredImportSelector,表示推迟导入
if (selector instanceof DeferredImportSelector) {
this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
} else {
// 如果import的是普通的ImportSelector
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
// 继续处理selectImports()所返回的类,这些返回的类被认为是导入进来的类,
Collection importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
}
}
// 如果import的类实现了ImportBeanDefinitionRegistrar接口
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 =
ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
this.environment, this.resourceLoader, this.registry);
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
}
// 如果import的类就是普通的类,就把import进来的类当做配置类
else {
// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
// process it as an @Configuration class
this.importStack.registerImport(
currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
// 注意,在asConfigClass方法中,不仅会将candidate生成一个ConfigurationClass,还会记录一下candidate是被哪个类导入的importedBy
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);
}
finally {
this.importStack.pop();
}
}
}
3.7. 如果配置类上加了ImportResource()注解,则获取注解中资源,将资源加入到当前配置类的属性中,此处仅仅是把注解内容解析出来,然后作为属性添加到configClass里面去,还并不是它真正的执行时机;
一个通用的结论:
@PropertySource()用于导入.properties属性配置文件;
@ImportResource()用于导入.xml的Bean信息的配置文件;
3.8. 将配置类中加了@Bean注解的方法找到并记录,但这里并没有真正处理@Bean;
3.9. 解析配置类所实现的接口中有没有default的方法上是加了@Bean的,但并没有真正处理@Bean;
3.10. 如果当前配置类还有父类,将父类返回继续处理父类;
@Nullable
protected final SourceClass doProcessConfigurationClass(
ConfigurationClass configClass, SourceClass sourceClass, Predicate filter)
throws IOException {
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注解)
//如果配置类上加了@PropertySource,读取@PropertySource("spring.properties")中指定的配置文件,将文件中的内容解析出来,放到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(处理@ComponentScan注解)
// 会进行扫描,得到的BeanDefinition会注册到Spring容器中,并且会检查是不是配置类并进行解析
Set 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 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(处理@Import注解)
// 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) {
// 显然它还支持${}这种方式去环境变量里取值的,比如spring-beans-${profie}.xml等
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
//将资源加入到当前配置类的属性中,此处仅仅是把注解解析出来,然后作为属性添加到configClass里面去,还并不是它真正的执行时机
configClass.addImportedResource(resolvedResource, readerClass);
}
}
// Process individual @Bean methods
// 将配置类中加了@Bean注解的方法找到并记录,但并没有真正处理@Bean,即并没有真正地去解析加了@Bean注解的方法并生成BeanDefination,只是暂时找出来
Set beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// Process default methods on interfaces
// 解析配置类所实现的接口中有没有default的方法上是加了@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;
}
4. 针对解析过的配置类去加载BeanDefinition
4.1. 根据解析过的配置类去生成对应的BeanDefinition
回到processConfigBeanDefinitions()这个方法,由于执行parser.parse(candidates)解析配置类,
有可能会得到其它配置类,而所有的这些配置类中,如果有@Bean注解的方法、或者加了@ImportResource注解、或者是实现了ImportBeanDefinitionRegistrar接口的,在解析配置类的时候,只是把它们作为配置类的属性存储起来,还没有真正的处理,到this.reader.loadBeanDefinitions(configClasses)这一步才会真正的处理,生成BeanDefinition;
public void loadBeanDefinitions(Set configurationModel) {
TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
for (ConfigurationClass configClass : configurationModel) {
loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
}
}
private void loadBeanDefinitionsForConfigurationClass(
ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
if (trackedConditionEvaluator.shouldSkip(configClass)) {
String beanName = configClass.getBeanName();
if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
this.registry.removeBeanDefinition(beanName);
}
this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
return;
}
if (configClass.isImported()) {
// 将被导入的类生成BeanDefinition并注册到Spring容器中
// @Component的内部类,@Import所导入的类都是被导入的类
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
// @Bean生成BeanDefinition并注册
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
loadBeanDefinitionsForBeanMethod(beanMethod);
}
// 处理@ImportResource("spring.xml")
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
// 处理ImportBeanDefinitionRegistrar,调用registerBeanDefinitions()方法
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
4.2. 基于上述 4.1. 如果有新的BeanDefinition生成,还需要去判断是不是配置类、去解析,所以,这也是会出现do ...while循环的原因;
do {
StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
// 解析配置类,会把每个BeanDefinitionHolder首先封装为ConfigurationClass
// 在这个过程中会进行扫描、导入等步骤,从而会找到其他的ConfigurationClass
// 解析配置类的结果是什么?
parser.parse(candidates); // AppConfig.class--->BeanDefinition
parser.validate();
//由于解析配置类有可能会得到其它配置类,这里获取到的是目前为止所有的配置类,而且这些配置类是被解析过了的,但并不表示整个Spring容器只有这些配置类
//例如解析AppConfig.class后,会得到其它的一些配置类
// configClasses相当于就是解析之后的结果
Set 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注解的方法,会对应多个BeanDefination,一个配置类配置了@ImportResource,基本也会得到多个BeanDefintion
//比如在下面这行代码执行之前,AppConfig1,是没有被解析过的,在这里才会被解析到,并且会生成BeanDefination,所以这里有可能又会得到一些新的BeanDefination
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 oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
Set 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());
执行完BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry()方法后,紧接着会执行postProcessBeanFactory()方法,在postProcessBeanFactory()方法中会为加了Configuration注解的配置类,生成代理类,注意:只有是full配置类时,才会为其生成代理类;
/**
* Prepare the Configuration classes for servicing bean requests at runtime
* by replacing them with CGLIB-enhanced subclasses.
*/
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
int factoryId = System.identityHashCode(beanFactory);
if (this.factoriesPostProcessed.contains(factoryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + beanFactory);
}
this.factoriesPostProcessed.add(factoryId);
if (!this.registriesPostProcessed.contains(factoryId)) {
// BeanDefinitionRegistryPostProcessor hook apparently not supported...
// Simply call processConfigurationClasses lazily at this point then.
processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
}
// 增强配置类,代理加了Configuration注解的配置类
enhanceConfigurationClasses(beanFactory);
beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
StartupStep enhanceConfigClasses = this.applicationStartup.start("spring.context.config-classes.enhance");
Map configBeanDefs = new LinkedHashMap<>();
// 遍历,找出配置类
for (String beanName : beanFactory.getBeanDefinitionNames()) {
BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE);
AnnotationMetadata annotationMetadata = null;
MethodMetadata methodMetadata = null;
if (beanDef instanceof AnnotatedBeanDefinition) {
AnnotatedBeanDefinition annotatedBeanDefinition = (AnnotatedBeanDefinition) beanDef;
annotationMetadata = annotatedBeanDefinition.getMetadata();
methodMetadata = annotatedBeanDefinition.getFactoryMethodMetadata();
}
if ((configClassAttr != null || methodMetadata != null) && beanDef instanceof AbstractBeanDefinition) {
// Configuration class (full or lite) or a configuration-derived @Bean method
// -> eagerly resolve bean class at this point, unless it's a 'lite' configuration
// or component class without @Bean methods.
AbstractBeanDefinition abd = (AbstractBeanDefinition) beanDef;
// 没有加载类就去加载
if (!abd.hasBeanClass()) {
boolean liteConfigurationCandidateWithoutBeanMethods =
(ConfigurationClassUtils.CONFIGURATION_CLASS_LITE.equals(configClassAttr) &&
annotationMetadata != null && !ConfigurationClassUtils.hasBeanMethods(annotationMetadata));
if (!liteConfigurationCandidateWithoutBeanMethods) {
try {
abd.resolveBeanClass(this.beanClassLoader);
}
catch (Throwable ex) {
throw new IllegalStateException(
"Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
}
}
}
}
if (ConfigurationClassUtils.CONFIGURATION_CLASS_FULL.equals(configClassAttr)) {
if (!(beanDef instanceof AbstractBeanDefinition)) {
throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" +
beanName + "' since it is not stored in an AbstractBeanDefinition subclass");
}
else if (logger.isInfoEnabled() && beanFactory.containsSingleton(beanName)) {
logger.info("Cannot enhance @Configuration bean definition '" + beanName +
"' since its singleton instance has been created too early. The typical cause " +
"is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor " +
"return type: Consider declaring such methods as 'static'.");
}
configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
}
}
if (configBeanDefs.isEmpty() || NativeDetector.inNativeImage()) {
// nothing to enhance -> return immediately
enhanceConfigClasses.end();
return;
}
// 生成代理类,并设置到BeanDefinition中,针对的是full配置类
ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
for (Map.Entry entry : configBeanDefs.entrySet()) {
AbstractBeanDefinition beanDef = entry.getValue();
// If a @Configuration class gets proxied, always proxy the target class
beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
// Set enhanced subclass of the user-specified bean class
Class> configClass = beanDef.getBeanClass(); // Appconfig
// 生成代理类
Class> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
if (configClass != enhancedClass) {
if (logger.isTraceEnabled()) {
logger.trace(String.format("Replacing bean definition '%s' existing class '%s' with " +
"enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName()));
}
//将当前配置类对应的BeanDefination对象的beanClass属性,设置成代理类
//所以当根据这些BeanDefination创建Bean的时候,生成出来的是代理对象
beanDef.setBeanClass(enhancedClass);
}
}
enhanceConfigClasses.tag("classCount", () -> String.valueOf(configBeanDefs.keySet().size())).end();
}
由于生成代理类后,当前配置类对应的BeanDefination对象中的beanClass属性会被设置为代理类,所以当根据这些BeanDefination创建Bean的时候,创建出来的就是代理对象了,那么在执行代理对象中的方法的时候(比如,加了@Bean注解的方法),就有可能执行的是代理逻辑了,那代理逻辑解决的问题是什么?
① 如果代理对象正在执行的方法就是当前正在创建的Bean的工厂方法,那就直接执行对应的方法得到对象作为Bean,什么意思呢?例如,Spring在创建OrderService类型的Bean的时候会在创建Bean实例(即createBeanInstance())这一步,处理@Bean对应的BeanDefinition,那么就会调用orderService()方法实例化OrderService对象,并且会记录当前正在调用的factoryMethod(也就是orderService()),由于此时的factoryBean是代理对象,所以会执行代理逻辑;调用orderService()方法实例化OrderService对象如下:
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
@Nullable Object factoryBean, final Method factoryMethod, Object... args) {
try {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction
代理逻辑如下:
public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
MethodProxy cglibMethodProxy) throws Throwable {
// enhancedConfigInstance是代理对象
ConfigurableBeanFactory beanFactory = getBeanFactory(enhancedConfigInstance);
String beanName = BeanAnnotationHelper.determineBeanNameFor(beanMethod);
// Determine whether this bean is a scoped-proxy
if (BeanAnnotationHelper.isScopedProxy(beanMethod)) {
String scopedBeanName = ScopedProxyCreator.getTargetBeanName(beanName);
if (beanFactory.isCurrentlyInCreation(scopedBeanName)) {
beanName = scopedBeanName;
}
}
// To handle the case of an inter-bean method reference, we must explicitly check the
// container for already cached instances.
// First, check to see if the requested bean is a FactoryBean. If so, create a subclass
// proxy that intercepts calls to getObject() and returns any cached bean instance.
// This ensures that the semantics of calling a FactoryBean from within @Bean methods
// is the same as that of referring to a FactoryBean within XML. See SPR-6602.
if (factoryContainsBean(beanFactory, BeanFactory.FACTORY_BEAN_PREFIX + beanName) &&
factoryContainsBean(beanFactory, beanName)) {
Object factoryBean = beanFactory.getBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName);
if (factoryBean instanceof ScopedProxyFactoryBean) {
// Scoped proxy factory beans are a special case and should not be further proxied
}
else {
// It is a candidate FactoryBean - go ahead with enhancement
return enhanceFactoryBean(factoryBean, beanMethod.getReturnType(), beanFactory, beanName);
}
}
// 如果代理对象正在执行的方法就是当前正在创建Bean的工厂方法,那就直接执行对应的方法得到对象作为Bean
if (isCurrentlyInvokedFactoryMethod(beanMethod)) {
// The factory is calling the bean method in order to instantiate and register the bean
// (i.e. via a getBean() call) -> invoke the super implementation of the method to actually
// create the bean instance.
if (logger.isInfoEnabled() &&
BeanFactoryPostProcessor.class.isAssignableFrom(beanMethod.getReturnType())) {
logger.info(String.format("@Bean method %s.%s is non-static and returns an object " +
"assignable to Spring's BeanFactoryPostProcessor interface. This will " +
"result in a failure to process annotations such as @Autowired, " +
"@Resource and @PostConstruct within the method's declaring " +
"@Configuration class. Add the 'static' modifier to this method to avoid " +
"these container lifecycle issues; see @Bean javadoc for complete details.",
beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName()));
}
// 注意这里传入的是代理对象,相当于在执行父类的方法,注意和Spring事务做区分
return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
}
// 如果代理对象正在执行的方法不是正在创建Bean的方法,那就直接根据方法的名字去Spring容器中获取
return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
}
② 如果代理对象正在执行的方法不是正在创建的Bean的工厂方法,那就直接根据方法的名字去Spring容器中获取,这样可以保证@Bean方法的单例;上述①②情况代码示例如下:
@Configuration
public class AppConfig {
// 这里的orderService()方法会调三次,还有一次是Spring启动,创建OrderService类型的Bean的时候会调
@Bean
public UserService userService() {
System.out.println(orderService());
System.out.println(orderService());
return new UserService();
}
@Bean
public OrderService orderService(){
return new OrderService();
}
}
@Bean之间的方法调用是怎么保证单例的?( @Configuration加与不加的区别是什么?)
1.如果希望@Bean的方法返回是对象是单例 需要在类上面加上@Configuration;
2.Spring 会在invokeBeanFactoryPostProcessor 中,通过内置BeanFactoryPostProcessor会生成CGLib动态代理对象;
3.当@Bean方法进行互调时, 则会通过CGLIB进行增强,通过调用的方法名作为Bean的名称去ioc容器中获取,进而保证了@Bean方法的单例;