spring 系列:spring IOC之BeanDefinition解析

1. 背景

在IOC前需搞清楚Spring容器,以及為什么需要Spring容器悍缠。

通常來說,使用容器運行組件耐量,除了提供一個組件運行環(huán)境之外,容器還提供了許多底層服務(wù)滤港。例如廊蜒,Servlet容器底層實現(xiàn)了TCP連接,解析HTTP協(xié)議等非常復(fù)雜的服務(wù)溅漾,如果沒有容器來提供這些服務(wù)山叮,我們就無法編寫像Servlet這樣代碼簡單,功能強大的組件添履。早期的JavaEE服務(wù)器提供的EJB容器最重要的功能就是通過聲明式事務(wù)服務(wù)屁倔,使得EJB組件的開發(fā)人員不必自己編寫冗長的事務(wù)處理代碼,所以極大地簡化了事務(wù)處理暮胧。
Spring的核心就是提供了一個IoC容器锐借,它可以管理所有輕量級的JavaBean組件,提供的底層服務(wù)包括組件的生命周期管理往衷、配置和組裝服務(wù)钞翔、AOP支持,以及建立在AOP基礎(chǔ)上的聲明式事務(wù)服務(wù)等席舍。
參考 IoC容器

2. 使用

2.1 基于XML

bean定義:

public class FirstBean {
    public void hello() {
        System.out.println("hello world");
    }
}

XML定義:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean name="firstBean" class="com.cui.study.spring.FirstBean"/>
</beans>

類加載和使用:

public class Main {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        FirstBean firstBean = context.getBean("firstBean", FirstBean.class);
        firstBean.hello();
    }
}

2.2 基于注解的方式

bean定義:

@Component
public class FirstBean {
    public void hello() {
        System.out.println("hello world");
    }
}

類加載和使用:

@ComponentScan(value = "com.cui.study.spring")
public class Main {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        FirstBean firstBean = context.getBean("firstBean", FirstBean.class);
        firstBean.hello();
    }
}

3. 核心源碼解析

Spring 容器初始化核心流程在AbstractApplicationContext#refresh方法中(版本為spring-context-5.3.23):

public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

            // Prepare this context for refreshing.
                        // 容器初始化前準(zhǔn)備布轿,如設(shè)置容器狀態(tài)、初始化監(jiān)聽器和事件列表等
            prepareRefresh();

            // Tell the subclass to refresh the internal bean factory.
            // 核心流程:初始化容器来颤,并解析xml汰扭、注解中的BeanDefinition列表
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // Prepare the bean factory for use in this context.
            // 配置工廠類的標(biāo)準(zhǔn)化特征,如ClassLoader and post-processors.
            prepareBeanFactory(beanFactory);

            try {
                // Allows post-processing of the bean factory in context subclasses.
                // 容器初始化福铅,并加載BeanDefinition后萝毛,修改容器
                postProcessBeanFactory(beanFactory);

                StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
                // Invoke factory processors registered as beans in the context.
                // 初始化 BeanFactoryPostProcessor 擴展點(容器擴展點),并執(zhí)行
                invokeBeanFactoryPostProcessors(beanFactory);

                // Register bean processors that intercept bean creation.
                // 創(chuàng)建并注冊 BeanPostProcessor(Bean擴展點)
                registerBeanPostProcessors(beanFactory);
                beanPostProcess.end();

                // Initialize message source for this context.
                // 初始化MessageSource滑黔,用于國際化
                initMessageSource();

                // Initialize event multicaster for this context.
                // 初始化 ApplicationEventMulticaster
                initApplicationEventMulticaster();

                // Initialize other special beans in specific context subclasses.
                //子容器擴展點珊泳,初始化其他特殊的bean
                onRefresh();

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

                // Instantiate all remaining (non-lazy-init) singletons.
                // 核心流程:初始化所有剩余的非延遲初始化的單例bean
                finishBeanFactoryInitialization(beanFactory);

                // Last step: publish corresponding event.
                // 容器初始化結(jié)束,清理緩存拷沸,初始化并執(zhí)行LifecycleProcessor#onRefresh色查,發(fā)送ContextRefreshedEvent事件
                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();
                contextRefresh.end();
            }
        }
    }

4. 基于XML方式的BeanDefinition解析

基于XML的解析方式,在刷新容器時解析BeanDefinition撞芍,核心步驟主要分為以下幾個步驟:

  1. 容器刷新時解析BeanDefinition秧了;
  2. 容器委托給XmlBeanDefinitionReader解析BeanDefinition
  3. XmlBeanDefinitionReader將XML解析成Document序无,并委托給BeanDefinitionDocumentReader解析验毡;
  4. BeanDefinitionDocumentReader處理<beans>標(biāo)簽衡创,解析出來的BeanDefinitionHolder注冊到容器的beanDefinitionMap對象中。<bean>標(biāo)簽解析過程委托給BeanDefinitionParserDelegate晶通。
    4.1 BeanDefinitionParserDelegate具體解析<bean>標(biāo)簽璃氢,返回BeanDefinitionHolder

