spring boot @SpringBootApplication @EnableAutoConfiguration 的工作原理

在spring boot中@SpringBootApplication、@EnableAutoConfiguration是最常见Annotation,且最为重要,所以本文将展开对此的解读。@SpringBootApplication在spring框架中的处理尤为复杂,然后能将它的来龙去脉(加载机制)讲清楚的文章非常少。说实话你要完全理解及解读它,需要对spring 3.x的源码有一定程度了解,主要是它在原有的基础上拓展了一些新概念,如若不按本文的思路,稍有不慎就会陷入代码的海洋里不能自拔。

目录

1. SpringApplication

1.1 SpringFactoriesLoader

1.2 ApplicationListener

1.3 ApplicationContextInitializer

1.4 SpringApplication.run

1.5 SpringApplicationRunListeners和SpringApplicationRunListener

2. AbstractApplicationContext.refresh

2.1 BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor和BeanPostProcessor

2.2 ConfigurationClassPostProcessor

2.4 AnnotationConfigServletWebServerApplicationContext

2.5 ConfigurationClassParser

3. EnableAutoConfiguration

3.1 ImportSelector


@SpringBootApplication(scanBasePackages = {"com.example"})
public class WebApp {
    public static void main(String[] args) {
        SpringApplication.run(WebApp.class, args);
    }
}

首问:@SpringBootApplication是如何被解析并加载到spring ioc中的?

1. SpringApplication

在之前的文章“容器启动原理揭秘”中提到过,最终通过 JarLauncher.launch 运行的目标是 WebApp.main 方法,之后就没有再深入的讲。首先进入视野的拦路虎就是SpringApplication,可以理解为它相当于spring的外观模式,集各功能于一身,它也给用户提供了链式语法支持-Builder模式(SpringApplicationBuilder().sources(Parent.class).child(Application.class)..run(args))。

public class SpringApplication {
    //入口
    public static ConfigurableApplicationContext run(Class primarySource, String... args) {
        return run(new Class[]{primarySource}, args);
    }
    public static ConfigurableApplicationContext run(Class[] primarySources, String[] args) {
        return (new SpringApplication(primarySources)).run(args);
    }
    public SpringApplication(Class... primarySources) {
        this((ResourceLoader)null, primarySources);
    }
    public SpringApplication(ResourceLoader resourceLoader, Class... primarySources) {
        this.sources = new LinkedHashSet();
        this.bannerMode = Mode.CONSOLE;
        this.logStartupInfo = true;
        this.addCommandLineProperties = true;
        this.headless = true;
        this.registerShutdownHook = true;
        this.additionalProfiles = new HashSet();
        this.isCustomEnvironment = false;
        this.resourceLoader = resourceLoader;
        Assert.notNull(primarySources, "PrimarySources must not be null");
        this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
        // 判断web类型为reactive、none、servlet(只要可以加载Servlet或ConfigurableWebApplicationContext),当前为servlet
        this.webApplicationType = this.deduceWebApplicationType();
        //从SpringFactoriesLoader中加载ApplicationContextInitializer类,并实例化
        this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
        //从SpringFactoriesLoader中加载ApplicationListener类,并实例化
        this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
        //这个是很重要的属性:WebApp 
        this.mainApplicationClass = this.deduceMainApplicationClass();
    }
}

你可能会问:SpringFactoriesLoader是什么鬼?ApplicationContextInitializer和ApplicationListener又是什么东西?

1.1 SpringFactoriesLoader

SpringFactoriesLoader 在spring boot中非常重要,它是spring对SPI的实现版本,主要是从jar中META-INF/spring.factories读取拓展配置信息。在spring boot框架中有两个核心的 jar,它内置的 spring.factories 非常重要(使用者一般很少关注),而一般功能进行拓展也基于此:

spring-boot-2.0.5.RELEASE.jar/META-INF/spring.factories

# PropertySource Loaders
org.springframework.boot.env.PropertySourceLoader=\
org.springframework.boot.env.PropertiesPropertySourceLoader,\
org.springframework.boot.env.YamlPropertySourceLoader

# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener

# Error Reporters
org.springframework.boot.SpringBootExceptionReporter=\
org.springframework.boot.diagnostics.FailureAnalyzers

# Application Context Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
org.springframework.boot.context.ContextIdApplicationContextInitializer,\
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer

# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.ClearCachesApplicationListener,\
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
org.springframework.boot.context.FileEncodingApplicationListener,\
org.springframework.boot.context.config.AnsiOutputApplicationListener,\

spring-boot-autoconfigure-2.0.5.RELEASE.jar/META-INF/spring.factories

# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener

# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.autoconfigure.BackgroundPreinitializer

# Auto Configuration Import Listeners
org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\
org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener

# Auto Configuration Import Filters
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
org.springframework.boot.autoconfigure.condition.OnClassCondition

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\

SpringFactoriesLoader 源码其实也不复杂,这里不再赘述。

public abstract class SpringFactoriesLoader {
    public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
    private static final Map> cache = new ConcurrentReferenceHashMap();
    public static  List loadFactories(Class factoryClass, @Nullable ClassLoader classLoader) {
        Assert.notNull(factoryClass, "'factoryClass' must not be null");
        ClassLoader classLoaderToUse = classLoader;
        if (classLoader == null) {
            classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
        }

        List factoryNames = loadFactoryNames(factoryClass, classLoaderToUse);
        if (logger.isTraceEnabled()) {
            logger.trace("Loaded [" + factoryClass.getName() + "] names: " + factoryNames);
        }

        List result = new ArrayList(factoryNames.size());
        Iterator var5 = factoryNames.iterator();

        while(var5.hasNext()) {
            String factoryName = (String)var5.next();
            result.add(instantiateFactory(factoryName, factoryClass, classLoaderToUse));
        }

        AnnotationAwareOrderComparator.sort(result);
        return result;
    }
}

1.2 ApplicationListener

ApplicationListener 就是Spring的事件监听器,最重要的方法就是 onApplicationEvent,而事件源就是spring的广播组件(SimpleApplicationEventMulticaster),所有监听器通过 SpringFactoriesLoader 获取

spring boot @SpringBootApplication @EnableAutoConfiguration 的工作原理_第1张图片

//事件监听器
@FunctionalInterface
public interface ApplicationListener extends EventListener {
    void onApplicationEvent(E var1);
}
//广播事件
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
    public void multicastEvent(ApplicationEvent event) {
        this.multicastEvent(event, this.resolveDefaultEventType(event));
    }
    //添加监听器
    public void addApplicationListener(ApplicationListener listener) {
        Object var2 = this.retrievalMutex;
        synchronized(this.retrievalMutex) {
            Object singletonTarget = AopProxyUtils.getSingletonTarget(listener);
            if (singletonTarget instanceof ApplicationListener) {
                this.defaultRetriever.applicationListeners.remove(singletonTarget);
            }

            this.defaultRetriever.applicationListeners.add(listener);
            this.retrieverCache.clear();
        }
    }
}
//较重要的监听器实现类
public class BackgroundPreinitializer implements ApplicationListener {
    public void onApplicationEvent(SpringApplicationEvent event) {
        //如果是首次触发ApplicationStartingEvent时执行
        if (event instanceof ApplicationStartingEvent && preinitializationStarted.compareAndSet(false, true)) {
            this.performPreinitialization();
        }

        if ((event instanceof ApplicationReadyEvent || event instanceof ApplicationFailedEvent) && preinitializationStarted.get()) {
            try {
                preinitializationComplete.await();
            } catch (InterruptedException var3) {
                Thread.currentThread().interrupt();
            }
        }
    }
    private void performPreinitialization() {
        try {
            Thread thread = new Thread(new Runnable() {
                public void run() {
                    this.runSafely(new BackgroundPreinitializer.ConversionServiceInitializer());
                    this.runSafely(new BackgroundPreinitializer.ValidationInitializer());
                    this.runSafely(new BackgroundPreinitializer.MessageConverterInitializer());
                    this.runSafely(new BackgroundPreinitializer.MBeanFactoryInitializer());
                    this.runSafely(new BackgroundPreinitializer.JacksonInitializer());
                    this.runSafely(new BackgroundPreinitializer.CharsetInitializer());
                    BackgroundPreinitializer.preinitializationComplete.countDown();
                }
                public void runSafely(Runnable runnable) {
                    try {
                        runnable.run();
                    } catch (Throwable var3) {
                        ;
                    }

                }
            }, "background-preinit");
            thread.start();
        } catch (Exception var2) {
            preinitializationComplete.countDown();
        }
    }
}

题外话,BackgroundPreinitializer 把耗时的操作采用这种模式(事件+多线程)来实现,足以可见spring的设计功底。

