主要功能

  • 接受Configuration和Component标注的class,生成Bean
  • package扫描

注意AnnotationConfigServletWebServerApplicationContext只能接受class注册,不能接受xml注册,xml注册是在SpringApplication那里面处理的,SpringApplication负责解析xml并手动调用registerBeanDefinition注册到AnnotationConfigServletWebServerApplicationContext

Factory

	/**
	 * {@link ApplicationContextFactory} registered in {@code spring.factories} to support
	 * {@link AnnotationConfigServletWebServerApplicationContext}.
	 */
	static class Factory implements ApplicationContextFactory {

		@Override
		public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {
			return (webApplicationType != WebApplicationType.SERVLET) ? null
					: new AnnotationConfigServletWebServerApplicationContext();
		}

	}

Factory 会被写入spring.factory,这样AnnotationConfigServletWebServerApplicationContext就会生成。平时我们的web服务都是生成的这个。

Constructor

	/**
	 * Create a new {@link AnnotationConfigServletWebServerApplicationContext} that needs
	 * to be populated through {@link #register} calls and then manually
	 * {@linkplain #refresh refreshed}.
	 */
	public AnnotationConfigServletWebServerApplicationContext() {
		this.reader = new AnnotatedBeanDefinitionReader(this);
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}

在SpringApplication的分析那里我们已经知道SpringApplication只会注册一个BeanDefinition,那就是我们的mainClass。AnnotationConfigServletWebServerApplicationContext本身也是个BeanDefinitionRegistry,所以可以直接传给AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner。

Additional Component Candidates


	private final AnnotatedBeanDefinitionReader reader;

	private final ClassPathBeanDefinitionScanner scanner;

	private final Set<Class<?>> annotatedClasses = new LinkedHashSet<>();

	private String[] basePackages;
	@Override
	public final void register(Class<?>... annotatedClasses) {
		Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
		this.annotatedClasses.addAll(Arrays.asList(annotatedClasses));
	}
		@Override
	public final void scan(String... basePackages) {
		Assert.notEmpty(basePackages, "At least one base package must be specified");
		this.basePackages = basePackages;
	}
	@Override
	protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		super.postProcessBeanFactory(beanFactory);
		if (this.basePackages != null && this.basePackages.length > 0) {
			this.scanner.scan(this.basePackages);
		}
		if (!this.annotatedClasses.isEmpty()) {
			this.reader.register(ClassUtils.toClassArray(this.annotatedClasses));
		}
	}

可以看到,AnnotationConfigServletWebServerApplicationContext可以通过register() & scan()添加额外的需要扫描的class和package,但是,根据我们之前的分析, SpringApplication其实只是调用了一个org.springframework.context.support.GenericApplicationContext#registerBeanDefinition (GenericApplicationContext是AnnotationConfigServletWebServerApplicationContext的父父类)。所以annotatedClasses,和basePackages 其实都是空的。也就是没有被用到。但是一旦注册,就会在org.springframework.context.support.AbstractApplicationContext#refresh的postProcessBeanFactory阶段被调用到,随后被invokeBeanFactoryPostProcessors统一处理,比如cgiproxy等等。

Parent Class ServletWebServerApplicationContext