4.1 容器刷新

加載BeanDefinition的入口在AbstractRefreshableApplicationContext#loadBeanDefinitions中狮辽,具體邏輯在子類AbstractXmlApplicationContext里實現(xiàn)一也。調(diào)用鏈路如下:

loadBeanDefinitions調(diào)用鏈路

加載BeanDefinition委托給BeanDefinitionReader#loadBeanDefinitions方法,實現(xiàn)類為XmlBeanDefinitionReader喉脖。

4.2 XmlBeanDefinitionReader解析過程

加載BeanDefinition委托過程

真正注冊BeanDefinition的操作在doLoadBeanDefinitions中實現(xiàn)椰苟。

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
            throws BeanDefinitionStoreException {
// try,忽略
                // 將XML轉(zhuǎn)換成Document對象
        Document doc = doLoadDocument(inputSource, resource);
                // 注冊BeanDefinition树叽,并返回注冊BeanDefinition總數(shù)
        int count = registerBeanDefinitions(doc, resource);
        if (logger.isDebugEnabled()) {
            logger.debug("Loaded " + count + " bean definitions from " + resource);
        }
        return count;
// catch處理舆蝴,忽略
    }

registerBeanDefinitions中最后委托給BeanDefinitionDocumentReader#registerBeanDefinitions

4.3 BeanDefinitionDocumentReader解析過程

    public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
        BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
        int countBefore = getRegistry().getBeanDefinitionCount();
                // 委托給BeanDefinitionDocumentReader的registerBeanDefinitions
        documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
        return getRegistry().getBeanDefinitionCount() - countBefore;
    }

BeanDefinitionDocumentReader中的調(diào)用鏈路如下:

BeanDefinitionDocumentReader加載BeanDefinition過程

parseBeanDefinitions的實現(xiàn)細(xì)節(jié)如下:

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
        if (delegate.isDefaultNamespace(root)) {
            NodeList nl = root.getChildNodes();
            for (int i = 0; i < nl.getLength(); i++) {
                Node node = nl.item(i);
                if (node instanceof Element) {
                    Element ele = (Element) node;
                    if (delegate.isDefaultNamespace(ele)) {
                                                // Spring提供的默認(rèn)element解析题诵,包括import洁仗、alias、bean性锭、beans
                        parseDefaultElement(ele, delegate);
                    }
                    else {
                                                // 自定義element解析(http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#xml-custom)
                        delegate.parseCustomElement(ele);
                    }
                }
            }
        }
        else {
            delegate.parseCustomElement(root);
        }
    }

最終在parseDefaultElement中解析XML中定義的import京痢、aliasbeanbeans篷店。

    private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
        if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
            importBeanDefinitionResource(ele);
        }
        else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
            processAliasRegistration(ele);
        }
        else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
            processBeanDefinition(ele, delegate);
        }
        else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
            // recurse
            doRegisterBeanDefinitions(ele);
        }
    }

主要看對bean標(biāo)簽的處理祭椰,在方法processBeanDefinition中:

    protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
                // 計算BeanDefinition,委托給BeanDefinitionParserDelegate實現(xiàn)真正的解析動作
        BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
        if (bdHolder != null) {
            bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
            try {
                // Register the final decorated instance.
                // 將BeanDefinition注冊到容器的beanDefinitionMap中
                BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
            }
            catch (BeanDefinitionStoreException ex) {
                getReaderContext().error("Failed to register bean definition with name '" +
                        bdHolder.getBeanName() + "'", ele, ex);
            }
            // Send registration event.
            getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
        }
    }

4.3.1 BeanDefinitionParserDelegate 解析過程

BeanDefinitionParserDelegate中的實現(xiàn)邏輯如下:

BeanDefinitionParserDelegate調(diào)用鏈路

核心邏輯在parseBeanDefinitionElement中疲陕,解析結(jié)果為GenericBeanDefinition方淤,解析的元素可參考[Spring官方文檔]。(https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-autowired-annotation-qualifiers)