1.3 ApplicationContextInitializer

ApplicationContextInitializer 是 ConfigurableApplicationContext(继承自ApplicationContext) 实例后的上下文初始化组件,它主要可以向 applicationContext 注入一些新的bean、修改 applicationContext 基本信息等,核心方法是 initialize,所有实现类通过 SpringFactoriesLoader 获取

public interface ApplicationContextInitializer {
    void initialize(C var1);
}

spring提供的实现非常多,比如:ContextIdApplicationContextInitializer,它实现applicationContext.setId(contextId.getId())

spring boot @SpringBootApplication @EnableAutoConfiguration 的工作原理_第2张图片

1.4 SpringApplication.run

其实 SpringApplication.run 整体还不算特别复杂,关键的方法有 prepareContext refreshContext会比较绕。当然这里面有一个出现的频率非常高的对象 SpringApplicationRunListeners (读源码就是这样,要解决痛点),那它是干什么的?继续向下看吧!

public class SpringApplication {
    //真正的入口
    public ConfigurableApplicationContext run(String... args) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        ConfigurableApplicationContext context = null;
        Collection exceptionReporters = new ArrayList();
        this.configureHeadlessProperty();
        //下面专门解释
        SpringApplicationRunListeners listeners = this.getRunListeners(args);
        //触发ApplicationStartingEvent
        listeners.starting();

        Collection exceptionReporters;
        try {
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            //获取配置对象
            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
            //向environment添加新配置
            this.configureIgnoreBeanInfo(environment);
            //打印spring boot的Banner
            Banner printedBanner = this.printBanner(environment);
            //根据webApplicationType类型获取applicationContext,当前为AnnotationConfigServletWebServerApplicationContext
            context = this.createApplicationContext();
            //异常汇总报告
            exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
            //向applicationContext中填充信息(environment、调用ApplicationContextInitializer、注入新bean)
            this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
            //刷新application
            this.refreshContext(context);
            //无任何实现
            this.afterRefresh(context, applicationArguments);
            stopWatch.stop();
            if (this.logStartupInfo) {
                //打印日志
                (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
            }
            //触发ApplicationStartedEvent
            listeners.started(context);
            //调用ioc中所有ApplicationRunner.run和CommandLineRunner.run
            this.callRunners(context, applicationArguments);
        } catch (Throwable var10) {
            this.handleRunFailure(context, var10, exceptionReporters, listeners);
            throw new IllegalStateException(var10);
        }
        try {
            //触发ApplicationReadyEvent
            listeners.running(context);
            return context;
        } catch (Throwable var9) {
            this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
            throw new IllegalStateException(var9);
        }
    }
    private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) {
        ConfigurableEnvironment environment = this.getOrCreateEnvironment();  
        this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs());
        //触发ApplicationEnvironmentPreparedEvent
        listeners.environmentPrepared((ConfigurableEnvironment)environment);
        this.bindToSpringApplication((ConfigurableEnvironment)environment);
        if (!this.isCustomEnvironment) {
            //根据webApplicationType类型获取配置对象(环境信息、profile),当前为StandardServletEnvironment
            environment = (new EnvironmentConverter(this.getClassLoader())).convertEnvironmentIfNecessary((ConfigurableEnvironment)environment, this.deduceEnvironmentClass());
        }

        ConfigurationPropertySources.attach((Environment)environment);
        return (ConfigurableEnvironment)environment;
    }
    private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
        context.setEnvironment(environment);
        //注入beanNameGenerator、设置ResourceLoader
        this.postProcessApplicationContext(context);
        //调用所有的初始化组件(ApplicationContextInitializer)
        this.applyInitializers(context);
        //无任何实现
        listeners.contextPrepared(context);
        if (this.logStartupInfo) {
            //打印getApplicationLog()信息
            this.logStartupInfo(context.getParent() == null);
            // 打印Profile信息
            this.logStartupProfileInfo(context);
        }
        //ioc容器保存应用程序启动参数(String[] args)信息
        context.getBeanFactory().registerSingleton("springApplicationArguments", applicationArguments);
        if (printedBanner != null) {
            //ioc容器保存Banner信息
            context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);
        }
        
        Set sources = this.getAllSources();
        Assert.notEmpty(sources, "Sources must not be empty");
        //把启动类(WebApp )注入到Ioc容器中,调用BeanDefinitionLoader.load
        this.load(context, sources.toArray(new Object[0]));
        //触发ApplicationPreparedEvent
        listeners.contextLoaded(context);
    }
    private void refreshContext(ConfigurableApplicationContext context) {
        //调用AbstractApplicationContext.refresh(后面专门讲)
        this.refresh(context);
        //添加钩子函数
        if (this.registerShutdownHook) {
            try {
                context.registerShutdownHook();
            } catch (AccessControlException var3) {
                ;
            }
        }
    }
}
class BeanDefinitionLoader {
    //prepareContext方法中this.load最终会执行到这里
    private int load(Class source) {
        if (this.isGroovyPresent() && BeanDefinitionLoader.GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
            BeanDefinitionLoader.GroovyBeanDefinitionSource loader = (BeanDefinitionLoader.GroovyBeanDefinitionSource)BeanUtils.instantiateClass(source, BeanDefinitionLoader.GroovyBeanDefinitionSource.class);
            this.load(loader);
        }
        //WebApp类符合条件
        if (this.isComponent(source)) {
            this.annotatedReader.register(new Class[]{source});
            return 1;
        } else {
            return 0;
        }
    }
} 
  

