入口代碼:
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(Config.class);
執行了AnnotationConfigApplicationContext中的一個構造函數
找到第一行代碼 看AnnotationConfigApplicationContext的空參構造
創建一個AnnotatedBeanDefinitionReader
創建一個ClassPathBeanDefinitionScanner
AnnotatedBeanDefinitionReader是什麼?
這個類的主要作用就是註冊BeanDefinition,與之相類似的功能的類還有一個就是ClassPathBeanDefinitionScanner。它們最大的不同在於AnnotatedBeanDefinitionReader支持註冊單個的BeanDefinition,而ClassPathBeanDefinitionScanner會一次註冊所有掃描到的BeanDefinition。
AnnotatedBeanDefinitionReader源碼解析
// 這裏只保留了這個類中的部分代碼,其餘不重要我都沒有放出來
public class AnnotatedBeanDefinitionReader {
// 上面我們已經說了,這個reader對象主要的工作就是註冊BeanDefinition,那麼將BeanDefinition註冊到哪裏去呢?所以它內部就保存了一個BeanDefinition的註冊表。對應的就是我們代碼中的AnnotationConfigApplicationContext
private final BeanDefinitionRegistry registry;
// 見名知意,Bean名稱的生成器,生成BeanName
private BeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator();
// 解析@Scope註解
private ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();
// 解析@Conditional註解
private ConditionEvaluator conditionEvaluator;
// 將解析指定的類成爲BeanDefinition並註冊到容器中
public void registerBean(Class<?> annotatedClass, String name, Class<? extends Annotation>... qualifiers) {
doRegisterBean(annotatedClass, null, name, qualifiers);
}
// 真正的執行註冊的方法
<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
// Spring在這裏寫死了,直接new了一個AnnotatedGenericBeanDefinition,也就是說通過reader對象註冊的BeanDefinition都是AnnotatedGenericBeanDefinition。
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
// 調用conditionEvaluator的shouldSkip方法
// 判斷當前的這個bd是否需要被註冊
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
// 在註冊時可以提供一個instanceSupplier
abd.setInstanceSupplier(instanceSupplier);
// 解析@Scope註解,得到一個ScopeMetadata
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
// 將@Scope註解中的信息保存到bd中
abd.setScope(scopeMetadata.getScopeName());
// 調用beanNameGenerator生成beanName
// 所謂的註冊bd就是指定將bd放入到容器中的一個beanDefinitionMap中
// 其中的key就是beanName,value就是解析class後得到的bd
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
// 這句代碼將進一步解析class上的註解信息,Spring在創建這個abd的信息時候就已經將當前的class放入其中了,所有這行代碼主要做的就是通過class對象獲取到上面的註解(包括@Lazy,@Primary,@DependsOn註解等等),然後將得到註解中對應的配置信息並放入到bd中的屬性中
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
// 下面的這段不用過多關注,爲了文章的完整性我這裏還是說說我的理解
// 正常的容器啓動階段qualifiers肯定等於null
// 我能想到的不爲空的方法就是直接在外部調用了register方法並且出入了qualifiers參數
// 就是說我們手動直接註冊了一個類,但是我們沒有在類上添加@Lazy,@Primary註解,但是我們又希望能將其標記爲Primary爲true/LazyInit爲true,這個時候就手動傳入Primary.class跟Lazy.class即可。
if (qualifiers != null) {
for (Class<? extends Annotation> qualifier : qualifiers) {
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
}
else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
// 我們註冊時,我們可以傳入一些回調方法,在解析得到bd後調用
for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
customizer.customize(abd);
}
// bd中是沒有beanName屬性的,BeanDefinitionHolder中就是保存了beanName以及對應的BeanDefinition
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
// 這個地方主要是解析Scope中的ProxyMode屬性,默認爲no,不生成代理對象
// 後文做詳細分析
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
// 註冊bd到容器中,實際上最終就是將bd放到了beanFactory中的一個map裏(beanDefinitionMap)
// key爲beanName,value爲bd
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
}