public AbstractBeanDefinition parseBeanDefinitionElement(
            Element ele, String beanName, @Nullable BeanDefinition containingBean) {

        this.parseState.push(new BeanEntry(beanName));

        String className = null;
        if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
            className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
        }
        String parent = null;
        if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
            parent = ele.getAttribute(PARENT_ATTRIBUTE);
        }

        try {
            AbstractBeanDefinition bd = createBeanDefinition(className, parent);
            // 解析bean屬性
            parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
            bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
            // 解析meta標(biāo)簽
            parseMetaElements(ele, bd);
            // 解析lookup-method標(biāo)簽
            parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
            // 解析replaced-method標(biāo)簽
            parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
            // 解析constructor-arg標(biāo)簽
            parseConstructorArgElements(ele, bd);
            // 解析property標(biāo)簽
            parsePropertyElements(ele, bd);
            // 解析qualifier標(biāo)簽
            parseQualifierElements(ele, bd);

            bd.setResource(this.readerContext.getResource());
            bd.setSource(extractSource(ele));

            return bd;
        }
        catch (ClassNotFoundException ex) {
            error("Bean class [" + className + "] not found", ele, ex);
        }
        catch (NoClassDefFoundError err) {
            error("Class that bean class [" + className + "] depends on not found", ele, err);
        }
        catch (Throwable ex) {
            error("Unexpected failure during bean definition parsing", ele, ex);
        }
        finally {
            this.parseState.pop();
        }

        return null;
    }

5. 基于Annotation方式的BeanDefinition解析

基于Annotation的方式借助BeanFactoryPostProcessor擴展類實現(xiàn)蹄殃。核心實現(xiàn)邏輯如下:

  • 初始化AnnotationConfigApplicationContext時携茂,初始化AnnotatedBeanDefinitionReader,在AnnotatedBeanDefinitionReader中注冊ConfigurationClassPostProcessor诅岩,實際解析BeanDefinition解析在ConfigurationClassPostProcessor中完成讳苦;
  • AbstractApplicationContext#refresh初始化容器后,invokeBeanFactoryPostProcessors方法中調(diào)用容器后置處理器吩谦;
  • 容器委托給PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors處理鸳谜,在委托類中調(diào)用postProcessor.postProcessBeanFactory執(zhí)行容器后置處理器,其中包括ConfigurationClassPostProcessor式廷,其優(yōu)先級最低咐扭。在ConfigurationClassPostProcessor中處理配置類
  • ConfigurationClassPostProcessor委托給ConfigurationClassParser解析配置類列表中所有的BeanDefinition;解析結(jié)束后,遞歸遍歷新解析BeanDefinition中的配置類
  • ConfigurationClassParser中遍歷配置類蝗肪,每個配置類委托給ComponentScanAnnotationParser實現(xiàn)具體的BeanDefinition解析動作
  • ComponentScanAnnotationParser創(chuàng)建ClassPathBeanDefinitionScanner袜爪,并計算待掃描路徑basePackages,最后的解析動作委托給ClassPathBeanDefinitionScanner#doScan處理
  • ClassPathBeanDefinitionScanner找到所有配置類路徑范圍內(nèi)包含@Component的類(@Service/@Repository/@Controller是特殊的@Component注解薛闪,也會被掃描)辛馆,創(chuàng)建ScannedGenericBeanDefinition;委托AnnotationScopeMetadataResolver解析@Scope注解豁延;解析通用注解昙篙,包括@Lazy@Primary术浪、@DependsOn@Role寿酌、@Description胰苏;檢測是否已注冊,如果未注冊則創(chuàng)建BeanDefinitionHolder醇疼,如果未注冊完成注冊

5.1 AnnotationConfigApplicationContext初始化過程

AnnotationConfigApplicationContext初始化過程如下:

    public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
                // 初始化
        this();
                // 注冊入口配置類
        register(componentClasses);
                // 創(chuàng)建并刷新容器
        refresh();
    }

    public AnnotationConfigApplicationContext() {
        StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");
        // 初始化AnnotatedBeanDefinitionReader硕并,注冊注解相關(guān)的處理器
        this.reader = new AnnotatedBeanDefinitionReader(this);
        createAnnotatedBeanDefReader.end();
        // 初始化ClassPathBeanDefinitionScanner,注冊默認(rèn)注解過濾器秧荆,包括@Component
        this.scanner = new ClassPathBeanDefinitionScanner(this);
    }

5.1.1 AnnotatedBeanDefinitionReader創(chuàng)建過程

BeanDefinition解析中起到關(guān)鍵作用的功能是注冊ConfigurationClassPostProcessor處理器:

    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);
        // 注冊默認(rèn)處理器
        AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
    }

// 調(diào)用本地方法
public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
        registerAnnotationConfigProcessors(registry, null);
    }

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<>(8);

// 注冊ConfigurationClassPostProcessor處理器倔毙,基于@Component、@Service乙濒、@Repository陕赃、@Controller 注解的BeanDefinition解析主要依賴該處理器
        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));
        }