到这里你感觉是结束了!

这好像并没看到spring是如何处理 SpringBootApplication、EnableAutoConfiguration 相关的逻辑啊?

如果你真正调试,你会发现一个这样现象:

  • 未执行refreshContext方法前,applicationContext (Ioc容器)好像注入的的bean非常少,其中一个就是WebApp对象
  • 执行refreshContext之后,applicationContext (Ioc容器)里什么都有了,的确是 SpringBootApplication、EnableAutoConfiguration 生效了

是的,这发现很重要!!至少知道 refreshContext (就是 AbstractApplicationContext.refresh)是突破口!!

1.5 SpringApplicationRunListeners和SpringApplicationRunListener

SpringApplicationRunListeners 管理着 applicationContext  初始化、实例化、启动运行的各个阶段,它最重要的职责就是通过事件驱动与外界的联系。SpringApplicationRunListener是通过 SpringFactoriesLoader 获取的,它定义了applicationContext  的各个阶段及其实现(EventPublishingRunListener ),EventPublishingRunListener的特点是事件驱动,它通过事件广播组件SimpleApplicationEventMulticaster与外界交换。

class SpringApplicationRunListeners {
    SpringApplicationRunListeners(Log log, Collection listeners) {
        this.log = log;
        //通过SpringApplicationRunListener
        this.listeners = new ArrayList(listeners);
    }
    public void starting() {
        Iterator var1 = this.listeners.iterator();
        //调用所有的SpringApplicationRunListener.starting
        while(var1.hasNext()) {
            SpringApplicationRunListener listener = (SpringApplicationRunListener)var1.next();
            listener.starting();
        }
    }
    public void started(ConfigurableApplicationContext context) {
        Iterator var2 = this.listeners.iterator();
        while(var2.hasNext()) {
            SpringApplicationRunListener listener = (SpringApplicationRunListener)var2.next();
            listener.started(context);
        }
    }
}
//SpringApplicationRunListener是通过SpringFactoriesLoader获取的
private SpringApplicationRunListeners getRunListeners(String[] args) {
    Class[] types = new Class[]{SpringApplication.class, String[].class};
    return new SpringApplicationRunListeners(logger, this.getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
}
//applicationContext的各个阶段
public interface SpringApplicationRunListener {
    void starting();//启动中
    void environmentPrepared(ConfigurableEnvironment environment);//环境变量初始化
    void contextPrepared(ConfigurableApplicationContext context);//上下文准备
    void contextLoaded(ConfigurableApplicationContext context);
    void started(ConfigurableApplicationContext context);
    void running(ConfigurableApplicationContext context);
    void failed(ConfigurableApplicationContext context, Throwable exception);//失败
}
//支持事件驱动的SpringApplicationRunListener的实现
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {
    public EventPublishingRunListener(SpringApplication application, String[] args) {
        this.application = application;
        this.args = args;
        //事件广播组件
        this.initialMulticaster = new SimpleApplicationEventMulticaster();
        Iterator var3 = application.getListeners().iterator();

        while(var3.hasNext()) {
            ApplicationListener listener = (ApplicationListener)var3.next();
            this.initialMulticaster.addApplicationListener(listener);
        }

    }
    public void starting() {
        //发事件
        this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
    }
    public void environmentPrepared(ConfigurableEnvironment environment) {
        this.initialMulticaster.multicastEvent(new ApplicationEnvironmentPreparedEvent(this.application, this.args, environment));
    }
    public void contextLoaded(ConfigurableApplicationContext context) {
        ApplicationListener listener;
        for(Iterator var2 = this.application.getListeners().iterator(); var2.hasNext(); context.addApplicationListener(listener)) {
            listener = (ApplicationListener)var2.next();
            if (listener instanceof ApplicationContextAware) {
                ((ApplicationContextAware)listener).setApplicationContext(context);
            }
        }
        //发事件
        this.initialMulticaster.multicastEvent(new ApplicationPreparedEvent(this.application, this.args, context));
    }
    public void started(ConfigurableApplicationContext context) {
        //发事件
        context.publishEvent(new ApplicationStartedEvent(this.application, this.args, context));
    }
}

2. AbstractApplicationContext.refresh

AbstractApplicationContext.refresh 是非常复杂的,为避免知识点无限延伸,和本文主题相关性不大的东西不展开探讨。

public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {    
    public void refresh() throws BeansException, IllegalStateException {
        Object var1 = this.startupShutdownMonitor;
        synchronized(this.startupShutdownMonitor) {
            //设置this.startupDate、this.closed=true,this.active=true,initPropertySources()、validateRequiredProperties()
            this.prepareRefresh();
            /**通知子类刷新内部的bean factory,主要分为两步:
             * refreshBeanFactory(进行真正的配置加载,xml是在这一步解析的,读取注册的regular bean)
             * 获取beanFactory
             */
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
            /**配置beanFactory标准的上下文特性,非常复杂
             * set:classLoader
             * set:StandardBeanExpressionResolver (spring EL)
             * addBeanPostProcessor:ApplicationContextAwareProcessor(BeanPostProcessor提供set各种aware)
             * addBeanPostProcessor:ApplicationListenerDetector(ApplicationListener处理)
             * ignoreDependencyInterface、registerResolvableDependency
             */
            this.prepareBeanFactory(beanFactory);

            try {
                //在子类中,允许对beanFactory进行后期处理
                this.postProcessBeanFactory(beanFactory);
                //执行BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor,后面专门讲            
                this.invokeBeanFactoryPostProcessors(beanFactory);
                /**添加实例化的后置处理器,并对所有的进行排序
                 * BeanPostProcessorChecker
                 * ApplicationListenerDetector
                **/               
                this.registerBeanPostProcessors(beanFactory);
                //初始化国际化服务
                this.initMessageSource();
                //创建事件广播器
                this.initApplicationEventMulticaster();
                //在子类中实现
                this.onRefresh();
                /**注册一部分给出的事件监听器,
                 * addApplicationListenerBean:只添加监听器的名字(留待bean实例化完成后再注册)
                **/
                this.registerListeners();
                //单例模式的bean的实例化、成员变量注入、初始化等工作都在此完成
                this.finishBeanFactoryInitialization(beanFactory);
                /**applicationContext刷新完成后的处理
                 * initLifecycleProcessor()
                 * this.getLifecycleProcessor().onRefresh
                 * this.publishEvent(new ContextRefreshedEvent(this));
                **/
                this.finishRefresh();
            } catch (BeansException var9) {
                if (this.logger.isWarnEnabled()) {
                    this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
                }
                //刷新失败后的处理,主要是将一些保存环境信息的集合做清理
                this.destroyBeans();
                //applicationContext是否已经激活的标志,设置为false
                this.cancelRefresh(var9);
                throw var9;
            } finally {
                this.resetCommonCaches();
            }

        }
    }
}

这里有一点基本上可以确认了:refresh调用方法invokeBeanFactoryPostProcessors(beanFactory)

其实这里有一个疑问:regular bean是什么?BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor有什么区别及联系?

2.1 BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor和BeanPostProcessor

ConfigurationClassPostProcessor(其实是个BeanDefinitionRegistryPostProcessor,之前的文章讲过)今天的主角,处理spring-boot中的SpringBootApplication ,

//AbstractApplicationContext.invokeBeanFactoryPostProcessors的入口
final class PostProcessorRegistrationDelegate {
	//里面处理很复杂,但英文注释已经足够了解很多的情况了
	public static void invokeBeanFactoryPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors) {

		// Invoke BeanDefinitionRegistryPostProcessors first, if any.
		Set processedBeans = new HashSet<>();

		if (beanFactory instanceof BeanDefinitionRegistry) {
			BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
			List regularPostProcessors = new ArrayList<>();
			List 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 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);
			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);
			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);
				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 priorityOrderedPostProcessors = new ArrayList<>();
		List orderedPostProcessorNames = new ArrayList<>();
		List 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 orderedPostProcessors = new ArrayList<>();
		for (String postProcessorName : orderedPostProcessorNames) {
			orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		sortPostProcessors(orderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

		// Finally, invoke all other BeanFactoryPostProcessors.
		List nonOrderedPostProcessors = new ArrayList<>();
		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();
	}
}

