spring源碼學習(一)

因爲本人水平有限,本文內容較爲簡單,僅供我的學習筆記,或者你們參考,若是可以幫助你們,榮幸之至!本文主要分析AnnotationConfigApplicationContext實例化以後,到底幹了那些事情。程序員

  • 首先經過實例化applicationContext

  

AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(Appconfig.class);

AnnotationConfigApplicationContext.getBean("beanName");

 

分析:第一句實例化annotationConfigApplicationContext,初始化了spring的環境,第二句就能夠從spring ioc容器中獲取bean。spring

  • 接下來查看構造方法
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
        this();
        register(annotatedClasses);
        refresh();
    }

 

  • 分析:this()方法會先調用父類的構造函數,再調用當前類的默認構造方法,在父類的構造方法當中,實例化了DefaultListableBeanFactory對象,spring當中的默認工廠, 在當前類的構造函數當中實例化了一個reader和scanner。
public GenericApplicationContext() {
        this.beanFactory = new DefaultListableBeanFactory();
    }
  • 這裏的beanFactory很重要,後續實例化beanDefinition、beanName都存儲在這裏。
        this.reader = new AnnotatedBeanDefinitionReader(this);
        this.scanner = new ClassPathBeanDefinitionScanner(this);
  •  reader用來讀取被加了註解的beanDenition,以及在當前的構造函數當中,會實例化spring當中很是重要的五個beanPostProcessor(後續分析),以及一個beanFactory,在本文最後會對其分析。
  • scanner顧名思義是用來掃描的,只不過是提供外部程序員來調用的,spring內部並無使用到。
public void register(Class<?>... annotatedClasses) {
        Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
        this.reader.register(annotatedClasses);
    }
  • 這裏的register方法就是調用了咱們在構造函數當中初始化的reader,來完成註冊beanDenifition。這裏註冊的類參數是一個數組,經過for循環來處理。註冊一個bean以後須要調用refresh()方法,來完成實例化。若是註冊了Appconfig類的話,若是不調用refresh()方法,項目會報錯,若是註冊的是普通的bean,在經過getBean來獲取的時候,底層方法會手動調用refresh()當中的方法。接下來咱們看register()當中的方法。
<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);
    }
  • 分析:首先會判斷是否跳過解析,若是元數據爲null,或者沒有加condition註解則返回false。由於該beanDenifition是初始化new出來的,因此元數據永遠不會爲空。接下來獲取bean的做用域範圍,默認是單例,生成beanName,接下來解析類的通用註解,好比說lazy,primary,description等等註解。處理限定符註解,還有自定義註解。beanDefinitionHolder主要是爲了傳值,在註冊beanDenifition時候能夠少傳一個參數。這裏傳的這幾個參數永遠爲null,好比@Nullable Supplier<T> instanceSupplier, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers,因此不用解析,若是咱們想要解析,只能獲取到reader對象,手動調用傳參數給他。
          // Still in startup registration phase
                this.beanDefinitionMap.put(beanName, beanDefinition);
                this.beanDefinitionNames.add(beanName);
                this.manualSingletonNames.remove(beanName);
  • map當中存儲key:beanName,value:beanDefinition,beanDefinitionName集合當中存儲全部的beanDenifitionName。
                // Register aliases for bean name, if any.
        String[] aliases = definitionHolder.getAliases();
        if (aliases != null) {
            for (String alias : aliases) {
                registry.registerAlias(beanName, alias);
            }
        }
  • 源碼當中處理類的別名,spring當中若是設置了別名,能夠經過id或者別名從spring容器當中獲取類的實例。

接下來查看最後一個refresh方法,spring當中的bean生命週期,就是從這裏開始的數組

@Override
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            prepareRefresh();

            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // Prepare the bean factory for use in this context.
            prepareBeanFactory(beanFactory);

            try {
                // Allows post-processing of the bean factory in context subclasses.

                postProcessBeanFactory(beanFactory);

                // Invoke factory processors registered as beans in the context.
                invokeBeanFactoryPostProcessors(beanFactory);

                // Register bean processors that intercept bean creation.
                registerBeanPostProcessors(beanFactory);

                // Initialize message source for this context.
                initMessageSource();

                // Initialize event multicaster for this context.
                
                initApplicationEventMulticaster();

                // Initialize other special beans in specific context subclasses.
                onRefresh();

                // Check for listener beans and register them.
                registerListeners();

                // Instantiate all remaining (non-lazy-init) singletons.
                finishBeanFactoryInitialization(beanFactory);

                // Last step: publish corresponding event.
                finishRefresh();
            }

            catch (BeansException ex) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
                }

                // Destroy already created singletons to avoid dangling resources.
                destroyBeans();

                // Reset 'active' flag.
                cancelRefresh(ex);

                // Propagate exception to caller.
                throw ex;
            }

            finally {
                // Reset common introspection caches in Spring's core, since we
                // might not ever need metadata for singleton beans anymore...
                resetCommonCaches();
            }
        }
    }

分析:ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();獲取咱們的beanFactory,bean的生命週期就是從這裏開始的,prepareBeanFactory顧名思義準備beanfactory,包括設置類加載器、解析器(解析相似與el表達式的頁面語句,由spring提供的)、屬性編輯器(spring boot當中的yml配置)、這裏最重要的是添加了一個BeanPostProcessor,beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));來看這裏作了什麼事情!緩存

class ApplicationContextAwareProcessor implements BeanPostProcessor

該類繼承自BeanPostProcessor,實現了這兩個方法app

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

緩存預熱之時,咱們會使用@PostConstruct註解初始化init()方法,在構造函數以後執行,@preDestroy在銷燬以後執行。後置處理器spring提供給咱們的擴展點,這兩個方法會在init方法的先後執行,spring當中的AOP也是這樣來完成對IOC的增強的,已經把bean暴漏出來了,在這裏返回代理對象便可。接下來看ApplicationContextAwareProcessor實現後置處理器作了那些事情。編輯器

@Override
    @Nullable
    public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
        AccessControlContext acc = null;

        if (System.getSecurityManager() != null &&
                (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
                        bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
                        bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
            acc = this.applicationContext.getBeanFactory().getAccessControlContext();
        }

        if (acc != null) {
            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                invokeAwareInterfaces(bean);
                return null;
            }, acc);
        }
        else {
            invokeAwareInterfaces(bean);
        }

        return bean;
    }

    private void invokeAwareInterfaces(Object bean) {
        if (bean instanceof Aware) {
            if (bean instanceof EnvironmentAware) {

                ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
            }
            if (bean instanceof EmbeddedValueResolverAware) {
                ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
            }
            if (bean instanceof ResourceLoaderAware) {
                ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
            }
            if (bean instanceof ApplicationEventPublisherAware) {
                ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
            }
            if (bean instanceof MessageSourceAware) {
                ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
            }
            if (bean instanceof ApplicationContextAware) {
                if (!bean.getClass().getSimpleName().equals("IndexDao"))
                ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
            }
        }
    }

分析:這裏主要判斷是否實現了ApplicationContextAware接口,若是實現了,就把applicationContext注入給他。此時就能夠解釋爲何實現了applicationcontext接口,重寫set方法,就能夠獲取applicationContext,解決單例模式下獲取原型對象了。關於spring當中的其餘後置處理器,會在後續文章中更新!ide

相關文章
相關標籤/搜索