1. 程式人生 > >Spring 原始碼閱讀 一

Spring 原始碼閱讀 一

終於,有一天我也來看Spring的原始碼了,看了一陣之後感覺心情那叫一個舒暢,對Spring底層的實現也有了進一步的瞭解, 最直觀的感受就是Spring的命名風格很贊,很長,真的長到使人見名知意, 閒言少敘,開始整理筆記了

程式的入口

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);

跟進這個AnnotationConfigApplicationContext()程式的啟動入口, 註解配置的應用上下文.主要做了下面的三件事

  • 呼叫本類無參構造方法
  • 呼叫register(annotatedClasses) 將我們傳遞進來的配置類註冊進BeanFactoryBeanDefinitionMap
  • 重新整理容器
    public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
        this();
        register(annotatedClasses);
        refresh();
    }

建立BeanFactory

首先呼叫本類的無參構造方法,,通過上圖,可以看到,AnnotationConfigAllicationContext

的父類是GenericApplicationContext但是,在執行本類的無參構造方法時會先執行父類的無參構造方法.它父類的無參構造方法我貼在下面,就做了一件事,初始化了Spring的BeanFactory,沒錯就是Spring的Bean工廠,由於兩者的繼承關係,我們就任務,AnnotationConfigApplicationContext的Bean工廠被初始化了

    public GenericApplicationContext() {
        this.beanFactory = new DefaultListableBeanFactory();
    }

建立AnnotatedBeanDefinitionReader
載入

接著回到這個構造方法的原始碼我貼在下面, 這個構造方法主要做了兩件事

  • 為應用的上下文建立reader讀取器, 讀取被添加了註解的類資訊
  • 例項化了一個Scanner, 這個Scanner可以用去做包掃描的工作,但是Spring根據我們的配置資訊去進行包掃描的工作時,並沒有使用這個掃描器,而是自己new 了一個,當前的掃描器可以理解成是方便程式設計師使用而建立的
    public AnnotationConfigApplicationContext() {
        this.reader = new AnnotatedBeanDefinitionReader(this); 
        this.scanner = new ClassPathBeanDefinitionScanner(this);
    }

下面跟進AnnotatedBeanDefinitionReader掃描器的建立過程,經過幾個沒有重要邏輯的方法,我們會進入registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source),下面是原始碼: 這算是Spring初始化的一個小高潮了!!!,為啥這樣說呢? 因下面的邏輯中,為Spring初始化過程中,構建BeanFactory提供了幾個開天闢地性質的RootBeanDefinition``

  • 首先是在為BeanFactory添加了兩個大元件
    • AnnotationAwareOrderComparator用於解析@Order@Priorty註解
    • ContextAnnotationAutowireCandidateResolver 提供了懶載入的支援
  • 然後就是往BeanFactory中的BeanDefinitionMap中添加了6個RootBeanDefinition
    • ConfigurationClassPostProcessor
    • AutowiredAnnotationBeanPostProcessor
    • ...
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
        BeanDefinitionRegistry registry, @Nullable Object source) {

    //   得到bean工廠
    DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
    if (beanFactory != null) {
        if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
            //  給Bean工廠新增原材料
            //  AnnotationAwareOrderComparator 主要能解析@Order註解和@Priority
            beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
        }
        if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
            //  ContextAnnotationAutowireCandidateResolver 提供處理懶載入(Lazy)相關的功能
            beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
        }
    }
    //   作用是方便傳遞引數BeanDefinitionHolder
    Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
    // BeanDefinition的註冊,這裡很重要,需要理解註冊每個bean的型別
    //   就是判斷工廠中有沒有包含 CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME 名稱的bean, Spring在啟動時,工廠肯定是空的返回false , 加上! 表示ture
    if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {//configuration_annotation_processor_bean_name
        //   注意: 下面的ConfigurationClassPostProcessor實現了BeanDefinitionRegistryPostProcessor,間接實現了 BeanFactoryPostProcessor bean工廠的後置處理器
        //   RootBeanDefinition可以理解成 描述Spring內部類的Definition

        //   除了通過AnnotationedBeanDefinitionReader把 加上了註解的類載入成bean,下面的第二種方式, 通過new RootBeanDefinition, 進而將 XXX.class起來註冊進bean工廠
        //   這是使用第二種方式, 通過new Spring自己實現的BeanDefinition介面的類,將java轉換成 Bean 然後put進BeanFactory的BeanDefinitionMap中
        //   下面的111-666 就是最先放置進去的6個Spring的RootBean物件
        //   ---111---------------------------
        RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
        def.setSource(source);
        //   跟進去 registerPostProcessor
        beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        //AutowiredAnnotationBeanPostProcessor 實現了 MergedBeanDefinitionPostProcessor
        //MergedBeanDefinitionPostProcessor 最終實現了 BeanPostProcessor
        //   ---222---------------------------
        RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        //   ---333---------------------------
        RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
    if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {

        //   ---444---------------------------
        RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
    if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition();
        try {
            def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
                    AnnotationConfigUtils.class.getClassLoader()));
        }
        catch (ClassNotFoundException ex) {
            throw new IllegalStateException(
                    "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
        }
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
        //   ---555---------------------------

        RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
    }

    if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
        //   ---666---------------------------
        RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
    }

    return beanDefs;
}