2.2 ConfigurationClassPostProcessor

前面讲过ConfigurationClassPostProcessor实是个BeanDefinitionRegistryPostProcessor。还是看源码吧,其实不需要所有的地方都懂,有注释的地方看懂就能了解今天的真相。

public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
		PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		int factoryId = System.identityHashCode(beanFactory);
		if (this.factoriesPostProcessed.contains(factoryId)) {
			throw new IllegalStateException(
					"postProcessBeanFactory already called on this post-processor against " + beanFactory);
		}
		this.factoriesPostProcessed.add(factoryId);
		if (!this.registriesPostProcessed.contains(factoryId)) {
			// BeanDefinitionRegistryPostProcessor hook apparently not supported...
			// Simply call processConfigurationClasses lazily at this point then.
			//看这里啊,英文解释很明确,处理Configuration类
			processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
		}
		enhanceConfigurationClasses(beanFactory);
		beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
	}
	public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
		List configCandidates = new ArrayList<>();
		String[] candidateNames = registry.getBeanDefinitionNames();
		//从ioc中找到有spring注解的bean
		for (String beanName : candidateNames) {
			BeanDefinition beanDef = registry.getBeanDefinition(beanName);
			if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
					ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
				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;
		}
		...
		// Parse each @Configuration class
		// ConfigurationClassParser 后面具体讲
		ConfigurationClassParser parser = new ConfigurationClassParser(
				this.metadataReaderFactory, this.problemReporter, this.environment,
				this.resourceLoader, this.componentScanBeanNameGenerator, registry);

		Set candidates = new LinkedHashSet<>(configCandidates);
		Set alreadyParsed = new HashSet<>(configCandidates.size());
		do {
			parser.parse(candidates);
			parser.validate();
		...
	}
}