// 注冊AutowiredAnnotationBeanPostProcessor處理器,后面@Autowired注入的bean主要依賴該處理器
        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));
        }

        // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
// 注冊CommonAnnotationBeanPostProcessor處理器颁股,后面@Resource注入的bean主要依賴該處理器處理
        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.
// 支持spring JPA
        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));
        }
// 注冊EventListenerMethodProcessor么库,處理@EventListener注解的方法
        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));
        }
// 注冊DefaultEventListenerFactory,EventListener的默認(rèn)處理器
        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;
    }

5.1.2 ClassPathBeanDefinitionScanner創(chuàng)建過程

對解析BeanDefinition起關(guān)鍵作用的功能是添加處理@Component注解的AnnotationTypeFilter過濾器甘有,核心代碼如下:

    protected void registerDefaultFilters() {
                // 在includeFilters中添加Component過濾器诉儒,解析BeanDefinition時使用此處理器過濾
        this.includeFilters.add(new AnnotationTypeFilter(Component.class));
        ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
        try {
            this.includeFilters.add(new AnnotationTypeFilter(
                    ((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
            logger.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
        }
        catch (ClassNotFoundException ex) {
            // JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
        }
        try {
            this.includeFilters.add(new AnnotationTypeFilter(
                    ((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
            logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
        }
        catch (ClassNotFoundException ex) {
            // JSR-330 API not available - simply skip.
        }
    }

5.2 AbstractApplicationContext#refresh容器刷新過程

在容器刷新主流程中,加載基于AnnotationBeanDefinition解析過程在invokeBeanFactoryPostProcessors(beanFactory);中實現(xiàn):

    protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        // 解析動作委托給PostProcessorRegistrationDelegate處理
        PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

        // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
        // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
        if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }
    }

5.3 PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors容器創(chuàng)建后置處理器處理過程

PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors邏輯比較復(fù)雜亏掀,主要做了幾件事(邏輯只包括BeanDefinitionRegistry容器忱反,非BeanDefinitionRegistry較簡單,可自行從else開始看):

  • 執(zhí)行入?yún)氲?code>BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry方法(BeanDefinitionRegistryPostProcessorBeanFactoryPostProcessor的子類滤愕,增加了postProcessBeanDefinitionRegistry擴展方法温算,用來注冊新的BeanDefinition,注冊新的BeanDefinition
  • 從容器中獲取實現(xiàn)了PriorityOrdered的BeanDefinitionRegistryPostProcessor间影,初始化米者,執(zhí)行起postProcessBeanDefinitionRegistry方法注冊新的BeanDefinition
  • 從容器中獲取實現(xiàn)了Ordered的BeanDefinitionRegistryPostProcessor,初始化,執(zhí)行起postProcessBeanDefinitionRegistry方法注冊新的BeanDefinition
  • 從容器中獲取實現(xiàn)了Ordered的BeanDefinitionRegistryPostProcessor蔓搞,初始化胰丁,執(zhí)行起postProcessBeanDefinitionRegistry方法注冊新的BeanDefinition
    • 從容器中獲取剩余的BeanDefinitionRegistryPostProcessor,初始化喂分,執(zhí)行起postProcessBeanDefinitionRegistry方法注冊新的BeanDefinition
  • 執(zhí)行以上BeanDefinitionRegistryPostProcessor處理器的postProcessBeanFactory
  • 依次獲取并執(zhí)行實現(xiàn)了PriorityOrdered锦庸、Ordered及其他的postProcessBeanFactory方法
    public static void invokeBeanFactoryPostProcessors(
            ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

        // WARNING: Although it may appear that the body of this method can be easily
        // refactored to avoid the use of multiple loops and multiple lists, the use
        // of multiple lists and multiple passes over the names of processors is
        // intentional. We must ensure that we honor the contracts for PriorityOrdered
        // and Ordered processors. Specifically, we must NOT cause processors to be
        // instantiated (via getBean() invocations) or registered in the ApplicationContext
        // in the wrong order.
        //
        // Before submitting a pull request (PR) to change this method, please review the
        // list of all declined PRs involving changes to PostProcessorRegistrationDelegate
        // to ensure that your proposal does not result in a breaking change:
        // https://github.com/spring-projects/spring-framework/issues?q=PostProcessorRegistrationDelegate+is%3Aclosed+label%3A%22status%3A+declined%22

        // Invoke BeanDefinitionRegistryPostProcessors first, if any.
        // 如果存在BeanDefinitionRegistryPostProcessor,執(zhí)行其postProcessBeanDefinitionRegistry方法蒲祈,修改BeanDefinition列表
        Set<String> processedBeans = new HashSet<>();

        if (beanFactory instanceof BeanDefinitionRegistry) {
            BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
            List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
            List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

            for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
                if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                    BeanDefinitionRegistryPostProcessor registryProcessor =
                            (BeanDefinitionRegistryPostProcessor) postProcessor;
                    registryProcessor.postProcessBeanDefinitionRegistry(registry);
                    registryProcessors.add(registryProcessor);
                }
                else {
                    regularPostProcessors.add(postProcessor);
                }
            }

            // Do not initialize FactoryBeans here: We need to leave all regular beans
            // uninitialized to let the bean factory post-processors apply to them!
            // Separate between BeanDefinitionRegistryPostProcessors that implement
            // PriorityOrdered, Ordered, and the rest.
            List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

            // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
        // 獲取實現(xiàn)了PriorityOrdered的BeanDefinitionRegistryPostProcessor甘萧,并初始化(ConfigurationClassPostProcessor在此時被初始化)
            String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                }
            }
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
                        // 執(zhí)行postProcessBeanDefinitionRegistry方法,修改容器BeanDefinition列表梆掸,BeanDefinition解析在這里處理
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
            currentRegistryProcessors.clear();

            // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
                        // 獲取實現(xiàn)了Ordered的BeanDefinitionRegistryPostProcessor處理器扬卷,初始化并執(zhí)行其invokeBeanDefinitionRegistryPostProcessors方法
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                }
            }
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
            currentRegistryProcessors.clear();

            // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
                        // 循環(huán)獲取BeanDefinitionRegistryPostProcessor,初始化酸钦,執(zhí)行invokeBeanDefinitionRegistryPostProcessors方法怪得,直到無新的BeanDefinitionRegistryPostProcessor時結(jié)束
            boolean reiterate = true;
            while (reiterate) {
                reiterate = false;
                postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
                for (String ppName : postProcessorNames) {
                    if (!processedBeans.contains(ppName)) {
                        currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                        processedBeans.add(ppName);
                        reiterate = true;
                    }
                }
                sortPostProcessors(currentRegistryProcessors, beanFactory);
                registryProcessors.addAll(currentRegistryProcessors);
                invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
                currentRegistryProcessors.clear();
            }

            // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
                        // 執(zhí)行后置處理器的postProcessBeanFactory方法,該方法需BeanDefinition注冊完調(diào)用
            invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
            invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
        }

        else {
            // Invoke factory processors registered with the context instance.
            invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
        }

        // Do not initialize FactoryBeans here: We need to leave all regular beans
        // uninitialized to let the bean factory post-processors apply to them!
                // 獲取BeanFactoryPostProcessor卑硫,初始化并執(zhí)行后置處理器的postProcessBeanFactory方法徒恋,該方法需BeanDefinition注冊完調(diào)用
        String[] postProcessorNames =
                beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

        // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
        // Ordered, and the rest.
        List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
        List<String> orderedPostProcessorNames = new ArrayList<>();
        List<String> nonOrderedPostProcessorNames = new ArrayList<>();
        for (String ppName : postProcessorNames) {
            if (processedBeans.contains(ppName)) {
                // skip - already processed in first phase above
            }
            else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
            }
            else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
                orderedPostProcessorNames.add(ppName);
            }
            else {
                nonOrderedPostProcessorNames.add(ppName);
            }
        }

        // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
        sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

        // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
        List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
        for (String postProcessorName : orderedPostProcessorNames) {
            orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
        }
        sortPostProcessors(orderedPostProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

        // Finally, invoke all other BeanFactoryPostProcessors.
        List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
        for (String postProcessorName : nonOrderedPostProcessorNames) {
            nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
        }
        invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

        // Clear cached merged bean definitions since the post-processors might have
        // modified the original metadata, e.g. replacing placeholders in values...
        beanFactory.clearMetadataCache();
    }