上面的程式碼中有來如下兩個亮點:

亮點1:RootBeanDefinition

首先涉及到的知識點就是,Spring有哪幾種方式將物件轉成BeanDefinition? 其實是有兩種,第一種就是讓Spring通過Scanner去掃描包解析程式設計師提供的添加了註解的類,這是個自動完成的過程,第二種就是Spring通過new RootBeanDefinition等諸多的BeanDefinition介面的實現類, 然後將Spring原生的物件當成引數傳遞進去進而轉換成BeanDefinition, 當然,Spring在這裡選擇的就是第二種方法

亮點2:ConfigurationClassPostProcessor

這個類很牛,為什麼這麼說呢? 先看一下他的繼承類圖

沒錯,他是6個RootBeanDefinition中唯一的一個實現BeanFactoryPostProcessor的,其他的五個RootBeanDifinition實現的都是BeanPostProcessor, 其實也不用懵逼,只要我們整明白這裡說的BeanPostProcessorBeanFactoryPostProcessor的作用就好了,然後在這裡我用下面的兩個模組解釋

BeanPostProcessor

介面的抽象方法原始碼如下:

public interface BeanPostProcessor {

@Nullable
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
@Nullable
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

兩個方法名,見名知意: 第一個會在 物件的 constructor 之後,init()方法之前呼叫

第二個會在init()方法之後呼叫

但是,大家可以發現,它的呼叫時機都是在構造方法執行之後進行攔截,這時候BeanDefinition已經被例項化了

BeanFactoryPostProcessor

@FunctionalInterface
public interface BeanFactoryPostProcessor {

    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}

它就比較厲害了, 這也是Spring牛的地方,它不僅僅會替我們維護這些Bean,而且還通過當前的BeanFactoryPostProcessor,為程式設計師開放一個缺口,讓程式設計師可以參與到Bean的建立過程中來,為什麼這樣說呢, 其實大家可以看到,它唯一的抽象方法中的入參位置上是誰? 沒錯,就是BeanFactory, Bean工廠都給我們了,那不是想幹啥幹啥?

其次,它的作用時機是執行Bean的構造方法之前

最直接的應用場景: 當一個單例的Bean依賴 多例的Bean時,我們多次通過 應用的上下文獲取出來的單例bean的hashcode都是唯一的這沒錯,但是緊接著列印它依賴的多例物件的hashcode同樣是相同的,這種單例失效的問題,就可以根據這個知識點從容解決

前面說的ConfigurationClassPostProcessor就是BeanFactoryPostProcessor的實現類,並且它也不辱使命, 完美的使用作用時機不同的特點,在程式設計師提供的配置類的構造方法呼叫之前,就先入為主,圍棋生成了 cglib代理物件


接著看程式碼,回到上面的程式碼,我們看如何將RootBeanDefinition註冊進BeanFactory, 我從上面擷取一行程式碼放在這裡

    //   跟進去 registerPostProcessor
        beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));

跟進這個registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)

