写在前面
本文基于springboot来进行测试,对springboot不了解或者是想要直接获取测试代码的朋友,可以参考这篇文章。
1:源码分析
1.1:入口分析
当我们执行main方法,然后调用run函数,最终会执行到代码org.springframework.context.annotation.ConfigurationClassParser#parse(java.util.Set<org.springframework.beans.factory.config.BeanDefinitionHolder>)
,该方法是用来解析java config类的,即标记有@Configuration注解的类,的我们来通过调用栈看下:
其中4
执行BeanFactoryPostProcessor的时候会调用到该方法,关于该过程详细可以参考这篇文章。parse
方法也正是我们要分析的入口了。
1.2:parse
源码位置:org.springframework.context.annotation.ConfigurationClassParser#parse(java.util.Set<org.springframework.beans.factory.config.BeanDefinitionHolder>)
,源码如下:
org.springframework.context.annotation.ConfigurationClassParser#parse(java.util.Set<org.springframework.beans.factory.config.BeanDefinitionHolder>)
public void parse(Set<BeanDefinitionHolder> configCandidates) {
for (BeanDefinitionHolder holder : configCandidates) {
// 获取bean定义
BeanDefinition bd = holder.getBeanDefinition();
try {
// <202105201137>
if (bd instanceof AnnotatedBeanDefinition) {
// <202105231114>
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
}
....snip...
}
// <202105201138>
this.deferredImportSelectorHandler.process();
}
<202105201137>
处如果是AnnotatedBeanDefinition类型,这是BeanDefinition的子接口,对外暴露了注解源信息,源码如下:
org.springframework.beans.factory.annotation.AnnotatedBeanDefinition
// 扩展BeanDefinition接口,在不需要加载class类的前提下,暴漏关于bean对应class的AnnotationMetadata
public interface AnnotatedBeanDefinition extends BeanDefinition {
// 返回bean定义对应的注解元信息对象
AnnotationMetadata getMetadata();
// 如果是有工厂方法的话,返回工厂方法的注解元信息对象
@Nullable
MethodMetadata getFactoryMethodMetadata();
}
<202105231114>
处源码如下:
org.springframework.context.annotation.ConfigurationClassParser#parse(org.springframework.core.type.AnnotationMetadata, java.lang.String)
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
// <202105231117>
processConfigurationClass(new ConfigurationClass(metadata, beanName));
}
<202105231117>
处源码如下:
org.springframework.context.annotation.ConfigurationClassParser#processConfigurationClass
protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
...snip...
// 这里通过do..while循环来依次处理每个bean的相关注解
do {
// <202105231122>
sourceClass = doProcessConfigurationClass(configClass, sourceClass);
} while (sourceClass != null);
...snip...
}
<202105231122>(重点!!!)
处源码如下:
org.springframework.context.annotation.ConfigurationClassParser#doProcessConfigurationClass
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
throws IOException {
// 如果是标注了@Component注解
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
processMemberClasses(configClass, sourceClass);
}
// 处理@PropertySource注解
// 关于PropertySource可以参考:https://blog.csdn.net/wang0907/article/details/117037183
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class,
org.springframework.context.annotation.PropertySource.class)) {
if (this.environment instanceof ConfigurableEnvironment) {
processPropertySource(propertySource);
}
else {
logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
"]. Reason: Environment must implement ConfigurableEnvironment");
}
}
// 处理@ComponentScan注解
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) {
// 通过当前的componentscan的信息,扫描对应的类生成bean定义
// 最终成为spring bean
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
// 递归处理有@Configuration注解的bean定义
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
// <202105251519>
// 处理@Import注解
// 关于@Import注解可以参考:https://blog.csdn.net/wang0907/article/details/113131549#t7
processImports(configClass, sourceClass, getImports(sourceClass), true);
// 处理@ImportResource注解
// 关于@ImportResource注解,可以参考:https://blog.csdn.net/wang0907/article/details/117037183
// 一般在启动类上我们不会使用@ImportResource注解,所以这里一般为null
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);
}
}
// <202105251442>
// 处理类中方法的@Bean注解
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
processInterfaces(configClass, sourceClass);
// 递归处理@Configuration注解所在类的父类,返回值会在外层的do...while循环中被处理
if (sourceClass.getMetadata().hasSuperClass()) {
String superclass = sourceClass.getMetadata().getSuperClassName();
if (superclass != null && !superclass.startsWith("java") &&
!this.knownSuperclasses.containsKey(superclass)) {
this.knownSuperclasses.put(superclass, configClass);
return sourceClass.getSuperClass();
}
}
// 如果是执行到这里,则外层的do...while循环也就结束了
return null;
}
<202105251442>
处是处理标记有@Bean注解的方法,比如在启动类配置如下:
@SpringBootApplication
public class HelloWorldMainApplication {
public static void main(String[] args) throws URISyntaxException, IOException {
ConfigurableApplicationContext run = SpringApplication.run(HelloWorldMainApplication.class, args);
MyPropertySourceBean bean = run.getBean(MyPropertySourceBean.class);
System.out.println(bean);
}
@Bean
public Object obj1() {
return new Object();
}
@Bean
public Object obj2() {
return new Object();
}
}
则此处运行结果就如下图,获取的是obj1
和obj2
这两个方法的信息:
<202105251519>
处会处理ImportSelector,具体参考1.3:processImports
。<202105201138>
处用于处理DeferredImportSelector,具体参考1.4:deferredImportSelectorHandler_process
。
1.3:processImports
源码:
org.springframework.context.annotation.ConfigurationClassParser#processImports
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, boolean checkForCircularImports) {
// <202105251535>
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) {
// 如果是ImportSelector
if (candidate.isAssignable(ImportSelector.class)) {
Class<?> candidateClass = candidate.loadClass();
// 创建ImportSelector类实例
ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
// 回调相关aware
ParserStrategyUtils.invokeAwareMethods(
selector, this.environment, this.resourceLoader, this.registry);
// 如果是也实现了DeferredImportSelector,注意这里就不执行else了,即不执行ImportSelector的selectImports方法
if (selector instanceof DeferredImportSelector) {
// <202105251610>
// 处理DeferedImportSelector逻辑
this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
}
else {
// 通过执行ImportSelector接口的selectImports方法,获取要import的类名称数组,重要!!!
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
processImports(configClass, currentSourceClass, importSourceClasses, false);
}
}
// 如果是ImportBeanDefinitionRegistrar,用于注册bean定义
else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
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 {
this.importStack.registerImport(
currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
processConfigurationClass(candidate.asConfigClass(configClass));
}
}
}
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();
}
}
}
<202105251535>
处的值来源于@Import注解信息的值,来源如下图:
标记1和2的就是结果
。
最终结果值如下图:
<202105251610>
处理在实现了ImportSelector接口时,也实现了DeferredImportSelector接口的情况,源码如下:
org.springframework.context.annotation.ConfigurationClassParser.DeferredImportSelectorHandler#handle
public void handle(ConfigurationClass configClass, DeferredImportSelector importSelector) {
DeferredImportSelectorHolder holder = new DeferredImportSelectorHolder(configClass, importSelector);
if (this.deferredImportSelectors == null) {
DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
handler.register(holder);
// 执行相关的import的工作
handler.processGroupImports();
}
else {
// 添加到集合中,统一处理,详细参考“1.4:deferredImportSelectorHandler_process”
this.deferredImportSelectors.add(holder);
}
}
1.4:deferredImportSelectorHandler_process
重要!!!
,用来引入springboot在META-INF/spring.factories文件中配置的自动配置类。
源码如下:
org.springframework.context.annotation.ConfigurationClassParser.DeferredImportSelectorHandler#process
public void process() {
// <202105251650>
List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
this.deferredImportSelectors = null;
try {
if (deferredImports != null) {
DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
deferredImports.sort(DEFERRED_IMPORT_COMPARATOR);
deferredImports.forEach(handler::register);
// <202105251708>
handler.processGroupImports();
}
}
finally {
this.deferredImportSelectors = new ArrayList<>();
}
}
<202105251650>
默认只有一个即AutoConfigurationImportSelector
类,如下图:
<202105251708>
处是执行具体的引入,源码如下:
org.springframework.context.annotation.ConfigurationClassParser.DeferredImportSelectorGroupingHandler#processGroupImports
public void processGroupImports() {
// 循环所有,依次处理
for (DeferredImportSelectorGrouping grouping : this.groupings.values()) {
// grouping.getImports()处就是获取所有的自动配置类,然后在依次递归处理import信息
grouping.getImports().forEach(entry -> {
ConfigurationClass configurationClass = this.configurationClasses.get(entry.getMetadata());
try {
processImports(configurationClass, asSourceClass(configurationClass),
asSourceClasses(entry.getImportClassName()), false);
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to process import candidates for configuration class [" +
configurationClass.getMetadata().getClassName() + "]", ex);
}
});
}
}