5.4 ConfigurationClassPostProcessor解析過程

ConfigurationClassPostProcessor解析過程比較簡單:

  • 從容器的BeanDefinition列表中獲取配置類
  • 設(shè)置BeanNameGenerator
  • 創(chuàng)建ConfigurationClassParser,并委托給parser解析
  • 遞歸從解析結(jié)果中繼續(xù)獲取配置類欢伏,并委托給ConfigurationClassParser解析入挣,直到?jīng)]有配置類
    public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
        List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
        String[] candidateNames = registry.getBeanDefinitionNames();

            // 查找配置類,注解為@ Configuration硝拧、@Component径筏、@ComponentScan、@Import障陶、@ImportResource
        for (String beanName : candidateNames) {
            BeanDefinition beanDef = registry.getBeanDefinition(beanName);
            if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
                }
            }
            else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
                configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
            }
        }

        // Return immediately if no @Configuration classes were found
        if (configCandidates.isEmpty()) {
            return;
        }

        // Sort by previously determined @Order value, if applicable
        // 排序操作
        configCandidates.sort((bd1, bd2) -> {
            int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
            int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
            return Integer.compare(i1, i2);
        });

        // Detect any custom bean name generation strategy supplied through the enclosing application context
// 檢測是否存在自定義bean name生成策略匠璧,如果存在,創(chuàng)建并設(shè)置
        SingletonBeanRegistry sbr = null;
        if (registry instanceof SingletonBeanRegistry) {
            sbr = (SingletonBeanRegistry) registry;
            if (!this.localBeanNameGeneratorSet) {
                BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
                        AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
                if (generator != null) {
                    this.componentScanBeanNameGenerator = generator;
                    this.importBeanNameGenerator = generator;
                }
            }
        }

        if (this.environment == null) {
            this.environment = new StandardEnvironment();
        }

        // Parse each @Configuration class
                // 創(chuàng)建ConfigurationClassParser咸这,具體解析委托給ConfigurationClassParser
        ConfigurationClassParser parser = new ConfigurationClassParser(
                this.metadataReaderFactory, this.problemReporter, this.environment,
                this.resourceLoader, this.componentScanBeanNameGenerator, registry);

        Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
        Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
                // 遞歸調(diào)用夷恍,解析配置類,并從解析結(jié)果中篩選未解析的配置類媳维,繼續(xù)解析酿雪,直到無配置類
        do {
            StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
            parser.parse(candidates);
            parser.validate();

            Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
            configClasses.removeAll(alreadyParsed);

            // Read the model and create bean definitions based on its content
            if (this.reader == null) {
                this.reader = new ConfigurationClassBeanDefinitionReader(
                        registry, this.sourceExtractor, this.resourceLoader, this.environment,
                        this.importBeanNameGenerator, parser.getImportRegistry());
            }
            this.reader.loadBeanDefinitions(configClasses);
            alreadyParsed.addAll(configClasses);
            processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();

            candidates.clear();
            if (registry.getBeanDefinitionCount() > candidateNames.length) {
                String[] newCandidateNames = registry.getBeanDefinitionNames();
                Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
                Set<String> alreadyParsedClasses = new HashSet<>();
                for (ConfigurationClass configurationClass : alreadyParsed) {
                    alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
                }
                for (String candidateName : newCandidateNames) {
                    if (!oldCandidateNames.contains(candidateName)) {
                        BeanDefinition bd = registry.getBeanDefinition(candidateName);
                        if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
                                !alreadyParsedClasses.contains(bd.getBeanClassName())) {
                            candidates.add(new BeanDefinitionHolder(bd, candidateName));
                        }
                    }
                }
                candidateNames = newCandidateNames;
            }
        }
        while (!candidates.isEmpty());

        // Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
        if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
            sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
        }

        if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
            // Clear cache in externally provided MetadataReaderFactory; this is a no-op
            // for a shared cache since it'll be cleared by the ApplicationContext.
            ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
        }
    }