private static BeanDefinitionHolder registerPostProcessor(
        BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {

    definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    //   registerBeanDefinition()
    registry.registerBeanDefinition(beanName, definition);
    return new BeanDefinitionHolder(definition, beanName);
}

我們關注這個registry.registerBeanDefinition(beanName, definition); , 可以看到,其實這個registerBeanDefinition()BeanDefinitionRegistry的抽象方法,我們要找的是它的實現類,那問題來了, 是誰實現他呢? 可以回到部落格頂部,看看第一個圖,沒錯Spring的BeanFactory,也就是DefualtListableBeanFactory實現了這個介面,雖然有點意外,一個工廠竟然還是一個註冊器,但是這也是事實情況, 看看這個工廠是如何做的吧 .原函式很長,我截取了部分原始碼如下: 它的解釋我寫在原始碼的下面

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
            throws BeanDefinitionStoreException {
            ...
            else {
                //   新增進入容器中, 最終的結果就是,這個map中存在哪些類,Spring的IOC中就有哪些類
                // Still in startup registration phase
                this.beanDefinitionMap.put(beanName, beanDefinition);
                //   單獨使用一個list存放名字
                this.beanDefinitionNames.add(beanName);

                this.manualSingletonNames.remove(beanName);
            }
            this.frozenBeanDefinitionNames = null;
        }

        if (existingDefinition != null || containsSingleton(beanName)) {
            resetBeanDefinition(beanName);
        }

可以看到,他將一開始的6個RootBeanDefinition全都都put進了一個map中, 下面這個map

private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

key就是beanName, value就是BeanDefinition

這也是迄今為止我們遇到的第一個map, 這個map是BeanFactory的一個元件,但是它可不是傳說中的IOC容器,大家也看到了它裡面存放的是BeanDefinition,而不是Bean

將配置類註冊進BeanFactory

回到一開始AnnotationConfigApplicationContextregister(annotatedClasses);方法,然後一路往下跟,會經過幾個沒有什麼重要邏輯的方法, 然後來到這裡

public void register(Class<?>... annotatedClasses) {
    for (Class<?> annotatedClass : annotatedClasses) {
        //  繼續跟進去
        registerBean(annotatedClass);
    }
}

通過上面的程式碼,我們可以回想,annotatedClasses這個可變長度的引數,其實就是我們在AnnotationConfigApplicationContext中傳遞進來的主配置類MainConfig, 也就是說,這個主配置類是可以存在多個的

接著往下跟

<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
            @Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
        // 可以將當前類理解成一個方便引數傳遞的封裝類
        // 意為: 被加上註解的通用的BD
        // 將傳遞進來的 主配置類封裝進 這個AnnotatedGenericBeanDefinition
        AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);

        if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
            return;
        }

        abd.setInstanceSupplier(instanceSupplier);

        // 解析出它的元資料
        ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
        // 設定它的作用域
        abd.setScope(scopeMetadata.getScopeName());
        // 名稱生成器, 目的是為BeanDefinition取個名字,因為這個BD最終被存放到一個map中,
        // 預設情況下@Configuration(value = "XXX") 這個value有值,就是使用這個當成名字
        // 都這就使用 類名首字母小寫當成名字
        String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

        // 處理bean上的通用註解, @Lazy  @Dependon @Primary role等
        AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);

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

        for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
            customizer.customize(abd);
        }
        // 理解成方便引數傳遞的封裝類
        BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd,beanName);
  
        definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
        // 我們關注的重點, 註冊BeanDefinition
        BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
    }

上面的函式的主要作用如下: 將我們通過AnnotationConfigApplicationContext建構函式傳遞進來的主配置類封裝進了AnnotatedGenericBeanDefinition中,然後解析它身上的其他註解完成屬性的賦值

接著跟進registerBeanDefinition()方法

    public static void registerBeanDefinition(
            BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
            throws BeanDefinitionStoreException {

        //   再來這個方法之前封裝了一個 difinitionHolder , 然後在這裡又把它拆分開傳遞給了下面的函式
        // Register bean definition under primary name.
        String beanName = definitionHolder.getBeanName();
        //   在當前的BeanDefinitionReaderUtils中使用
        registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

        // Register aliases for bean name, if any.
        String[] aliases = definitionHolder.getAliases();
        if (aliases != null) {
            for (String alias : aliases) {
                registry.registerAlias(beanName, alias);
            }
        }
    }

繼續跟進

    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

於是有回到了上面註冊6大RootBeanDefinition的邏輯中,將我們的主配置類註冊進BeanFactoryBeanDefinitionMap

未完待續