- 三哥
内容来自【自学星球】
欢迎大家来了解我的星球,和星主(也就是我)一起学习 Java ,深入 Java 体系中的所有技术。我给自己定的时间是一年,无论结果如何,必定能给星球中的各位带来点东西。
想要了解更多,欢迎访问👉:自学星球
--------------SSM系列源码文章及视频导航--------------
创作不易,望三连支持!
SSM源码解析视频
👉点我
Spring
SpringMVC
MyBatis
---------------------【End】--------------------
进入源码
org.springframework.context.support.AbstractApplicationContext#invokeBeanFactoryPostProcessors
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
// 重点在这个方法
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
再次进入
org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
// 优先执行 BeanDefinitionRegistryPostProcessors
// 将已经执行的 postProcessBeanDefinitionRegistry 存储在 processedBeans 中,防止重复执行
Set<String> processedBeans = new HashSet<>();
// 判断 beanFactory 是否是 BeanDefinitionRegistry,是
if (beanFactory instanceof BeanDefinitionRegistry) {
// 类型强转
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
// 创建两个集合,分别存放不同的 BeanFactory 后置处理器
List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<>();
// 首先处理参数传递过来的 BeanFactoryPostProcessor,遍历所有的BeanFactoryPostProcessors
// 将 BeanDefinitionRegistryPostProcessor 和BeanFactoryPostProcessor 区分开
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
// BeanDefinitionRegistryPostProcessor 类型,先执行 postProcessBeanDefinitionRegistry 方法,在放入 registryProcessors 集合中
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
// beanFactoryPostProcessors 类型,存入 regularPostProcessors 集合中
regularPostProcessors.add(postProcessor);
}
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
// 用于保存本次要执行的 BeanDefinitionRegistryPostProcessor
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
// 调用所有实现 PriorityOrdered 接口的 BeanDefinitionRegistryPostProcessor 实现类
// 找到所有实现BeanDefinitionRegistryPostProcessor 接口的 bean 的beanName
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
// 遍历处理所有的符合规则的postProcessorNames
for (String ppName : postProcessorNames) {
// 检测是否实现PriorityOrdered接口
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
// 获取名字对应的bean实例,添加到currentRegistryProcessors中
// beanFactory.getBean中会进行相关相关bean的实例化工作
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
//将要执行的BFPP名称添加到processedBeans中,避免后续重复执行
processedBeans.add(ppName);
}
}
// 排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
// 添加registryProcessors,用于最后执行的postProcess方法
registryProcessors.addAll(currentRegistryProcessors);
// 遍历currentRegistryProcessors,执行postProcessBeanDefinitionRegistry
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
// 执行完毕,清空currentRegistryProcessors集合
currentRegistryProcessors.clear();
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
// 调用所有实现 Ordered 接口的BeanDefinitionRegistryPostProcessor实现类
// 找到所有实现BeanDefinitionRegistryPostProcessor 接口的bean的beanName
// 此处需要重复查找的原因在于可能在上面执行的过程中会新增新的
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// 检测是否实现Ordered接口,并且还未被执行过
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
// 获取名字对应的bean实例,添加到currentRegistryProcessors中
// beanFactory.getBean中会进行相关相关bean的实例化工作
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
//将要执行的BFPP名称添加到processedBeans中,避免后续重复执行
processedBeans.add(ppName);
}
}
// 排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
// 添加registryProcessors,用于最后执行的postProcess方法
registryProcessors.addAll(currentRegistryProcessors);
//遍历currentRegistryProcessors,执行postProcessBeanDefinitionRegistry
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
//执行完毕,清空currentRegistryProcessors集合
currentRegistryProcessors.clear();
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
// 最后执行其他的 BeanDefinitionRegistryPostProcessor 实现类
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// 只有不包含的才执行, 执行完之后会添加进 processedBeans
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
// 排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
// 添加registryProcessors,用于最后执行的postProcess方法
registryProcessors.addAll(currentRegistryProcessors);
// 遍历currentRegistryProcessors,执行postProcessBeanDefinitionRegistry
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
// 执行完毕,清空currentRegistryProcessors集合
currentRegistryProcessors.clear();
}
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
// 调用所有的BeanDefinitionRegistryPostProcessor的postProcessBeanFactory 方法
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
// 最后调用父类的入参BeanFactoryPostProcessor中普通BeanFactoryPostProcessor的postProcessBeanFactory 方法
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// Invoke factory processors registered with the context instance.
// 如果beanFactory不属于BeanDefinitionRegistry类型,直接执行postProcessBeanFactory方法
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// 到此为止,入参beanFactoryProcessors和容器中所有的BeanDefinitionRegistryPostProcessor已经全部处理完成
// 现在开始处理BeanFactoryPostProcessor
// 这里可能存在一部分只实现了BeanFactoryPostProcessor,没有实现BeanDefinitionRegistryPostProcessor接口的类
// 此处代码beanFactory.getBeanNamesForType在上面进行多次调用,但是传递参数不同,BeanDefinitionRegistryPostProcessor.class会注册实现BeanFactoryPostProcessor接口的类,但是BeanFactoryPostProcessor不会注册新的实现BeanFactoryPostProcessor接口的类
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
// 用于存放实现了priorityOrdered接口的beanName集合
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
// 用于存放实现了ordered接口的BeanFactoryProcessor的beanName
List<String> orderedPostProcessorNames = new ArrayList<>();
// 存放普通的BeanFactoryProcessor的beanName
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
// 遍历postProcessorNames,将三种不同集合区分开
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// 已经执行过的BeanFactoryPostProcessor不再执行
// skip - already processed in first phase above
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
// PriorityOrdered
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
// Ordered
orderedPostProcessorNames.add(ppName);
}
else {
// 普通的
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
// 对实现priorityOrdered接口的BeanFactoryPostProcessor进行排序
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
// 对实现priorityOrdered接口的BeanFactoryPostProcessor执行PostProcessorBeanFactory方法
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
// 创建实现 ordered 接口的 BeanFactoryPostProcessor 实现类集合
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
for (String postProcessorName : orderedPostProcessorNames) {
// 获取名字对应的bean实例,添加到orderedPostProcessors中
// beanFactory.getBean中会进行相关相关bean的实例化工作
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
// 对实现ordered接口的BeanFactoryPostProcessor进行排序
sortPostProcessors(orderedPostProcessors, beanFactory);
// 对实现ordered接口的BeanFactoryPostProcessor执行PostProcessorBeanFactory方法
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// Finally, invoke all other BeanFactoryPostProcessors.
// 创建存放BeanFactoryPostProcessor的集合对象,没有实现其他接口
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
for (String postProcessorName : nonOrderedPostProcessorNames) {
// 获取名字对应的bean实例,添加到nonOrderedPostProcessors中
// beanFactory.getBean中会进行相关相关bean的实例化工作
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
// 遍历nonOrderedPostProcessors, 执行postProcessBeanFactory方法
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
// 清除元数据缓存(mergedBeanDefinitions、allBeanNamesByType、singletonBeanNamesByType),
// 因为后处理器可能已经修改了原始元数据,例如, 替换值中的占位符...
beanFactory.clearMetadataCache();
}
这个方法整体看下来非常长,但总的来说也就是围绕两个接口 BeanDefinitionRegistryPostProcessor 和 BeanFactoryPostProcessor 进行处理,其中 BeanDefinitionRegistryPostProcessor 继承了 BeanFactoryPostProcessor。
该方法一共操作了三种 Bean 对象:
处理这三种 Bean 的流程也就是执行这些 Bean 中重写的 BeanFactoryPostProcessor 相关方法,那具体的执行顺序如下:
另外,在 invokeBeanFactoryPostProcessors 方法中涉及到了两个排序接口:PriorityOrdered 和 Ordered,其中 PriorityOrdered 继承了 Ordered,并且 PriorityOrdered 的优先级要高于 Ordered 这跟 BeanDefinitionRegistryPostProcessor 继承 BeanFactoryPostProcessor 有点类似。
实现 Ordered 接口需要重写 getOrder 方法,返回一个用于排序的 order 值,order 值的范围为 Integer.MIN_VALUE ~ Integer.MAX_VALUE,order 值越小优先级越高,Integer.MIN_VALUE 拥有最高优先级,而 Integer.MAX_VALUE 则对应的拥有最低优先级。
自此,invokeBeanFactoryPostProcessors 方法的执行流程我们分析完了,但是有一个悬念我们一直没有提:后置处理器的执行流程
。
这里排除我们自己的后置处理器外,我必须要讲的一个就是 ConfigurationClassPostProcessor
后置处理器,它非常非常重要,在我源码调试阶段也只找到这一个非用户自定义的后置处理器及,系统默认的后置处理器。
下面我们就来解开这个面纱。
前面提到,Spring 启动的时候容器中只有这一个系统默认的后置处理器,那它是在何时加入到容器中的呢!这是我们的一个关注点。
其实如果是从头看我这笔记的,因该能在 10.3 节中找到答案。
接下来我们看看这个类的结构关系图:
现在能明白它为什么是后置处理器、也能明白它为什么最先执行了吧!
那分析 ConfigurationClassPostProcessor 方法的切入点在哪呢!
两个切入口,分别对应不同的方法:
那,现在就明确了,先分析 postProcessBeanDefinitionRegistry 方法执行流程。
方法源码:
org.springframework.context.annotation.ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
// 根据对应的registry对象生成hashcode值,此对象只会操作一次,如果之前处理过就抛出异常
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);
}
// 将id添加到马上要处理的registry对象放到集合中
this.registriesPostProcessed.add(registryId);
// 处理配置类的bean的定义信息,重要重要重要
processConfigBeanDefinitions(registry);
}
进入 processConfigBeanDefinitions 方法源码
org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
// 创建存放 BeanDefinitionHolder 的对象集合(配置类 Bean)
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
// 对当前registry就是DefaultListableBeanFactory,获取所有已经注册的BeanDefinition的baneName
String[] candidateNames = registry.getBeanDefinitionNames();
// 遍历,主要是筛选出我们的注解配置类
for (String beanName : candidateNames) {
// 获取指定名称的BeanDefinition对象
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);
}
}
// 判断当前BeanDefinition是否是一个配置类,并为BeanDe设置属性为Lite或者Full,此处设置值是为了后续进行调用
// 如果Configuration配置proxyBeanMethods代理为true则为full
// 如果加了@Bean,@ComponentScan,@Component,@Import,@ImportResource注解,则是指为lite
// 如果配置类被@Order注解标注,则设置BeanDefinition的order属性值
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
// 对configCandidates集合进行排序
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;
});
// Detect any custom bean name generation strategy supplied through the enclosing application context
// 判断当前类型是否是SingletonBeanRegistry类型,进行相关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类,并初始化相关参数,完成配置类的相关解析工作
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
// 创建两个不重复的集合
// 存放 BeanDefinitionHolder 数据(指定大小是为了避免扩容和内存浪费,放的是我们的配置类)
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
// 已解析的配置类集合
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
// 解析带有@Controller、@Import、@ImportResource、@ComponentScan、@ComponentScans、@Bean的BeanDefinition
parser.parse(candidates);
// 将解析完的Configuration配置类进行校验,1、配置类不能是final,2、@Bean修饰的方法必须可以重写以支持CGLIB
parser.validate();
// 获取所有的bean,包括扫描的bean对象,@Import导入的bean对象
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
// 清除掉已经解析处理过的配置类
configClasses.removeAll(alreadyParsed);
// Read the model and create bean definitions based on its content
// 判断读取器是否为空,如果为空的话,就创建完全填充好的ConfigurationClass实例的读取器
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
// 核心方法,将完全填充好的ConfigurationClass实例转化为BeanDefinition注册入IOC容器
this.reader.loadBeanDefinitions(configClasses);
// 添加到已经处理的集合中
alreadyParsed.addAll(configClasses);
candidates.clear();
// 这里判断registry.getBeanDefinitionCount() > candidateNames.length的目的是为了知道reader.loadBeanDefinitions(configClasses)这一步有没有向BeanDefinitionMap中添加新的BeanDefinition
// 实际上就是看配置类(例如AppConfig类会向BeanDefinitionMap中添加bean)
// 如果有,registry.getBeanDefinitionCount()就会大于candidateNames.length
// 这样就需要再次遍历新加入的BeanDefinition,并判断这些bean是否已经被解析过了,如果未解析,需要重新进行解析
// 这里的AppConfig类向容器中添加的bean,实际上在parser.parse()这一步已经全部被解析了
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());
}
// 如果有未解析的类,则将其添加到candidates中,这样candidates不为空,就会进入到下一次的while的循环中
for (String candidateName : newCandidateNames) {
if (!oldCandidateNames.contains(candidateName)) {
BeanDefinition bd = registry.getBeanDefinition(candidateName);
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) {
if (!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();
}
}
总结一下这个方法干了些啥:
解析配置类
,(重点)根据我的总结,我们知道了主配置类是通过 parse 方法去解析,并将解析出来的类进行转化为 Bean 定义也既这个方法:loadBeanDefinitions 。
好,下面我们的重点就移动到这两个方法。
方法源码
org.springframework.context.annotation.ConfigurationClassParser#parse
public void parse(Set<BeanDefinitionHolder> configCandidates) {
// 初始化属性
this.deferredImportSelectors = new LinkedList<>();
// 遍历配置类,分情况进行解析
for (BeanDefinitionHolder holder : configCandidates) {
// 拿到配置类对应的 bd
BeanDefinition bd = holder.getBeanDefinition();
try {
// 判断配置类的类型,更具类型进行解析
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);
}
}
// 解析 2.5 小节情况下的 Bean 导入
processDeferredImportSelectors();
}
这个方法干了两个比较重要的事情
那我们先来分析解析配置类 parse 源码
1)parse
org.springframework.context.annotation.ConfigurationClassParser#parse(org.springframework.core.type.AnnotationMetadata, java.lang.String)
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
processConfigurationClass(new ConfigurationClass(metadata, beanName));
}
org.springframework.context.annotation.ConfigurationClassParser#processConfigurationClass
protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
// 判断是否跳过解析
if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
return;
}
// 第一次进入的时候,configurationClass的size为0,existingClass肯定为null,在此处处理configuration重复import
// 如果同一个配置类被处理两次,两次都属于被import的则合并导入类,返回,如果配置类不是被导入的,则移除旧的使用新的配置类
ConfigurationClass existingClass = this.configurationClasses.get(configClass);
if (existingClass != null) {
if (configClass.isImported()) {
if (existingClass.isImported()) {
// 如果要处理的配置类configclass在已经分析处理的配置类记录中已存在,合并两者的importBy属性
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.
// 处理配置类,由于配置类可能存在父类(若父类的全类名是以java开头的,则除外),所有需要将configClass变成sourceClass去解析,然后返回sourceClass的父类。
// 如果此时父类为空,则不会进行while循环去解析,如果父类不为空,则会循环的去解析父类
// SourceClass的意义:简单的包装类,目的是为了以统一的方式去处理带有注解的类,不管这些类是如何加载的
SourceClass sourceClass = asSourceClass(configClass);
do {
// 解析各种注解(真正解析方法)
sourceClass = doProcessConfigurationClass(configClass, sourceClass);
}
while (sourceClass != null);
// 将解析的配置类存储起来,这样回到parse方法时,能取到值
this.configurationClasses.put(configClass, configClass);
}
最终进入真正干活的方法
org.springframework.context.annotation.ConfigurationClassParser#doProcessConfigurationClass
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
throws IOException {
// Recursively process any member (nested) classes first
// 递归解析配置类中的内部类,因为内部类也是一个配置类
processMemberClasses(configClass, sourceClass);
// Process any @PropertySource annotations
// 如果配置类上加了@PropertySource注解,那么就解析加载properties文件,并将属性添加到spring上下文中
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class,
org.springframework.context.annotation.PropertySource.class)) {
if (this.environment instanceof ConfigurableEnvironment) {
processPropertySource(propertySource);
}
else {
logger.warn("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
"]. Reason: Environment must implement ConfigurableEnvironment");
}
}
// Process any @ComponentScan annotations
// 处理@ComponentScan或者@ComponentScans注解,并将扫描包下的所有bean转换成填充后的ConfigurationClass
// 此处就是将自定义的bean加载到IOC容器,因为扫描到的类可能也添加了@ComponentScan和@ComponentScans注解,因此需要进行递归解析
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
// 解析@ComponentScan和@ComponentScans配置的扫描的包所包含的类
// 比如 basePackages = cn.j3code, 那么在这一步会扫描出这个包及子包下的class,然后将其解析成BeanDefinition
// (BeanDefinition可以理解为等价于BeanDefinitionHolder)
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
// 通过上一步扫描包cn.j3code,有可能扫描出来的bean中可能也添加了ComponentScan或者ComponentScans注解.
//所以这里需要循环遍历一次,进行递归(parse),继续解析,直到解析出的类上没有ComponentScan和ComponentScans
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
// 判断是否是一个配置类,并设置full或lite属性
if (ConfigurationClassUtils.checkConfigurationClassCandidate(
holder.getBeanDefinition(), this.metadataReaderFactory)) {
// 通过递归方法进行解析
parse(holder.getBeanDefinition().getBeanClassName(), holder.getBeanName());
}
}
}
}
// Process any @Import annotations
// 处理@Import注解
processImports(configClass, sourceClass, getImports(sourceClass), true);
// Process any @ImportResource annotations
// 处理@ImportResource注解,导入spring的配置文件
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方法转化为BeanMethod对象,保存再集合中
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// Process default methods on interfaces
// 处理接口的默认方法实现,从jdk8开始,接口中的方法可以有自己的默认实现,因此如果这个接口的方法加了@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;
}
总结一下这个方法干了些啥:
以上步骤,从 2 到 8 开始每一步的解析流程都非常的复杂,如果我在这里一步步的每个都进行分析真的是在写书了。所以我只分析我认为常见且重要的一个步骤,既第三步,其它的我看源码都不是很难,大家有时间可以点进源码看看。
分析第三步,包扫描。
入口:
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
进入源码
org.springframework.context.annotation.ComponentScanAnnotationParser#parse
public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
// 生成 bd 扫描器
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
// 下面是一系列的给扫描器赋值操作,例如设置只扫描XXX规则、排除XXX规则扫描
// ....
// 真正开始去扫描的
return scanner.doScan(StringUtils.toStringArray(basePackages));
}
doScan 源码
org.springframework.context.annotation.ClassPathBeanDefinitionScanner#doScan
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
// 创建存放扫描出来的 bd 集合
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
// 循环解析传入进来的包路径
for (String basePackage : basePackages) {
// 这个就是根据我们传入进来的包路径进行查找符合规则的 bd
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
// 遍历符合扫描规则的 bd
for (BeanDefinition candidate : candidates) {
// 给 bd 设置属性
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
// 生成 beanName
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
// 根据生成的 bd 类型执行对应的初始化方法
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
// 检查 bd 是否符合一个 Bean 的规则(这里的判断是需要的,因为扫描出来的bd只是符合扫描规则,不一定符合生成 Bean 的规则)
if (checkCandidate(beanName, candidate)) {
// 符合规则,那么进行封装,注册 bd
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
// 返回扫描出来且符合生成 Bean 规则的 bd
return beanDefinitions;
}
总结一下这个方法干了些啥:
那么很显然重点方法就在于这个 bd 是如何被找出来的,也即 findCandidateComponents 方法的执行逻辑。
废话不多说,方法源码如下
org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#findCandidateComponents
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
// componentsIndex对象包含了扫描“META-INF/spring.components”文件后封装起来的需要注册的bean的信息,在这里与来basePackage同时进行处理(spring.components 与 basePackage同时满足才会被处理),
//如果“META-INF/spring.components”文件不存在,则 componentsIndex 为 null,反之则会在 ClassPathBeanDefinitionScanner # setResourceLoader 中对其进行赋值
if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
// 判断 META-INF/spring.components 文件中配置的注册 Bean 是否符合 basePackage 的包路径,符合则注入
return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
}
else {
// 根据包路径扫描
return scanCandidateComponents(basePackage);
}
}
如果我们不配置如下文件,则默认会走 scanCandidateComponents 方法。
好了,理清楚这个分支走向之后,进入我们的 scanCandidateComponents 方法源码
org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#scanCandidateComponents
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
// 初始化一个符合扫描规则的 bd 存放集合
Set<BeanDefinition> candidates = new LinkedHashSet<>();
try {
// 拼接, 加上了 "classpath*:" 前缀和 "**/*.class" 后缀, 大致可以理解为仅扫描当前类路径下的,且为当前包及其子包下的 class 文件
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + '/' + this.resourcePattern;
// 获取到所有 class 文件
Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
boolean traceEnabled = logger.isTraceEnabled();
boolean debugEnabled = logger.isDebugEnabled();
// 遍历 class
for (Resource resource : resources) {
if (traceEnabled) {
logger.trace("Scanning " + resource);
}
if (resource.isReadable()) {
try {
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
// 是否满足条件,这里是 Filter 筛选,这里是循环两个扫描规则,第一个是排除规则集合、一个是扫描规则集合
if (isCandidateComponent(metadataReader)) {
// 创建一个 bd,类型为 ScannedGenericBeanDefinition
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
// 设置相关属性
sbd.setResource(resource);
sbd.setSource(resource);
// 再次判断这个类是否符合条件(不是内部类并且是一个具体类)
// 具体类:不是接口也不是抽象类,如果是抽象类则需要带有 @Lookup 注解
if (isCandidateComponent(sbd)) {
if (debugEnabled) {
logger.debug("Identified candidate component class: " + resource);
}
// 符合要求,将 bd 放入集合
candidates.add(sbd);
}
else {
if (debugEnabled) {
logger.debug("Ignored because not a concrete top-level class: " + resource);
}
}
}
else {
if (traceEnabled) {
logger.trace("Ignored because not matching any filter: " + resource);
}
}
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to read candidate component class: " + resource, ex);
}
}
else {
if (traceEnabled) {
logger.trace("Ignored because not readable: " + resource);
}
}
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
}
// 返回扫描获得的 bd 集合
return candidates;
}
总结一下这个方法干了些啥:
好了,根据包路径扫描符合要求的 Bean 并封装成 Bean 定义注册进 BeanFactory 的容器中的实现流程我们已经分析完成了,也意味着我们的 parse 方法分析告一段落了。
2)processDeferredImportSelectors
这个方法是处理 DeferredImportSelector 的导入规则,既延迟导入。
先来看他的类继承图:
该图很清楚的让我们知道 DeferredImportSelector 是 ImportSelector 的子类,表示延迟处理自定义的 Bean 导入规则。
使用案例:
1,创建自定义类,实现 DeferredImportSelector 接口
public class MyDeferredImportSelector implements DeferredImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
// 将 Bean 的全限定类名传进入
return new String[]{"cn.j3code.studyspring.service.UserDServiceImpl"};
}
}
2,修改配置类
@ComponentScan(value = "cn.j3code.studyspring.life")
@Import(value = {MyDeferredImportSelector.class})
@Configuration
public class LifeConfiguration {}
那么此时,程序运行的时候就会来到 processDeferredImportSelectors 方法进行处理 MyDeferredImportSelector 类。
ok,进入 processDeferredImportSelectors 方法源码
org.springframework.context.annotation.ConfigurationClassParser#processDeferredImportSelectors
private void processDeferredImportSelectors() {
// 获取 deferredImportSelectors 属性值
List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
this.deferredImportSelectors = null;
if (deferredImports == null) {
return;
}
// 排序
Collections.sort(deferredImports, DEFERRED_IMPORT_COMPARATOR);
// 遍历 deferredImports 中导入的 DeferredImportSelector 类型
for (DeferredImportSelectorHolder deferredImport : deferredImports) {
// 获取到配置类
ConfigurationClass configClass = deferredImport.getConfigurationClass();
try {
// 调用配置类中的 selectImports 方法获取注入的值(全限定类名数组)
String[] imports = deferredImport.getImportSelector().selectImports(configClass.getMetadata());
// 执行 processImports 方法进行解析注册
processImports(configClass, asSourceClass(configClass), asSourceClasses(imports), false);
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to process import candidates for configuration class [" +
configClass.getMetadata().getClassName() + "]", ex);
}
}
}
总结一下这个方法干了些啥:
方法的逻辑不是很难,在上面的总结处已经说的很明白了。那现在还有一个疑问就是 this.deferredImportSelectors 的值是如何放进去的,也即 MyDeferredImportSelector 类如何添加到 deferredImportSelectors 属性中的。
那这就不得不看 parse 中解析 Imports 注解的这个方法了,源码如下:
org.springframework.context.annotation.ConfigurationClassParser#processImports
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, boolean checkForCircularImports) throws IOException {
// ...
// 遍历 Imports 导入的所有类
for (SourceClass candidate : importCandidates) {
// ...
// 判断导入的类是否是 DeferredImportSelector 类型,如果是那么则不进行解析,而是放入 deferredImportSelectors 属性集合中,交给 processDeferredImportSelectors 方法进行解析
if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {
this.deferredImportSelectors.add(
new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector));
}
// ...
}
// ...
}
方法代码很多,我省略了与我们要的答案无关的代码,只留下了向 this.deferredImportSelectors 属性中添加值的代码。
可以看出在解析 Imports 注解时,判断 Imports 中的 class ,如果是实现了 DeferredImportSelector 接口那么就放入 deferredImportSelectors 属性集合中,这就是我们要的答案。
好了 processDeferredImportSelectors 这个方法也给大家分析完了。
上面的 parse 解析逻辑只是将我们的主配置类进行了解析,并且除了包扫描出来的 class 封装成了 Bean 定义注册进了 BeanFacotry 中外,其它像 Import 、@Bean 形式的注入 Bean 还没有对其进行封装 Bean 定义,其还只是一个元数据的状态,所以 loadBeanDefinitions 方法,就是加载这些,将其变为 Bean 定义并且注入到 BeanFactory 中的一个逻辑。
那还记得这个入口代码在哪里嘛,如下:
this.reader.loadBeanDefinitions(configClasses);
进入方法
org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitions
public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
// 循环遍历加载的配置类
for (ConfigurationClass configClass : configurationModel) {
// 针对每个配置类加载出来的数据,进行挨个加载
loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
}
}
在进入 loadBeanDefinitionsForConfigurationClass 方法
org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForConfigurationClass
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()) {
// 封装该配置类为 Bean 定义注册进 BeanFactory
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
// 获取该类的所有 @Bean 注解标注的方法信息
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
// 将 @Bean 标注的方法封装为 Bean 定义进行注入
loadBeanDefinitionsForBeanMethod(beanMethod);
}
// 获取配置类上通过 @ImportedResources 注解导入的 xml 配置类,并开始解析 xml 配置类进行注册 Bean 定义
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
// 获取配置类上通过 @Import 注解导入的 ImportBeanDefinitionRegistrar 类型的类,执行其导入 Bean 的方法进行 Bean 定义的注册
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
总结一下这个方法干了些啥:
经过以上的源码分析,配置类的解析终于是告一段落了,其将所有人为配置的 Bean 相关的信息全部都加载封装进了 BeanFactory 中的 beanDefinitionMap 属性中。
画图高手为了能让大家更清楚的了解这个方法的各个执行流程,所以画了下面的流程图供大家参考。
好了,今天的内容到这里就结束了,我是 【J3】关注我,我们下期见
。
由于博主才疏学浅,难免会有纰漏,假如你发现了错误或偏见的地方,还望留言给我指出来,我会对其加以修正。
如果你觉得文章还不错,你的转发、分享、点赞、留言就是对我最大的鼓励。
感谢您的阅读,十分欢迎并感谢您的关注。