5.5 ConfigurationClassParser解析過程

parse方法遍歷配置類,調(diào)用重載的parse(((AnnotatedBeanDefinition) bd).getMetadata()完成解析侄刽。

    public void parse(Set<BeanDefinitionHolder> configCandidates) {
        for (BeanDefinitionHolder holder : configCandidates) {
            BeanDefinition bd = holder.getBeanDefinition();
            try {
                if (bd instanceof AnnotatedBeanDefinition) {
                    parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
                }
                else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
                    parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
                }
                else {
                    parse(bd.getBeanClassName(), holder.getBeanName());
                }
            }
            catch (BeanDefinitionStoreException ex) {
                throw ex;
            }
            catch (Throwable ex) {
                throw new BeanDefinitionStoreException(
                        "Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
            }
        }

        this.deferredImportSelectorHandler.process();
    }

parse調(diào)用processConfigurationClass解析指黎。

    protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
        processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
    }

processConfigurationClass實現(xiàn)如下:

protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
        // 判斷 @Conditional 注解是否滿足條件
        if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
            return;
        }

        ConfigurationClass existingClass = this.configurationClasses.get(configClass);
        if (existingClass != null) {
            if (configClass.isImported()) {
                // 如果已經(jīng)解析過,且是@Import的類州丹,不重復(fù)解析
                if (existingClass.isImported()) {
                    existingClass.mergeImportedBy(configClass);
                }
                // Otherwise ignore new imported config class; existing non-imported class overrides it.
                return;
            }
            else {
                // Explicit bean definition found, probably replacing an import.
                // Let's remove the old one and go with the new one.
                // 如果已經(jīng)解析過醋安,但不是@Import的杂彭,重復(fù)解析覆蓋
                this.configurationClasses.remove(configClass);
                this.knownSuperclasses.values().removeIf(configClass::equals);
            }
        }

        // Recursively process the configuration class and its superclass hierarchy.
        // 統(tǒng)一封裝成SourceClass處理
        SourceClass sourceClass = asSourceClass(configClass, filter);
        do {
                        // 實際的解析動作
            sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
        }
        while (sourceClass != null);

        this.configurationClasses.put(configClass, configClass);
    }