那新的问题来了:

  • ConfigurationClassPostProcessor是什么时候注入到spring ioc中的呢?
  • ConfigurationClassParser又是什么呢?

2.4 AnnotationConfigServletWebServerApplicationContext

在上面我们讲过SpringApplication.createApplicationContext(),最终得到的是AnnotationConfigServletWebServerApplicationContext,看源码吧

public class AnnotationConfigServletWebServerApplicationContext extends ServletWebServerApplicationContext implements AnnotationConfigRegistry {
    public AnnotationConfigServletWebServerApplicationContext() {
        this.annotatedClasses = new LinkedHashSet();
        //reader 这个对象很关键
        this.reader = new AnnotatedBeanDefinitionReader(this);
        this.scanner = new ClassPathBeanDefinitionScanner(this);
    }
}
public class AnnotatedBeanDefinitionReader {
	public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
		this(registry, getOrCreateEnvironment(registry));
	}
	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);
		//它注入了一些BeanFactoryPostProcessor
		AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
	}
}
public class AnnotationConfigUtils {
	public static Set 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 beanDefs = new LinkedHashSet<>(8);

		if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			//看这里,就是spring boot注解处理类
			RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			//Autowired注解处理类
			RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			//Required注解处理类
			RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
		if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

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

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

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

		return beanDefs;
	}
}

2.5 ConfigurationClassParser

ConfigurationClassParser是spring boot真正的配置类解析器,当然入口方法是parse。

