Spring學習筆記整理(二)

入口代碼

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);
    }

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章