doProcessConfigurationClass解析過程:

    protected final SourceClass doProcessConfigurationClass(
            ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
            throws IOException {

        if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
            // Recursively process any member (nested) classes first
            // 遞歸處理內(nèi)部類
            processMemberClasses(configClass, sourceClass, filter);
        }

        // Process any @PropertySource annotations
        // 處理@PropertySource注解,比較簡單吓揪,可見官網(wǎng)@PropertySource的用法
        for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
                sourceClass.getMetadata(), PropertySources.class,
                org.springframework.context.annotation.PropertySource.class)) {
            if (this.environment instanceof ConfigurableEnvironment) {
                processPropertySource(propertySource);
            }
            else {
                logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
                        "]. Reason: Environment must implement ConfigurableEnvironment");
            }
        }

        // Process any @ComponentScan annotations
        Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
                sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
        if (!componentScans.isEmpty() &&
                !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
            for (AnnotationAttributes componentScan : componentScans) {
                // The config class is annotated with @ComponentScan -> perform the scan immediately
                // 真正的解析動作委托給ComponentScanAnnotationParser#parse處理
                Set<BeanDefinitionHolder> scannedBeanDefinitions =
                        this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
                // Check the set of scanned definitions for any further config classes and parse recursively if needed
                for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
                    BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
                    if (bdCand == null) {
                        bdCand = holder.getBeanDefinition();
                    }
                    if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
                        // 遞歸遍歷已解析后的BeanDefinition
                        parse(bdCand.getBeanClassName(), holder.getBeanName());
                    }
                }
            }
        }

        // Process any @Import annotations
        // 處理@Import注解
        processImports(configClass, sourceClass, getImports(sourceClass), filter, true);

        // Process any @ImportResource annotations
        // 處理@ImportResource注解
        AnnotationAttributes importResource =
                AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
        if (importResource != null) {
            String[] resources = importResource.getStringArray("locations");
            Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
            for (String resource : resources) {
                String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
                configClass.addImportedResource(resolvedResource, readerClass);
            }
        }

        // Process individual @Bean methods
        // 處理方法@Bean注解
        Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
        for (MethodMetadata methodMetadata : beanMethods) {
            configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
        }

        // Process default methods on interfaces
        // 處理接口中的默認(rèn)方法實現(xiàn)中的 @Bean注解
        processInterfaces(configClass, sourceClass);

        // Process superclass, if any
        // 處理父類
        if (sourceClass.getMetadata().hasSuperClass()) {
            String superclass = sourceClass.getMetadata().getSuperClassName();
            if (superclass != null && !superclass.startsWith("java") &&
                    !this.knownSuperclasses.containsKey(superclass)) {
                this.knownSuperclasses.put(superclass, configClass);
                // Superclass found, return its annotation metadata and recurse
                return sourceClass.getSuperClass();
            }
        }

        // No superclass -> processing is complete
        return null;
    }

5.6 ComponentScanAnnotationParser解析過程

ComponentScanAnnotationParser 解析 @ComponentScan 屬性亲怠,委托給 ClassPathBeanDefinitionScanner解析。

    public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, String declaringClass) {
        ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
                componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);

        Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
        boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);
        scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator :
                BeanUtils.instantiateClass(generatorClass));

        ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy");
        if (scopedProxyMode != ScopedProxyMode.DEFAULT) {
            scanner.setScopedProxyMode(scopedProxyMode);
        }
        else {
            Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");
            scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));
        }

        scanner.setResourcePattern(componentScan.getString("resourcePattern"));

        for (AnnotationAttributes includeFilterAttributes : componentScan.getAnnotationArray("includeFilters")) {
            List<TypeFilter> typeFilters = TypeFilterUtils.createTypeFiltersFor(includeFilterAttributes, this.environment,
                    this.resourceLoader, this.registry);
            for (TypeFilter typeFilter : typeFilters) {
                scanner.addIncludeFilter(typeFilter);
            }
        }
        for (AnnotationAttributes excludeFilterAttributes : componentScan.getAnnotationArray("excludeFilters")) {
            List<TypeFilter> typeFilters = TypeFilterUtils.createTypeFiltersFor(excludeFilterAttributes, this.environment,
                this.resourceLoader, this.registry);
            for (TypeFilter typeFilter : typeFilters) {
                scanner.addExcludeFilter(typeFilter);
            }
        }

        boolean lazyInit = componentScan.getBoolean("lazyInit");
        if (lazyInit) {
            scanner.getBeanDefinitionDefaults().setLazyInit(true);
        }

        Set<String> basePackages = new LinkedHashSet<>();
        String[] basePackagesArray = componentScan.getStringArray("basePackages");
        for (String pkg : basePackagesArray) {
            String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),
                    ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
            Collections.addAll(basePackages, tokenized);
        }
        for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) {
            basePackages.add(ClassUtils.getPackageName(clazz));
        }
        if (basePackages.isEmpty()) {
            basePackages.add(ClassUtils.getPackageName(declaringClass));
        }

        scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
            @Override
            protected boolean matchClassName(String className) {
                return declaringClass.equals(className);
            }
        });
        return scanner.doScan(StringUtils.toStringArray(basePackages));
    }