class ConfigurationClassParser {
	public void parse(Set configCandidates) {
		this.deferredImportSelectors = new LinkedList<>();
		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);
			}
		}
		processDeferredImportSelectors();
	}
	//ImportSelector后续专门讲
	private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
			Collection importCandidates, 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) {
					//对ImportSelector的处理
					if (candidate.isAssignable(ImportSelector.class)) {
						// Candidate class is an ImportSelector -> delegate to it to determine imports
						Class candidateClass = candidate.loadClass();
						//实例化selector
						ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
						//							
						ParserStrategyUtils.invokeAwareMethods(
								selector, this.environment, this.resourceLoader, this.registry);
						if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {
							//如果为延迟导入处理则加入集合当中
							this.deferredImportSelectors.add(
									new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector));
						}
						else {
   							//根据ImportSelector方法的返回值来进行递归操作
							String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
							Collection importSourceClasses = asSourceClasses(importClassNames);
							processImports(configClass, currentSourceClass, importSourceClasses, 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 =
								BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
						ParserStrategyUtils.invokeAwareMethods(
								registrar, this.environment, this.resourceLoader, this.registry);
						configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
					}
					else {
						// 如果当前的类既不是ImportSelector也不是ImportBeanDefinitionRegistar就进行@Configuration的解析处理
						// 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));
					}
				}
			}
			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();
			}
		}
	}
	//处理spring各种注解类
	protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
			throws IOException {
		// 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.warn("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
						"]. Reason: Environment must implement ConfigurableEnvironment");
			}
		}
		// Process any @ComponentScan annotations
		Set 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 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), true);
		// Process any @ImportResource annotations
		AnnotationAttributes importResource =
				AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
		if (importResource != null) {
			String[] resources = importResource.getStringArray("locations");
			Class readerClass = importResource.getClass("reader");
			for (String resource : resources) {
				String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
				configClass.addImportedResource(resolvedResource, readerClass);
			}
		}
		// Process individual @Bean methods
		Set 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;
	}
}

那最剩下最后一个问题:ImportSelector又是什么呢?

3. EnableAutoConfiguration

个人感觉@EnableAutoConfiguration这个Annotation最为重要,所以放在最后来解读,大家是否还记得Spring框架提供的各种名字为@Enable开头的Annotation定义?比如@EnableScheduling、@EnableCaching、@EnableMBeanExport等,@EnableAutoConfiguration的理念和做事方式其实一脉相承、

简单概括一下就是,借助@Import的支持,收集和注册特定场景相关的bean定义。

  • @EnableScheduling是通过@Import将Spring调度框架相关的bean定义都加载到IoC容器。
  • @EnableMBeanExport是通过@Import将JMX相关的bean定义加载到IoC容器。

而@EnableAutoConfiguration也是借助@Import的帮助,将所有符合自动配置条件的bean定义加载到IoC容器,仅此而已!

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

    Class[] exclude() default {};

    String[] excludeName() default {};
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({Registrar.class})
public @interface AutoConfigurationPackage {
}
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
    Registrar() {
    }
    public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
        AutoConfigurationPackages.register(registry, (new AutoConfigurationPackages.PackageImport(metadata)).getPackageName());
    }
    public Set determineImports(AnnotationMetadata metadata) {
        return Collections.singleton(new AutoConfigurationPackages.PackageImport(metadata));
    }
}
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        if (!this.isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        } else {
            AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
            AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
            List configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
            configurations = this.removeDuplicates(configurations);
            Set exclusions = this.getExclusions(annotationMetadata, attributes);
            this.checkExcludedClasses(configurations, exclusions);
            configurations.removeAll(exclusions);
            configurations = this.filter(configurations, autoConfigurationMetadata);
            //触发AutoConfigurationImportEvent
            this.fireAutoConfigurationImportEvents(configurations, exclusions);
            return StringUtils.toStringArray(configurations);
        }
    }
   //从spring.factories中EnableAutoConfiguration获取所有
   protected List getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
        List configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
        Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
        return configurations;
    }
} 
  

AutoConfigurationPackage它其实是注册了一个Bean的定义。new PackageImport(metadata).getPackageName(),它其实返回了当前主程序类的同级以及子级 的包组件。这也就是为什么,我们要把WebApp放在项目的最高级中。

3.1 ImportSelector

之前讲过ImportSelectorConfigurationClassParser调用,AutoConfigurationImportSelector 继承了 DeferredImportSelector 继承了 ImportSelector,有一个重要的方法为:selectImports就像一只“八爪鱼”一样,勾起spring-boot的强大配置库。

spring boot @SpringBootApplication @EnableAutoConfiguration 的工作原理_第3张图片

总结,SpringBootApplication注解是通过一个BeanDefinitionRegistryPostProcessor实现解析,在createApplicationContext()时被实例化并注入到Ioc中,在AbstractApplicationContext.refresh被调用PostProcessor。

你可能感兴趣的:(spring源码,玩转spring,cloud,spring,boot)