spring5之容器始末源碼賞析 (一)總覽

     首先,本系列並非以介紹spring5 的新特性爲主,之因此以spring5爲標題,是由於即將賞析的源碼來自最新的spring版本.雖然說是spring最新版本,可是容器的整個生命週期與以前版本相比,並無很大的變化,咱們主要來看spring是如何一步步構建本身的容器,一步步將混亂不堪,錯綜複雜的依賴關係管理的層次分明,一步步組建本身的spring帝國.web

    由於篇幅緣由,並不能在一篇博客中將全部spring容器的內容都介紹完成,所以,將分爲幾個部分分別介紹,本篇會先從最頂層瀏覽一下spring的一些容器,以及spring抽象出的容器的組裝過程,使咱們對spring容器有一個總體上的認知.spring

  先來介紹spring中幾個重要的接口的做用:springboot

1.BeanFactory

2.BeanDefinition

3.BeanDefinitionRegistry

4.ApplicationContext


先看BeanFactory,這個接口定義了全部beanfactory基礎功能: 根據名稱獲取bean,獲取bean的類型/別名,判斷bean是否存在等,能夠看到,全部實現了這個接口的類,都具有這個功能.

BeanDefinition,定義了容器管理的對象.這個接口是整個spring的核心.BeanDefinition能夠看作spring的領域模型,它是對全部bean統一建模的產物,涵蓋了bean的全部信息,全部註冊進spring容器的bean均會被處理成各類beanDefinition的實現
存儲起來.

BeanDefinitionRegistry定義了beanDefinition的註冊功能.實現了這個接口的類,具有了註冊beandefinition的能力,將組裝好的beandefinition註冊到容器中。


最後看ApplicationContext,這個是容器的接口,全部容器均實現了這個接口,它定義了容器的基本功能:獲取容器名,獲取父容器,獲取beanfactory,註冊bean,等等,來看一下繼承關係:

 咱們發現它繼承許多接口,這意味着實現這個接口的類,必須具有它所實現的全部類的功能,固然,這些功能正真實現的地方不會在application的實例中,這裏用到了代理模式(百度),將主要職責委託給其它實現接口的類去作,將調用者和實現者解耦,使代碼具有良好的擴展性。架構

spring的容器有多種,我把它分兩大類:應用類和web類。app

應用類中經常使用的幾個容器:函數

AnnotationConfigApplicationContext  (主要是註解驅動,spring3.0之後加入)
GenericXmlApplicationContext   (也是3.0之後加入的,能夠做爲下面兩種的替代。相對與相面兩個容器來講比較靈活,能夠靈活設置xml)
ClassPathXmlApplicationContext  (和下面的容器基本同樣,一個是類路徑加載(主要特點是能加載jar中的xml文件),一個是文件路徑加載。二者實現基本同樣,因此會有GenericXmlApplicationContext的出現)
FileSystemXmlApplicationContext
web類的經常使用容器:
基本與上面一一對應,這裏就簡單列舉一些:
AnnotationConfigWebApplicationContext
GenericWebApplicationContext
XmlWebApplicationContext

瞭解上面的基本概念之後,咱們就要開始spring容器的探索之旅了,由於考慮到web容器還要考慮servlet版本,以及web.xml的配置,相對於應用容器來講稍微複雜一些。因此此次咱們並不會以支持web容器爲例去分析。
最近,springboot比較火爆(默認配置就是使用AnnotationConfigApplicationContext容器),咱們就來看看AnnotationConfigApplicationContext這個容器,看它是如何把一個個註解都轉化爲本身認識的bean並管理起來,
併爲咱們提供各類各樣的服務。(其實幾個容器的底層實現都同樣,畢竟是同一個爸生的。。。)
先看一個簡單的栗子:

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(Level1Config.class);
context.refresh();
Level2Component l = (Level3Component) context.getBean("level2Component");
l.asd();
@Configuration
@ComponentScan("org.springframework.context.annotation.componentscan.level2")
public class Level1Config {
    @Bean
    public TestBean level1Bean() {
        return new TestBean("level1Bean");
    }
}
@Component
public class Level2Component {
    @Autowired
    SimpleComponent simpleComponent;
    public void asd(){
        simpleComponent.testq();
    }

}
@Component
public class SimpleComponent {

    public void testq(){
        System.out.println("asdf");
    }

    @Bean
    public String exampleBean() {
        return "example";
    }

}

這個栗子中,spring掃描了「org.springframework.context.annotation.componentscan.level2」包,裝載了裏面的Level2Component和SimpleComponent等,並將SimpleComponent實例化賦值給Level2Component,而後咱們就能夠經過context獲取到Level2Component的實例,並調用SimpleComponent的方法。工具

咱們看到從context的聲明到bean實例被調用,只通過了4行代碼,可謂簡單至極,但在這背後卻作了咱們想象不到的許多事。ui