5.7 ClassPathBeanDefinitionScanner解析過程

解析BeanDefinition柠辞,并注冊到spring容器团秽。

    protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
        Assert.notEmpty(basePackages, "At least one base package must be specified");
        Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
        for (String basePackage : basePackages) {
            // 掃描所有`@Component`(包括`@Service`/`@Repository`/`@Controller`)注解類
            Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
            for (BeanDefinition candidate : candidates) {
                                 // 處理 @Scope 注解
                ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
                candidate.setScope(scopeMetadata.getScopeName());
                String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
                // 設(shè)置默認(rèn)參數(shù)
                if (candidate instanceof AbstractBeanDefinition) {
                    postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
                }
                if (candidate instanceof AnnotatedBeanDefinition) {
// 解析通用注解,包括@Lazy叭首,@Primary习勤,@DependsOn,@Role焙格,@Description注解
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
                }
                                // 判斷是否已注冊图毕,如果未注冊,注冊到spring容器
                if (checkCandidate(beanName, candidate)) {
                    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
                    definitionHolder =
                            AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
                    beanDefinitions.add(definitionHolder);
                    registerBeanDefinition(definitionHolder, this.registry);
                }
            }
        }
        return beanDefinitions;
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末眷唉,一起剝皮案震驚了整個濱河市予颤,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌厢破,老刑警劉巖荣瑟,帶你破解...
    沈念sama閱讀 216,651評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件治拿,死亡現(xiàn)場離奇詭異摩泪,居然都是意外死亡,警方通過查閱死者的電腦和手機劫谅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評論 3 392
  • 文/潘曉璐 我一進店門见坑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人捏检,你說我怎么就攤上這事荞驴。” “怎么了贯城?”我有些...
    開封第一講書人閱讀 162,931評論 0 353
  • 文/不壞的土叔 我叫張陵熊楼,是天一觀的道長。 經(jīng)常有香客問我能犯,道長鲫骗,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,218評論 1 292
  • 正文 為了忘掉前任踩晶,我火速辦了婚禮执泰,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘渡蜻。我一直安慰自己术吝,他們只是感情好计济,可當(dāng)我...
    茶點故事閱讀 67,234評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著排苍,像睡著了一般沦寂。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上纪岁,一...
    開封第一講書人閱讀 51,198評論 1 299
  • 那天凑队,我揣著相機與錄音,去河邊找鬼幔翰。 笑死漩氨,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的遗增。 我是一名探鬼主播叫惊,決...
    沈念sama閱讀 40,084評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼做修!你這毒婦竟也來了霍狰?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,926評論 0 274
  • 序言:老撾萬榮一對情侶失蹤饰及,失蹤者是張志新(化名)和其女友劉穎蔗坯,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體燎含,經(jīng)...
    沈念sama閱讀 45,341評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡宾濒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,563評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了屏箍。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片绘梦。...
    茶點故事閱讀 39,731評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖赴魁,靈堂內(nèi)的尸體忽然破棺而出卸奉,到底是詐尸還是另有隱情,我是刑警寧澤颖御,帶...
    沈念sama閱讀 35,430評論 5 343
  • 正文 年R本政府宣布榄棵,位于F島的核電站,受9級特大地震影響潘拱,放射性物質(zhì)發(fā)生泄漏疹鳄。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,036評論 3 326
  • 文/蒙蒙 一泽铛、第九天 我趴在偏房一處隱蔽的房頂上張望尚辑。 院中可真熱鬧,春花似錦盔腔、人聲如沸杠茬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瓢喉。三九已至宁赤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間栓票,已是汗流浹背决左。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留走贪,地道東北人佛猛。 一個月前我還...
    沈念sama閱讀 47,743評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像坠狡,于是被迫代替她去往敵國和親继找。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,629評論 2 354

推薦閱讀更多精彩內(nèi)容