可以看到AnnotationConfigServletWebServerApplicationContext提供的额外的class注册和package扫描在实际使用过程中(SpringApplication)用到,所以我们继续查看它的父类。
主要功能:开启一个webServer并且注册Filter和Servlet。
1, 查找ServletWebServerFactory,并且初始化webserver,通常这个Factory就是ServletWebServerFactoryAutoConfiguration -》ServletWebServerFactoryConfiguration -》EmbeddedTomcat -》TomcatServletWebServerFactory
2, 创建mapping: Any Servlet named ‘dispatcherServlet’ will always be mapped to ‘/’. Filter beans will be mapped to all URLs (‘/*’).
3, 自定义配置:For more advanced configuration, the context can instead define beans that implement the ServletContextInitializer interface (most often ServletRegistrationBeans and/or FilterRegistrationBeans
4, 不建议单独使用:Although this context can be used directly, most developers should consider using the AnnotationConfigServletWebServerApplicationContext or XmlServletWebServerApplicationContext variants. 肯定也不会单独使用,还有Environment抽象这些功能呢,使用SpringApplication好一些。

postProcessBeanFactory

	protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		beanFactory.addBeanPostProcessor(new WebApplicationContextServletContextAwareProcessor(this));
		beanFactory.ignoreDependencyInterface(ServletContextAware.class);
		registerWebApplicationScopes();
	}

这时候父类还没有扫描Beans,所以可以添加bean以及对beanFactory做配置。
WebApplicationContextServletContextAwareProcessor: 注入 ServletContext
registerWebApplicationScopes: Register web-specific scopes (“request”, “session”, “globalSession”) with the given BeanFactory

顺便说一下SpringBoot的命名,postProcessBeanFactory意思就是在BeanFactory创建初始化以后马上再process。其实叫做configureBeanFactory不是更好?

创建webserver

	@Override
	public final void refresh() throws BeansException, IllegalStateException {
		try {
			super.refresh();
		}
		catch (RuntimeException ex) {
			WebServer webServer = this.webServer;
			if (webServer != null) {
				webServer.stop();
			}
			throw ex;
		}
	}

	@Override
	protected void onRefresh() {
		super.onRefresh();
		try {
			createWebServer();
		}
		catch (Throwable ex) {
			throw new ApplicationContextException("Unable to start web server", ex);
		}
	}
	private void createWebServer() {
		WebServer webServer = this.webServer;
		ServletContext servletContext = getServletContext();
		if (webServer == null && servletContext == null) {
			StartupStep createWebServer = this.getApplicationStartup().start("spring.boot.webserver.create");
			ServletWebServerFactory factory = getWebServerFactory();
			createWebServer.tag("factory", factory.getClass().toString());
			this.webServer = factory.getWebServer(getSelfInitializer());
			createWebServer.end();
			getBeanFactory().registerSingleton("webServerGracefulShutdown",
					new WebServerGracefulShutdownLifecycle(this.webServer));
			getBeanFactory().registerSingleton("webServerStartStop",
					new WebServerStartStopLifecycle(this, this.webServer));
		}
		else if (servletContext != null) {
			try {
				getSelfInitializer().onStartup(servletContext);
			}
			catch (ServletException ex) {
				throw new ApplicationContextException("Cannot initialize servlet context", ex);
			}
		}
		initPropertySources();
	}
	protected void initPropertySources() {
		ConfigurableEnvironment env = getEnvironment();
		if (env instanceof ConfigurableWebEnvironment) {
			((ConfigurableWebEnvironment) env).initPropertySources(this.servletContext, null);
		}
	}

refresh 啥也没干交给org.springframework.context.support.AbstractApplicationContext#refresh, 转而在refresh的钩子函数onRefresh里面创建webserver,此时beanFactory以及扫描并初始化完成Bean了。
createWebServer逻辑也很简单,就是获取TomcatWebServerFactory,生成一个webserver,注意此时的WebServer还没有Run起来,直到注册的WebServerStartStopLifecycle获取到Start回调,也就是ApplicationContext完成的时候,才会Run起来

initPropertySources:通过之前对SpringApplication的分析知道env 就是ApplicationServletEnvironment, 追踪代码至:

	public static void initServletPropertySources(MutablePropertySources sources,
			@Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) {

		Assert.notNull(sources, "'propertySources' must not be null");
		String name = StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME;
		if (servletContext != null && sources.get(name) instanceof StubPropertySource) {
			sources.replace(name, new ServletContextPropertySource(name, servletContext));
		}
		name = StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME;
		if (servletConfig != null && sources.get(name) instanceof StubPropertySource) {
			sources.replace(name, new ServletConfigPropertySource(name, servletConfig));
		}
	}

因为我们根本就没有配置额外的source,所以并不会起作用.

selfInitialize

	private void selfInitialize(ServletContext servletContext) throws ServletException {
		prepareWebApplicationContext(servletContext);
		registerApplicationScope(servletContext);
		WebApplicationContextUtils.registerEnvironmentBeans(getBeanFactory(), servletContext);
		for (ServletContextInitializer beans : getServletContextInitializerBeans()) {
			beans.onStartup(servletContext);
		}
	}
	protected void prepareWebApplicationContext(ServletContext servletContext) {
		Object rootContext = servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
		if (rootContext != null) {
			if (rootContext == this) {
				throw new IllegalStateException(
						"Cannot initialize context because there is already a root application context present - "
								+ "check whether you have multiple ServletContextInitializers!");
			}
			return;
		}
		servletContext.log("Initializing Spring embedded WebApplicationContext");
		try {
			servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this);
			if (logger.isDebugEnabled()) {
				logger.debug("Published root WebApplicationContext as ServletContext attribute with name ["
						+ WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]");
			}
			setServletContext(servletContext);
			if (logger.isInfoEnabled()) {
				long elapsedTime = System.currentTimeMillis() - getStartupDate();
				logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms");
			}
		}
		catch (RuntimeException | Error ex) {
			logger.error("Context initialization failed", ex);
			servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex);
			throw ex;
		}
	}

prepareWebApplicationContext: 其实就是把Tomcat生成的ServletContext设置到自己的servletContext里面,吧ApplicationContext设置到ServletContext的ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE属性上
registerApplicationScope: 增加Application类型的scope
registerEnvironmentBeans:就是注册servletContext, servletConfig等bean,说明这些bean不能autowire,因为这是在其他bean都注册完成之后再注册的了,只能通过ServletContextAware接口获得。

getServletContextInitializerBeans: 获取所有ServletContextInitializer 的bean并且调用。

ServletContextInitializerBeans

在上一步有一个很重要的步骤,就是获取ServletContextInitializerBeans并且初始化。就是在这里获取了所有的Servlet(包括DispatchServlet)和Filter并且注册到servletContext上面。

org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration.DispatcherServletRegistrationConfiguration --> org.springframework.boot.autoconfigure.web.servlet.DispatcherServletRegistrationBean --> org.springframework.boot.web.servlet.DynamicRegistrationBean --> ServletContextInitializer

说明DispatcherServletRegistrationBean 就是一个ServletContextInitializer, 它注册了DispatchServlet到“/”这个mapping。

Ancestor Class GenericWebApplicationContext

在GenericApplicationContext的基础上增加web服务的一些通用功能。主要是增加了servletContext及其相关操作。还有themeSource(没用到),大部分method要么被ServletWebServerApplicationContext覆盖,要么被ServletWebServerApplicationContext调用。
被覆盖:postProcessBeanFactory,initPropertySources
被调用:onRefresh,创建themeSource

Ancestor Class GenericApplicationContext

GenericApplicationContext是第一个可以实例化的的继承AbstractApplicationContext的类。
主要是提供了默认的BeanFactory实现:DefaultListableBeanFactory
以及加载resource的实现:getResource。 GenericApplicationContext的resourceLoader总是null,所以总是会逐级调用到org.springframework.core.io.DefaultResourceLoader#getResource
GenericWebApplicationContext只有一个BeanFactory所以只能refresh一次。这好像不是个什么缺陷?

Ancestor Class AbstractApplicationContext

所有的具体ApplicationContext都是AbstractApplicationContext的子类,相当于所有ApplicationContext的模板父类。

  • 实现了refresh的逻辑,子类可以实现onFresh等回调函数
  • 自动检测并处理 BeanFactoryPostProcessors, BeanPostProcessors, and ApplicationListeners
  • 实现SimpleApplicationEventMulticaster for事件发布
  • getResourceByPath默认使用classpath

重要的内置bean(不存在就创建):messageSource, lifecycleProcessor,applicationEventMulticaster

重要变量:

private final List<BeanFactoryPostProcessor> beanFactoryPostProcessors = new ArrayList<>();
	@Override
	public void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor) {
		Assert.notNull(postProcessor, "BeanFactoryPostProcessor must not be null");
		this.beanFactoryPostProcessors.add(postProcessor);
	}

beanFactoryPostProcessors 并没有明显的的被调用,但是org.springframework.boot.SpringApplication#applyInitializers会读取spring.factories里面的ApplicationContextInitializer,比如

# 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.rsocket.context.RSocketPortInfoApplicationContextInitializer,\
org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer

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

DelegatingApplicationContextInitializer: 他会读取环境变量中context.initializer.classes的内容,然后初始化并调用对应的initializer。
SharedMetadataReaderFactoryContextInitializer: 他会调用applicationContext.addBeanFactoryPostProcessor(postProcessor);
我们可以SpringApplication.addInitializers添加自己的的initializer,也就可以添加addBeanFactoryPostProcessor。

Refresh

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

			// Prepare this context for refreshing.
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

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

			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				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.
				onRefresh();

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

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

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

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

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

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

				// Propagate exception to caller.
				throw ex;
			}

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

prepareRefresh:只是设置isActive等几个变量,暂时看不出作用
obtainFreshBeanFactory: 得到DefaultListableBeanFactory,这是在GenericApplicationContext定义并且重载了getBeanFactory

prepareBeanFactory:

	protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		// Tell the internal bean factory to use the context's class loader etc.
		beanFactory.setBeanClassLoader(getClassLoader());
		if (!shouldIgnoreSpel) {
			beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
		}
		beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

		// Configure the bean factory with context callbacks.
		beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
		beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
		beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
		beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
		beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationStartupAware.class);

		// BeanFactory interface not registered as resolvable type in a plain factory.
		// MessageSource registered (and found for autowiring) as a bean.
		beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
		beanFactory.registerResolvableDependency(ResourceLoader.class, this);
		beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
		beanFactory.registerResolvableDependency(ApplicationContext.class, this);

		// Register early post-processor for detecting inner beans as ApplicationListeners.
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

		// Detect a LoadTimeWeaver and prepare for weaving, if found.
		if (!NativeDetector.inNativeImage() && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			// Set a temporary ClassLoader for type matching.
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}

		// Register default environment beans.
		if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
		}
		if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
		}
		if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
		}
		if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
			beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
		}
	}

1, 配置众多aware接口
2, BeanFactory自动注入beanFactory, ResourceLoader,ApplicationEventPublisher,ApplicationContext其实都是注入当前的ApplicationContext,也就是AnnotationConfigServletWebServerApplicationContext实例(this)
3,注册ENVIRONMENT_BEAN_NAME,SYSTEM_PROPERTIES_BEAN_NAME, SYSTEM_ENVIRONMENT_BEAN_NAME, APPLICATION_STARTUP_BEAN_NAME四个bean
注意registerResolvableDependency和registerSingleton的区别,registerSingleton是会注入到beanFactory的,可以通过依赖查找获得,但是registerResolvableDependency不注入beanFactory,只能通过依赖注入获得。

postProcessBeanFactory:
空函数,留给子类实现,比如AnnotationConfigServletWebServerApplicationContext就实现了

	@Override
	protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		super.postProcessBeanFactory(beanFactory);
		if (this.basePackages != null && this.basePackages.length > 0) {
			this.scanner.scan(this.basePackages);
		}
		if (!this.annotatedClasses.isEmpty()) {
			this.reader.register(ClassUtils.toClassArray(this.annotatedClasses));
		}
	}

invokeBeanFactoryPostProcessors:调用所有的BeanFactoryPostProcessor以及子类BeanDefinitionRegistryPostProcessor。
registerBeanPostProcessors:与invokeBeanFactoryPostProcessors唯一不同的是,registerBeanPostProcessors从beanFactory里面获取String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);并且交给beanFactory去处理,而不是在这里处理。
registerListeners: 从beanFactory里面获取String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);

finishBeanFactoryInitialization: 缓存所有配置文件包括bean的定义,这时候就不能增加或者修改bean了,初始化所有的singleton实例

ConfigurationClassPostProcessor

在invokeBeanFactoryPostProcessors的时候会调用一个非常重要的processor: ConfigurationClassPostProcessor.他会读取我们的mainClass,扫描对应的package并且生成合适的bean。这就是@SpringApplication被处理的地方。

ConfigurationClassPostProcessor是何时被注册上去的

AnnotationConfigServletWebServerApplicationContext#constructor --> org.springframework.context.annotation.AnnotatedBeanDefinitionReader#AnnotatedBeanDefinitionReader(org.springframework.beans.factory.support.BeanDefinitionRegistry) -->
org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(org.springframework.beans.factory.support.BeanDefinitionRegistry)

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

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

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

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

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

		// 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;
	}

CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME 就是 ‘org.springframework.context.annotation.internalRequiredAnnotationProcessor’
实例就是org.springframework.context.annotation.ConfigurationClassPostProcessor。

postProcessBeanDefinitionRegistry

	@Override
	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");
			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();
		}
	}

registry.getBeanDefinitionNames() 和registry.getBeanNamesForType(Object.class)返回结果不同的,只有调用过registry.registerBeanDefinition的才会在getBeanDefinitionNames()返回,通过registerSingleton的不会返回。
然后筛选出所有ConfigurationClass,在这里只有我们的mainClass demoApplication返回

parser.parse: 读出当前环境的所有Configuration class,会自动处理componentScan与及Import指令, 包括用户自定义的以及各种AutoConfiguration,注意现在还只是读出了CondifurationClass还没有读到各种Component class以及@Bean method生成的component

postProcessBeanFactory

	@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.
			processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
		}

		enhanceConfigurationClasses(beanFactory);
		beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
	}

1, 给Configuration Class 加proxy,使所有的@Bean method返回同一个singleton
2,增加ImportAwareBeanPostProcessor, 使被引用的Consiguration可以获取引用着的信息。

DeferredImportSelectorHandler

在org.springframework.context.annotation.ConfigurationClassParser#parse(java.util.Set<org.springframework.beans.factory.config.BeanDefinitionHolder>)

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

可以看到deferredImportSelectorHandler处理了importSelector

	private class DeferredImportSelectorHandler {

		@Nullable
		private List<DeferredImportSelectorHolder> deferredImportSelectors = new ArrayList<>();

		/**
		 * Handle the specified {@link DeferredImportSelector}. If deferred import
		 * selectors are being collected, this registers this instance to the list. If
		 * they are being processed, the {@link DeferredImportSelector} is also processed
		 * immediately according to its {@link DeferredImportSelector.Group}.
		 * @param configClass the source configuration class
		 * @param importSelector the selector to handle
		 */
		public void handle(ConfigurationClass configClass, DeferredImportSelector importSelector) {
			DeferredImportSelectorHolder holder = new DeferredImportSelectorHolder(configClass, importSelector);
			if (this.deferredImportSelectors == null) {
				DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
				handler.register(holder);
				handler.processGroupImports();
			}
			else {
				this.deferredImportSelectors.add(holder);
			}
		}

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

这就是EnableAutoConfiguration的原理

org.springframework.boot.autoconfigure.EnableAutoConfiguration --》
org.springframework.context.annotation.ConfigurationClassParser.DeferredImportSelectorHandler --》
org.springframework.boot.autoconfigure.AutoConfigurationImportSelector --》

		List<String> configurations = new ArrayList<>(
				SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()));
	protected Class<?> getSpringFactoriesLoaderFactoryClass() {
		return EnableAutoConfiguration.class;
	}
GitHub 加速计划 / sp / spring-boot
40
10
下载
spring-projects/spring-boot: 是一个用于简化Spring应用开发的框架。适合用于需要快速开发企业级Java应用的项目。特点是可以提供自动配置、独立运行和内置的Tomcat服务器,简化Spring应用的构建和部署。
最近提交(Master分支:4 个月前 )
6eaeeccd Closes gh-48827 10 小时前
7af147d0 Previously, CloudFoundryActuatorAutoConfiguration required RestTemplateBuilder, using it to create the RestTemplate that's used the security interceptor. Following the modularization, RestTemplateBuilder is only present when spring-boot-restclient is on the classpath. In its absence, CloudFoundryActuatorAutoConfiguration would fail. This commit address this problem by using RestClient.Builder (and RestClient) instead of RestTemplateBuilder (and RestTemplate). This allows CloudFoundryActuatorAutoConfiguration to work without spring-boot-restclient as RestClient.Builder and RestClient are provided by spring-web that will always be there in an MVC webapp. Fixes gh-48826 10 小时前
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