• springBoot-启动原理


    注:SpringBoot版本 2.6.2

    SpringBoot的入口是从SpringApplication.run()传入我们的主启动类开始

    复制代码
    @SpringBootApplication
    public class LeeSpringbootApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(LeeSpringbootApplication.class, args);
        }
    }
    复制代码

    run()方法:

        1、初始化SrpingApplication对象

        2、执行run() 方法(primarySources:主启动类class)

    public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
        return new SpringApplication(primarySources).run(args);
    }

    1、初始化SrpingApplication对象

      1、设置应用类型,后面会根据类型初始化对应的环境,常用的一般都是servlet环境

      2、加载系统中引导器Bootstrapper(从META-INF/spring.factories中加载)

      3、初始化classpath下 META-INF/spring.factories 中已配置的ApplicationContextInitalizer

      4、初始化classpath下所以已配置的 ApplicationListener

      5、根据调用栈,设置 main 方法的类名

    复制代码
    public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
        //设置资源加载器为null
        this.resourceLoader = resourceLoader;
        //断言加载资源不能为null
        Assert.notNull(primarySources, "PrimarySources must not be null");
        //将primarySources数组转换为list,最后放到LinkedHashSet集合中
        this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
        // 1.1 推断应用类型,后面会根据类型初始化对应的环境,常用的一般都是servlet环境
        this.webApplicationType = WebApplicationType.deduceFromClasspath();
        // 1.2 加载系统中引导器Bootstrapper
        this.bootstrapRegistryInitializers = new ArrayList<>(
                getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
        // 1.3 初始化classpath下 META-INF/spring.factories 中已配置的ApplicationContextInitalizer
        setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
        // 1.4 初始化classpath下所以已配置的 ApplicationListener
        setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
        // 1.5 根据调用栈,设置 main 方法的类名
        this.mainApplicationClass = deduceMainApplicationClass();
    }
    复制代码

      在执行 getSpringFactoriesInstances(BootstrapRegistryInitializer.class) 中会调用 loadSpringFactories() 方法遍历所有jar包中classpath下 META-INF/spring.factories文件,并保存在缓存中

    private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
        Map<String, List<String>> result = cache.get(classLoader);
        if (result != null) {
            return result;
        }
    
        result = new HashMap<>();
        try {
            Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION);
            while (urls.hasMoreElements()) {
                URL url = urls.nextElement();
                UrlResource resource = new UrlResource(url);
                Properties properties = PropertiesLoaderUtils.loadProperties(resource);
                for (Map.Entry<?, ?> entry : properties.entrySet()) {
                    String factoryTypeName = ((String) entry.getKey()).trim();
                    String[] factoryImplementationNames =
                            StringUtils.commaDelimitedListToStringArray((String) entry.getValue());
                    for (String factoryImplementationName : factoryImplementationNames) {
                        result.computeIfAbsent(factoryTypeName, key -> new ArrayList<>())
                                .add(factoryImplementationName.trim());
                    }
                }
            }
    
            // Replace all lists with unmodifiable lists containing unique elements
            result.replaceAll((factoryType, implementations) -> implementations.stream().distinct()
                    .collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList)));
            cache.put(classLoader, result);
        }
        catch (IOException ex) {
            throw new IllegalArgumentException("Unable to load factories from location [" +
                    FACTORIES_RESOURCE_LOCATION + "]", ex);
        }
        return result;
    }
    loadSpringFactories

     

    2、执行run() 方法

      1、获取并启动监听器

      2、构造上下文环境

      3、初始化应用上下文

      4、刷新应用上下文前的准备阶段   

      5、刷新上下文

      6、刷新应用上下文后的扩展接口

    复制代码
    public ConfigurableApplicationContext run(String... args) {
        //记录程序运行时间
        long startTime = System.nanoTime();
        // 创建 DefaultBootstrapContext 的一项
        DefaultBootstrapContext bootstrapContext = createBootstrapContext();
        // ConfigurableApplicationContext spring的上下文
        ConfigurableApplicationContext context = null;
        configureHeadlessProperty();
        // 1、获取并启动监听器
        SpringApplicationRunListeners listeners = getRunListeners(args);
        listeners.starting(bootstrapContext, this.mainApplicationClass);
        try {
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            // 2、构造上下文环境
            ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
            // 处理需要忽略的Bean
            configureIgnoreBeanInfo(environment);
            // 打印banner (springboot图标)
            Banner printedBanner = printBanner(environment);
            // 3、初始化应用上下文
            context = createApplicationContext();
            context.setApplicationStartup(this.applicationStartup);
            // 4、刷新应用上下文前的准备阶段
            prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
            // 5、刷新上下文
            refreshContext(context);
            // 6、刷新应用上下文后的扩展接口
            afterRefresh(context, applicationArguments);
            // 记录执行时间
            Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
            if (this.logStartupInfo) {
                new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
            }
            listeners.started(context, timeTakenToStartup);
            callRunners(context, applicationArguments);
        }
        catch (Throwable ex) {
            handleRunFailure(context, ex, listeners);
            throw new IllegalStateException(ex);
        }
        try {
            Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
            listeners.ready(context, timeTakenToReady);
        }
        catch (Throwable ex) {
            handleRunFailure(context, ex, null);
            throw new IllegalStateException(ex);
        }
        return context;
    }
    复制代码

      2.1 加载监听器

        加载META-INF/spring.factories 中的 SpringApplicationRunListener,SpringApplicationRunListeners负责在springBoot启动的不同阶段,广播出不同的消息,传递给ApplicationListener监听器实现类

    复制代码
    private SpringApplicationRunListeners getRunListeners(String[] args) {
        Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
        return new SpringApplicationRunListeners(logger,
                getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args),
                this.applicationStartup);
    }
    复制代码

        getSpringFactoriesInstances 中加载构建监听器对象并根据order进行排序

    复制代码
    private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
        ClassLoader classLoader = getClassLoader();
        // Use names and ensure unique to protect against duplicates
        Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
        List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
        AnnotationAwareOrderComparator.sort(instances);
        return instances;
    }
    复制代码

      2.2 构造上下文环境

        根据之前标记的应用类型(SERVLET)创建相应的环境,并根据配置文件,配置相应的系统环境

    复制代码
    private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
                DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
        // Create and configure the environment
        //  创建并配置相应环境
        ConfigurableEnvironment environment = getOrCreateEnvironment();
        // 根据用户配置,配置系统环境
        configureEnvironment(environment, applicationArguments.getSourceArgs());
        ConfigurationPropertySources.attach(environment);
        // 启动监听器,其中一个重要的监听器 ConfigFileApplicationListener 加载项目配置文件的监听器
        listeners.environmentPrepared(bootstrapContext, environment);
        DefaultPropertiesPropertySource.moveToEnd(environment);
        Assert.state(!environment.containsProperty("spring.main.environment-prefix"),
                "Environment prefix cannot be set via properties.");
        bindToSpringApplication(environment);
        if (!this.isCustomEnvironment) {
            environment = convertEnvironment(environment);
        }
        ConfigurationPropertySources.attach(environment);
        return environment;
    }
    复制代码

      2.3 初始化应用上下文

        根据配置的应用类型(SERVLET)创建对应的context (AnnotationConfigServletWebServerApplicationContext) 并在父类 GenericApplicationContext 的构造方法中创建了DefaultListableBeanFactory(ioc容器)

        protected ConfigurableApplicationContext createApplicationContext() {
            return this.applicationContextFactory.create(this.webApplicationType);
        }
    复制代码
    ApplicationContextFactory DEFAULT = (webApplicationType) -> {
        try {
            switch (webApplicationType) {
            case SERVLET:
                return new AnnotationConfigServletWebServerApplicationContext();
            case REACTIVE:
                return new AnnotationConfigReactiveWebServerApplicationContext();
            default:
                return new AnnotationConfigApplicationContext();
            }
        }
        catch (Exception ex) {
            throw new IllegalStateException("Unable create a default ApplicationContext instance, "
                    + "you may need a custom ApplicationContextFactory", ex);
        }
    };
    复制代码

      2.4 刷新应用上下文前的准备阶段

        主要完成应用上下文属性设置,并且将启动类生成实例对象保存到容器中。

    复制代码
    private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
        ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
        ApplicationArguments applicationArguments, Banner printedBanner) {
        // 设置容器环境
        context.setEnvironment(environment);
        // 执行容器后置处理(主要设置转换器)
        postProcessApplicationContext(context);
        // 应用初始化器,执行容器中的 ApplicationContextInitializer 包括spring.factories
        applyInitializers(context);
        // 向各个容器中发送容器已经准备好的事件
        listeners.contextPrepared(context);
        bootstrapContext.close(context);
        if (this.logStartupInfo) {
            logStartupInfo(context.getParent() == null);
            logStartupProfileInfo(context);
        }
        // Add boot specific singleton beans
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        // 将main函数中的args参数封装成单例Bean,注册到容器
        beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
        if (printedBanner != null) {
            // 将printedBanner 封装成单例Bean 注册到容器
            beanFactory.registerSingleton("springBootBanner", printedBanner);
        }
        if (beanFactory instanceof AbstractAutowireCapableBeanFactory) {
            ((AbstractAutowireCapableBeanFactory) beanFactory).setAllowCircularReferences(this.allowCircularReferences);
        if (beanFactory instanceof DefaultListableBeanFactory) {
            ((DefaultListableBeanFactory) beanFactory)
                .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
        }
        }
        if (this.lazyInitialization) {
            context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
        }
        // Load the sources
        // 获取主启动类
        Set<Object> sources = getAllSources();
        Assert.notEmpty(sources, "Sources must not be empty");
        // 加载启动类,将启动类注册到容器
        load(context, sources.toArray(new Object[0]));
        // 发布容器中已加载的事件
        listeners.contextLoaded(context);
    }
    复制代码

        postProcessApplicationContext(context) 设置转换器

    protected void postProcessApplicationContext(ConfigurableApplicationContext context) {
        if (this.beanNameGenerator != null) {
            context.getBeanFactory().registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR,
                    this.beanNameGenerator);
        }
        if (this.resourceLoader != null) {
            if (context instanceof GenericApplicationContext) {
                ((GenericApplicationContext) context).setResourceLoader(this.resourceLoader);
            }
            if (context instanceof DefaultResourceLoader) {
                ((DefaultResourceLoader) context).setClassLoader(this.resourceLoader.getClassLoader());
            }
        }
        if (this.addConversionService) {
            context.getBeanFactory().setConversionService(context.getEnvironment().getConversionService());
        }
    }
    postProcessApplicationContext

        应用ApplicationContextInitializer

        protected void applyInitializers(ConfigurableApplicationContext context) {
            for (ApplicationContextInitializer initializer : getInitializers()) {
                Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(),
                        ApplicationContextInitializer.class);
                Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
                initializer.initialize(context);
            }
        }
    applyInitializer

        getAllSource() 获取主启动类

    public Set<Object> getAllSources() {
        Set<Object> allSources = new LinkedHashSet<>();
        if (!CollectionUtils.isEmpty(this.primarySources)) {
            allSources.addAll(this.primarySources);
        }
        if (!CollectionUtils.isEmpty(this.sources)) {
            allSources.addAll(this.sources);
        }
        return Collections.unmodifiableSet(allSources);
    }
    getAllSource

        load() 主要将主启动类生成实例对象保存在容器中,spring容器在启动的时候会将类解析成spring内部的BeanDefinition结构,并将BeanDefinition存储到DefaultListableBeanFactory的map中。

    复制代码
    protected void load(ApplicationContext context, Object[] sources) {
        if (logger.isDebugEnabled()) {
            logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
        }
        // 创建 BeanDefinitionLoader
        BeanDefinitionLoader loader = createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources);
        if (this.beanNameGenerator != null) {
            loader.setBeanNameGenerator(this.beanNameGenerator);
        }
        if (this.resourceLoader != null) {
            loader.setResourceLoader(this.resourceLoader);
        }
        if (this.environment != null) {
            loader.setEnvironment(this.environment);
        }
        // 将启动类生成实例对象保存到容器中
        loader.load();
    }
    复制代码
        getBeanDefinitionRegistry(context) 将上下文转换为 BeanDefinitionRegistry 类型
    private BeanDefinitionRegistry getBeanDefinitionRegistry(ApplicationContext context) {
        if (context instanceof BeanDefinitionRegistry) {
            return (BeanDefinitionRegistry) context;
        }
        if (context instanceof AbstractApplicationContext) {
            return (BeanDefinitionRegistry) ((AbstractApplicationContext) context).getBeanFactory();
        }
        throw new IllegalStateException("Could not locate BeanDefinitionRegistry");
    }
    
    getBeanDefinitionRegistry
    getBeanDefinitionRegistry

        createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources) 创建BeanDefinitionLoader,其中创建一些Bean定义读取器

    复制代码
    protected BeanDefinitionLoader createBeanDefinitionLoader(BeanDefinitionRegistry registry, Object[] sources) {
        return new BeanDefinitionLoader(registry, sources);
    }
    
    BeanDefinitionLoader(BeanDefinitionRegistry registry, Object... sources) {
        Assert.notNull(registry, "Registry must not be null");
        Assert.notEmpty(sources, "Sources must not be empty");
        this.sources = sources;
        // 创建注解形式的Bean定义读取器, eg:@Configuration @Bean @Component @Controller等
        this.annotatedReader = new AnnotatedBeanDefinitionReader(registry);
        // 创建xml形式的Bean定义读取器
        this.xmlReader = (XML_ENABLED ? new XmlBeanDefinitionReader(registry) : null);
        this.groovyReader = (isGroovyPresent() ? new GroovyBeanDefinitionReader(registry) : null);
        // 创建类路径扫描器
        this.scanner = new ClassPathBeanDefinitionScanner(registry);
        // 扫描器添加排除过滤器
        this.scanner.addExcludeFilter(new ClassExcludeFilter(sources));
    }
    复制代码

        

        loader.load()将启动类生成实例对象保存在容器中

    void load() {
        for (Object source : this.sources) {
        //source 为启动类
            load(source);        
        }
    }
    
    private void load(Object source) {
        Assert.notNull(source, "Source must not be null");
        if (source instanceof Class<?>) {
        // 从class中加载
            load((Class<?>) source);
            return;
        }
        if (source instanceof Resource) {
        // 从 Resource 中加载
            load((Resource) source);
            return;
        }
        if (source instanceof Package) {
        // 从 Package 中加载
            load((Package) source);
            return;
        }
        if (source instanceof CharSequence) {
        // 从 CharSequence 中加载
            load((CharSequence) source);
            return;
        }
        throw new IllegalArgumentException("Invalid source type " + source.getClass());
    }
    
    private void load(Class<?> source) {
        if (isGroovyPresent() && GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
            // Any GroovyLoaders added in beans{} DSL can contribute beans here
            GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source, GroovyBeanDefinitionSource.class);
            ((GroovyBeanDefinitionReader) this.groovyReader).beans(loader.getBeans());
        }
        if (isEligible(source)) {
            // 将启动类的 BeanDefinition 注册到 BeanDefinitionMap 中
            this.annotatedReader.register(source);
        }
    }
    
    load()
    load

     

      2.5 刷新上下文

         主要逻辑为AbstractApplicationContext 对象的 refresh() 方法,进行整个容器的刷新过程,会调用spring中的refresh()方法,其中有13个关键方法,来完成整个
    SpringBoot应用程序的启动。

    复制代码
    private void refreshContext(ConfigurableApplicationContext context) {
        if (this.registerShutdownHook) {
            shutdownHook.registerApplicationContext(context);
        }
        refresh(context);
    }
    
    protected void refresh(ConfigurableApplicationContext applicationContext) {
        applicationContext.refresh();
    }
    
    public final void refresh() throws BeansException, IllegalStateException {
        try {
            super.refresh();
        }
        catch (RuntimeException ex) {
            WebServer webServer = this.webServer;
            if (webServer != null) {
                webServer.stop();
            }
            throw ex;
        }
    }
    
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
    
            // Prepare this context for refreshing.
            //1:准备刷新上下文环境
            prepareRefresh();
    
            // Tell the subclass to refresh the internal bean factory.
            //2:获取告诉子类初始化Bean工厂  不同工厂不同实现
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
            // Prepare the bean factory for use in this context.
            // 对bean工厂进行填充属性
            prepareBeanFactory(beanFactory);
    
            try {
                // Allows post-processing of the bean factory in context subclasses.
                // 执行beanFactroy后置处理器
                postProcessBeanFactory(beanFactory);
    
                StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
                // Invoke factory processors registered as beans in the context.
                // 调用我们的bean工厂的后置处理器. 1. 会在此将class扫描成beanDefinition  2.bean工厂的后置处理器调用
                invokeBeanFactoryPostProcessors(beanFactory);
    
                // Register bean processors that intercept bean creation.
                // 注册我们bean的后置处理器
                registerBeanPostProcessors(beanFactory);
                beanPostProcess.end();
    
                // Initialize message source for this context.
                // 初始化国际化资源处理器.
                initMessageSource();
    
                // Initialize event multicaster for this context.
                // 创建事件多播器
                initApplicationEventMulticaster();
    
                // Initialize other special beans in specific context subclasses.
                // 这个方法同样也是留个子类实现的springboot也是从这个方法进行启动tomcat的.
                onRefresh();
    
                // Check for listener beans and register them.
                //把我们的事件监听器注册到多播器上
                registerListeners();
    
                // Instantiate all remaining (non-lazy-init) singletons.
                // 实例化我们剩余的单实例bean.
                finishBeanFactoryInitialization(beanFactory);
    
                // Last step: publish corresponding event.
                // 最后容器刷新 发布刷新事件(Spring cloud也是从这里启动的)
                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();
            }
        }
    }
    复制代码

     

        invokeBeanFactoryPostProcessors(beanFactory) 改方法会解析核心启动类中 @SpringBootApplication实现自动配置。

        Ioc容器的初始化包括三个步骤,该三个步骤在 invokeBeanFactoryPostProcessors 中完成。

                (1) Resource定位

           在SpringBoot中,包扫描是从主类所在包开始扫描,prepareContext()方法中,会将主类解析成BeanDefinition保存在容器中,然后在refresh()方法的invokeBeanFactoryPostProcessors()方法中解析主类的BeanDefinition获取basePackage的路径,这样就完成了定位的过程。

         SpringBoot的各种starter是通过SPI扩展机制实现的自动装配,SpringBoot的自动装配同样也是在invokeBeanFactoryPostProcessors()方法中实现的。在SpringBoot中有很多的@EnableXXX注解,其底层是@Import注解,在invokeBeanFactoryPostProcessors()方法中也实现了对该注解指定的配置类的定位加载。

         常规在SpringBoot中有三种定位方法:主类所在的包、SPI扩展机制实现的自动装配、@Import注解指定的类。

         SPI ,全称为 Service Provider Interface,是一种服务发现机制。它通过在ClassPath路径下的META-INF/services文件夹查找文件,自动加载文件里所定义的类,也可以这样理解SPI是“基于接口的编程+策略模式+配置文件”组成实现的动态加载机制。

                (2)BeanDefinition的载入

           SpringBoot会将通过定位得到的basePackage的路径拼装成 classpath:com/***/.class 的形式,然后 PathMatchingResourcePatternResolver类会将该路径下所有的 .class 文件加载进来,然后进行遍历判断是否含有 @Component 注解,如果有就是要装载的 BeanDefinition。

                (3)注册Beanfinition

           注册过程是将载入过程中解析得到的BeanDefinition向IOC容器进行注册。通过上下文分析,在容器中将BeanDefinition注入到一个ConcurrenHashMap中,IOC容器通过这个map来保存BeanDefinition数据。

    protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        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()));
        }
    }
    
    // PostProcessorRegistrationDelegate
    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.
        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.
            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);
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
            currentRegistryProcessors.clear();
    
            // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
            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.
            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.
            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!
        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();
    }
    
    private static void invokeBeanDefinitionRegistryPostProcessors(
            Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry, ApplicationStartup applicationStartup) {
    
        for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
            StartupStep postProcessBeanDefRegistry = applicationStartup.start("spring.context.beandef-registry.post-process")
                    .tag("postProcessor", postProcessor::toString);
            // 解析注解
            postProcessor.postProcessBeanDefinitionRegistry(registry);
            postProcessBeanDefRegistry.end();
        }
    }
    invokeBeanFactoryPostProcessors

       实现自动装配:

        invokeBeanFactoryPostProcessors()方法主要是对 ConfigurationClassPostProcessor 类的处理,这是BeanDefinitionRegistryPostProcessor的子类,BeanDefinitionRegistryPostProcessor 是BeanDefinitionRegistryPostProcessor 的子类,调用BeanDefinitionRegistryPostProcessor中的postProcessBeanDefinitionRegistry()方法,会解析 @PropertySource @ComponentScans @ComponentScan @Bean @Import等注解。

      refresh() -> AbstractApplicationContext.invokeBeanFactoryPostProcessors(beanFactory) 
      -> invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup())
      -> postProcessor.postProcessBeanDefinitionRegistry(registry) (ConfigurationClassPostProcessor类下的方法)
      -> processConfigBeanDefinitions(registry) -> new ConfigurationClassParser() (解析@Configuration 标注的类)
      -> parser.parse(candidates) (解析启动类上的注解)
      -> this.reader.loadBeanDefinitions(configClasses) (生效自动配置类)
    //     ConfigurationClassPostProcessor
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
        int registryId = System.identityHashCode(registry);
        if (this.registriesPostProcessed.contains(registryId)) {
            throw new IllegalStateException(
                    "postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
        }
        if (this.factoriesPostProcessed.contains(registryId)) {
            throw new IllegalStateException(
                    "postProcessBeanFactory already called on this post-processor against " + registry);
        }
        this.registriesPostProcessed.add(registryId);
        
        processConfigBeanDefinitions(registry);
    }
    public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
        List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
        String[] candidateNames = registry.getBeanDefinitionNames();
    
        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
        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
        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());
        do {
            StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
            //获取所有bean的全路径(解析各类注解)
            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();
        }
    }
    postProcessBeanDefinitionRegistry

        parser.parse(candidates) 从启动类开始解析各种注解(@PropertySource @ComponentScan @Import @ImportResource @Bean),加载配置类,在processImports(configClass, sourceClass, getImports(sourceClass), filter, true)中对启动类进行解析,加载其中的@Import注解的类。

    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();
    }
    
    protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
        processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
    }
    protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
        if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
            return;
        }
    
        ConfigurationClass existingClass = this.configurationClasses.get(configClass);
        if (existingClass != null) {
            if (configClass.isImported()) {
                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.
                this.configurationClasses.remove(configClass);
                this.knownSuperclasses.values().removeIf(configClass::equals);
            }
        }
    
        // Recursively process the configuration class and its superclass hierarchy.
        SourceClass sourceClass = asSourceClass(configClass, filter);
        do {
            sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
        }
        while (sourceClass != null);
    
        this.configurationClasses.put(configClass, configClass);
    }
    
    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
            processMemberClasses(configClass, sourceClass, filter);
        }
    
        // Process any @PropertySource annotations
        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
        // 对启动类下的所有 @ComponentScan 进行解析加载,包含(@RestController @Service等)
        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
                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)) {
                        parse(bdCand.getBeanClassName(), holder.getBeanName());
                    }
                }
            }
        }
    
        // Process any @Import annotations
        processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
    
        // Process any @ImportResource annotations
        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
        Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
        for (MethodMetadata methodMetadata : beanMethods) {
            configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
        }
    
        // Process default methods on interfaces
        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;
    }
    parse

        通过getImport(sourceClass) 解析启动类上的注解,获取到其中被@Import注解的类,即AutoConfigurationPackages、AutoConfigurationImportSelector。

        启动类上@SpringBootApplication注解为组合注解:

                   

        @SpringBootConfiguration:其实质是一个 @Configuration 注解,表明该类是一个配置类。

                     

        @EnableAutoConfiguration:开启了自动配置功能

                      

            @AutoConfigurationPackage:被该注解标注的类即主配置类,将主配置类所在的包当作base-package。

                 
        @ComponentScan:直接向容器中注入指定的组件

      在解析@Import注解时,会有一个getImports()方法,从启动类开始递归解析注解,把所有包含@Import的注解都解析到,然后再processImport()方法中对@Import注解的类进行分类,此处主要识别的是AutoConfigurationImportSelector 归属于ImportSelector的子类,在后续的过程中会调用 DeferredImprotSelectorHandler中的process()方法,来完成EnableAutoConfiguration的加载。

    private Set<SourceClass> getImports(SourceClass sourceClass) throws IOException {
        Set<SourceClass> imports = new LinkedHashSet<>();
        Set<SourceClass> visited = new LinkedHashSet<>();
        collectImports(sourceClass, imports, visited);
        return imports;
    }
        private void collectImports(SourceClass sourceClass, Set<SourceClass> imports, Set<SourceClass> visited)
            throws IOException {
    
        if (visited.add(sourceClass)) {
            for (SourceClass annotation : sourceClass.getAnnotations()) {
                String annName = annotation.getMetadata().getClassName();
                if (!annName.equals(Import.class.getName())) {
                    collectImports(annotation, imports, visited);
                }
            }
            imports.addAll(sourceClass.getAnnotationAttributes(Import.class.getName(), "value"));
        }
    }
    getImports

      执行this.deferredImportSelectorHandler.process()方法进行实现自动装配

    public void process() {
        List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
        this.deferredImportSelectors = null;
        try {
            if (deferredImports != null) {
                DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
                deferredImports.sort(DEFERRED_IMPORT_COMPARATOR);
                deferredImports.forEach(handler::register);
                handler.processGroupImports();
            }
        }
        finally {
            this.deferredImportSelectors = new ArrayList<>();
        }
    }
    
    // ConfigurationClassParser
    public void processGroupImports() {
        for (DeferredImportSelectorGrouping grouping : this.groupings.values()) {
            Predicate<String> exclusionFilter = grouping.getCandidateFilter();
            grouping.getImports().forEach(entry -> {
                ConfigurationClass configurationClass = this.configurationClasses.get(entry.getMetadata());
                try {
                    // 处理配置类上的注解
                    processImports(configurationClass, asSourceClass(configurationClass, exclusionFilter),
                            Collections.singleton(asSourceClass(entry.getImportClassName(), exclusionFilter)),
                            exclusionFilter, false);
                }
                catch (BeanDefinitionStoreException ex) {
                    throw ex;
                }
                catch (Throwable ex) {
                    throw new BeanDefinitionStoreException(
                            "Failed to process import candidates for configuration class [" +
                                    configurationClass.getMetadata().getClassName() + "]", ex);
                }
            });
        }
    }
    
    
    // DeferredImportSelectorGrouping
    public Iterable<Group.Entry> getImports() {
        for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {
            // 遍历DeferredImportSelectorHolder对象集合deferredImports,deferrdImports集合装了各种ImportSelector(AutoConfigurationImportSelect)
            this.group.process(deferredImport.getConfigurationClass().getMetadata(),
                    deferredImport.getImportSelector());
        }
        // 经过上面处理,然后再进行选择导入哪写配置类
        return this.group.selectImports();
    }
    //AutoConfigurationImportSelector
    public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
        Assert.state(deferredImportSelector instanceof AutoConfigurationImportSelector,
                () -> String.format("Only %s implementations are supported, got %s",
                        AutoConfigurationImportSelector.class.getSimpleName(),
                        deferredImportSelector.getClass().getName()));
        // 获取自动配置类放入 AutoConfigurationEntry 对象中
        AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
                .getAutoConfigurationEntry(annotationMetadata);
        // 将封装了自动配置类的 AutoConfigurationEntry 对象装进 autoConfigurationEntries 集合
        this.autoConfigurationEntries.add(autoConfigurationEntry);
        // 遍历刚获取的自动配置类
        for (String importClassName : autoConfigurationEntry.getConfigurations()) {
            // 将符合条件的自动配置类作为 key,annotationMetadata作为值放进 entries 集合中
            this.entries.putIfAbsent(importClassName, annotationMetadata);
        }
    }
    // AutoConfigurationImportSelector
    public Iterable<Entry> selectImports() {
        if (this.autoConfigurationEntries.isEmpty()) {
            return Collections.emptyList();
        }
                .getAutoConfigurationEntry(annotationMetadata);
        // 得到所有要排除的自动配置类集合
        Set<String> allExclusions = this.autoConfigurationEntries.stream()
                .map(AutoConfigurationEntry::getExclusions).flatMap(Collection::stream).collect(Collectors.toSet());
                .getAutoConfigurationEntry(annotationMetadata);
        // 得到经过过滤后所有符合条件的自动配置类集合
        Set<String> processedConfigurations = this.autoConfigurationEntries.stream()
                .map(AutoConfigurationEntry::getConfigurations).flatMap(Collection::stream)
                .collect(Collectors.toCollection(LinkedHashSet::new));
                .getAutoConfigurationEntry(annotationMetadata);
        // 移除需要排除的自动配置类
        processedConfigurations.removeAll(allExclusions);
    
                .getAutoConfigurationEntry(annotationMetadata);
        // 对标注有 @Order注解的自动配置类进行排序
        return sortAutoConfigurations(processedConfigurations, getAutoConfigurationMetadata()).stream()
                .map((importClassName) -> new Entry(this.entries.get(importClassName), importClassName))
                .collect(Collectors.toList());
    }
    
    private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
            Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
            boolean checkForCircularImports) {
    
        if (importCandidates.isEmpty()) {
            return;
        }
    
        if (checkForCircularImports && isChainedImportOnStack(configClass)) {
            this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
        }
        else {
            this.importStack.push(configClass);
            try {
                for (SourceClass candidate : importCandidates) {
                    if (candidate.isAssignable(ImportSelector.class)) {
                        // Candidate class is an ImportSelector -> delegate to it to determine imports
                        Class<?> candidateClass = candidate.loadClass();
                        ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
                                this.environment, this.resourceLoader, this.registry);
                        Predicate<String> selectorFilter = selector.getExclusionFilter();
                        if (selectorFilter != null) {
                            exclusionFilter = exclusionFilter.or(selectorFilter);
                        }
                        if (selector instanceof DeferredImportSelector) {
                            this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
                        }
                        else {
                            String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
                            Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
                            processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
                        }
                    }
                    else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
                        // Candidate class is an ImportBeanDefinitionRegistrar ->
                        // delegate to it to register additional bean definitions
                        Class<?> candidateClass = candidate.loadClass();
                        ImportBeanDefinitionRegistrar registrar =
                                ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
                                        this.environment, this.resourceLoader, this.registry);
                        configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
                    }
                    else {
                        // Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
                        // process it as an @Configuration class
                        this.importStack.registerImport(
                                currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
                        processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
                    }
                }
            }
            catch (BeanDefinitionStoreException ex) {
                throw ex;
            }
            catch (Throwable ex) {
                throw new BeanDefinitionStoreException(
                        "Failed to process import candidates for configuration class [" +
                        configClass.getMetadata().getClassName() + "]", ex);
            }
            finally {
                this.importStack.pop();
            }
        }
    }
        
    View Code

      执行 this.reader.loadBeanDefinitions(configClasses) 对自动配置类进行生效,生成Bean对象。

     

    自动装配原理总结:

      1、当启动SpringBoot应用程序时,会创建 SpringApplication 对象,在对象的构造方法中进行某些参数的初始化工作,最主要的是判断当前应用程序的类型及初始化器和监听器,在这个过程中会加载整个应用程序的 META-INF/spring.factories 文件,将文件的内容保存到缓存中(Map<ClassLoader, Map<String, List<String>>> cache ),方便后续获取。

      2、SpringApplication对象创建完成后,开始执行run() 方法来完成整个启动。启动过程中最主要的是有两个方法:prepareContext()、refreshContext(),在这两个方法中完成了自动装配的核心功能。在其之前的处理逻辑中包含了上下文对象的创建,banner的打印等各个准备工作。

      3、在prepareContext()方法中主要完成的是对上下文对象的初始化操作,包含了属性值的设置(比如环境对象)。在整个过程中load()方法完成将当前启动类作为一个BeanDefinition注册到registry中,方便后续在进行BeanFactory调用执行时找到对应的主类,来完成对 @SpringBootApplication @EnableAutoConfiguration等注解的解析工作。

      4、在refreshContext()方法中会进行整个容器的刷新过程,会调用spring中的refresh()方法。refresh()中有13个关键方法,在自动装配过程中,会调用invokeBeanFactoryPostProcessors()方法主要是对 ConfigurationClassPostProcessor 类的处理,这是BeanDefinitionRegistryPostProcessor的子类,BeanDefinitionRegistryPostProcessor 是BeanFactoryPostProcessor 的子类,调用BeanDefinitionRegistryPostProcessor中的postProcessBeanDefinitionRegistry()方法,会解析@PropertySource @ComponentScans @ComponentScan @Bean @Import等注解。

      5、在解析@Import注解时,会有一个getImports()方法,从启动类开始递归解析注解,把所有包含@Import的注解都解析到,然后再processImport()方法中对@Import注解的类进行分类,此处主要识别的是AutoConfigurationImportSelector 归属于ImportSelector的子类,在后续的过程中会调用 DeferredImprotSelectorHandler中的process()方法,来完成EnableAutoConfiguration的加载。

  • 相关阅读:
    基于视觉显著性的车载单目相机自运动估计及前车尺度估计方法
    线段树 模板 Java语言版
    2000-2021年全国各省水土流失治理面积数据
    python 数据结构之字典
    183. 从不订购的客户—not in()、左连接
    Java笔记:手写spring之ioc
    Cytoscape 安装教程 | Network Data Integration, Analysis, and Visualization in a Box
    IDEA插件开发(11)---插件配置文件
    python staticmethod和classmethod的作用与区别
    深入分析 Java对象进入老年代的四种方式
  • 原文地址:https://www.cnblogs.com/sunnyLee/p/15915814.html