在深刻源碼以前,咱們最好先從最頂層看一下它的架構,而後帶着問題去看,這樣纔能有目的性的找到答案和學到東西,廢話很少說,先看一下spring是如何裝配AnnotationConfigApplicationContext的,我的總結以下:this

準備 ——>初始化容器——>掃描裝配beanDefinition(這裏只是初步裝配)——>組裝實例化beanlua

所以,本系列也會分紅四部分和你們一塊兒來鑑賞各個流程的代碼。

這裏就先來介紹相對簡單的一步:準備。

準備階段,spring主要是爲容器初始化一些bean,將一些配置文件讀取,掃描器,beanfacotry,bean的一些默認處理工具類實例化並裝配起來,看一下構造函數:

    public AnnotationConfigApplicationContext() {
        this.reader = new AnnotatedBeanDefinitionReader(this);
        this.scanner = new ClassPathBeanDefinitionScanner(this);
    }

還有它父類的構造函數:

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

按照類初始化的順序,咱們能夠看到,這裏初始化了resourcePatternResolver,beanfactory,annotationBeanDefinitionReader,classPathBeanDefinitionScanner,這幾個類,這些類的做用分別是:資源定位解析,定義bean容器,註解類解析,類路徑資源掃描。它們的詳細實如今後續討論中依然會出現,這裏咱們只詳細關注AnnotationBeanDefinitionReader,這個類,由於這個類參與了準備階段的工做。

先看一下構造函數:

    public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        Assert.notNull(environment, "Environment must not be null");
        this.registry = registry;
        this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
        AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
    }
ConditionEvaluator是@Conditional註解的解析的實現類,這裏咱們重點看

AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);

    public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
            BeanDefinitionRegistry registry, @Nullable Object source) {

        DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
        if (beanFactory != null) {
            if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
                beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
            }
            if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
                beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
            }
        }

        Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(4);

        if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

        if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            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)) {
            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)) {
            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)) {
            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)) {
            RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
        }

        return beanDefs;
    }

在AnnotatedBeanDefinitionReader被實例化的時候spring洋洋灑灑註冊了一堆bean,這些bean將在之後咱們有新的bean加入的時候起關鍵性做用,好比改變bean的行爲,好比監聽發佈事件,好比解析一個外部定義的配置類,等等,這些bean在後面的分析中均會一一出現,這裏一樣不作全面介紹,咱們只要知道,這些bean實在這個時候就已經被spring裝載進來了。

咱們繼續往下看:

接着就是註冊咱們自定義的bean了.
public void register(Class<?>... annotatedClasses) {
        Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
        this.reader.register(annotatedClasses);
    }

在咱們register配置類的時候reader(即AnnotationBeanDefinitionReader)的register方法會被調用,進而會調用它的doRegisterBean方法,將配置類注入容器中:

<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
            @Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {

        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());
        String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

        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);
        BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
    }

按照順序,首先咱們能夠看到,配置類會被放到AnnotatedGenericBeanDefinition中:

public AnnotatedGenericBeanDefinition(Class<?> beanClass) {
        setBeanClass(beanClass);
        this.metadata = new StandardAnnotationMetadata(beanClass, true);
    }

  annotationGenericBeanDefinition實例會持有StandardAnnotationMetadata的實例,StandardAnnotationMetadata顧名思義,它是封裝了這個類的註解的元數據。接着,spring會判斷是否符合Condition註解的條件(spring4的加進來的一個註解),接下來會解析scope註解,來肯定這個bean的做用域,接下來會調用processCommonDefinitionAnnotations方法處理一些常規的註解:@Primary,@DependsOn,@Rule.@Description,並將這些信息放入定義好的beanDefinition中,接着經過BeanDefinitionReaderUtils將beanDefinition註冊到容器裏。至此算是容器中的第一個咱們本身的bean就註冊完成。

  咱們看到,register方法實際上就是將配置類中一些咱們不長用註解信息解析並放入beandefinition中,將註解元數據放入StandardAnnotationMetadata中,由beanDefinition持有,最終把beanDefinition放入容器中(beanFactory),並無發生什麼不得了的事情,咱們定義的註解類也只是初步解析,並無進行掃描或者注入其它bean,事實上,在bean的準備階段,spring確實沒作多少事情,而是將一些十分重要的bean一一初始化進容器中,而咱們自定義的配置類就是其中之一。

 

好了,第一階段就到這裏。第一階段準備階段,spring實例化了一個reader,並在實例化過程當中裝載了annotationConfigApplicationContext容器特有的bean的處理邏輯,隨後把咱們的配置類也裝載進去變完成了準備階段的工做。

 

                                                                                                                                                    轉載請註明出處。

相關文章
相關標籤/搜索