文章目录

  • 主要功能
  • Factory
  • Constructor
  • Additional Component Candidates
  • Parent Class ServletWebServerApplicationContext
    • postProcessBeanFactory
    • 创建webserver
    • selfInitialize
    • ServletContextInitializerBeans
  • Ancestor Class GenericWebApplicationContext
  • Ancestor Class GenericApplicationContext
  • Ancestor Class AbstractApplicationContext
    • 重要变量:
    • Refresh
    • ConfigurationClassPostProcessor
      • ConfigurationClassPostProcessor是何时被注册上去的
      • postProcessBeanDefinitionRegistry
      • postProcessBeanFactory
    • DeferredImportSelectorHandler

主要功能

  • 接受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 {@Overridepublic 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;@Overridepublic final void register(Class<?>... annotatedClasses) {Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");this.annotatedClasses.addAll(Arrays.asList(annotatedClasses));}@Overridepublic final void scan(String... basePackages) {Assert.notEmpty(basePackages, "At least one base package must be specified");this.basePackages = basePackages;}@Overrideprotected 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

 @Overridepublic final void refresh() throws BeansException, IllegalStateException {try {super.refresh();}catch (RuntimeException ex) {WebServer webServer = this.webServer;if (webServer != null) {webServer.stop();}throw ex;}}@Overrideprotected 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<>();@Overridepublic 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就实现了

 @Overrideprotected 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

 @Overridepublic 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 foundif (configCandidates.isEmpty()) {return;}// Sort by previously determined @Order value, if applicableconfigCandidates.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 contextSingletonBeanRegistry 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 classConfigurationClassParser 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 contentif (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 classesif (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

 @Overridepublic 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 {@Nullableprivate 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;}

spring-boot源码解析之AnnotationConfigServletWebServerApplicationContext相关推荐

  1. spring boot 源码解析23-actuate使用及EndPoint解析

    前言 spring boot 中有个很诱人的组件–actuator,可以对spring boot应用做监控,只需在pom文件中加入如下配置即可: <dependency><group ...

  2. spring boot 源码解析15-spring mvc零配置

    前言 spring boot 是基于spring 4 的基础上的一个框架,spring 4 有一个新特效–>基于java config 实现零配置.而在企业的实际工作中,spring 都是和sp ...

  3. spring boot 源码解析52-actuate中MVCEndPoint解析

    前言 之前的几篇文章分析了spring boot 中有关endpoint的实现,细心的朋友可以发现,在org.springframework.boot.actuate.endpoint.mvc 包下也 ...

  4. spring boot 源码解析43-JmxMetricWriter详解

    前言 本文我们来介绍JmxMetricWriter, JmxMetricWriter是依赖于spring jmx 来实现的. 因此本文的开头先介绍一下spring boot 与jmx的集成,然后分析J ...

  5. spring boot 源码解析31-AuthenticationAuditListener,AuthorizationAuditListener

    前言 这篇文章我们来分析一下org.springframework.boot.actuate.security,org.springframework.boot.actuate.audit中的代码,这 ...

  6. spring boot 源码解析29-LogbackLoggingSystem

    前言 现在我们来分析一下LogbackLoggingSystem,spring boot 中默认生效的,该类也是继承自Slf4JLoggingSystem. 解析 LogbackLoggingSyst ...

  7. spring boot 源码解析8-SpringApplication#run第8步

    前言 这篇文章我们分析SpringApplication#run第8步.执行prepareContext方法.该方法的内容比较多.我们慢慢来. 分析 SpringApplication#run 第8步 ...

  8. 【细读Spring Boot源码】重中之重refresh()

    前言 版本:spring-boot-2.7.3 | spring-context-5.3.22 在Spring Boot启动过程中[细读Spring Boot源码]启动步骤 主流程详情7中applic ...

  9. Spring Boot源码简析 @EnableTransactionManagement

    相关阅读 Spring Boot源码简析 事务管理 Spring Boot源码简析 @EnableAspectJAutoProxy Spring Boot源码简析 @EnableAsync Sprin ...

  10. spring事务源码解析

    前言 在spring jdbcTemplate 事务,各种诡异,包你醍醐灌顶!最后遗留了一个问题:spring是怎么样保证事务一致性的? 当然,spring事务内容挺多的,如果都要讲的话要花很长时间, ...

最新文章

  1. TorchScript神经网络集成技术
  2. js RegExp用法
  3. redis基础之有序集合应用
  4. 武安高中计算机学院那个好,河北邯郸最好的5所高中,前两所学霸如云,看看有你的母校没?...
  5. 二叉树的最小深度Python解法
  6. c语言解魔方程序,请哪位牛人告诉我怎样用C语言程序复原3阶魔方的
  7. MVC路由中routes.IgnoreRoute({resource}.axd/{*pathInfo}) 到底什么意思!
  8. 4问教你搞定java中的ThreadLocal
  9. 【经验分享】如何搭建本地MQTT服务器(Windows ),并进行上下行调测
  10. 腾讯公开“区块链网络的信息处理方法”相关专利
  11. java中 Double和double区别
  12. 从零实现深度学习框架——优化反向传播相关代码
  13. 关于CityEngine导入shp数据
  14. 【转】《Unity Shader入门精要》冯乐乐 随书彩图
  15. python中集合的符号_python集合中的操作符有哪些?怎么用?
  16. springMVC源码分析--HandlerMethod
  17. 一口气入门计算机网络基础(CCNA)
  18. 若某非空二叉树的先序序列和后序序列正好相反,或者正好相同,则二叉树形态是怎么样的?
  19. fft 估计载波频率程序_fft频率估计
  20. android快牙原理,实测快牙的真实传输速度

热门文章

  1. 自动驾驶系统进阶与项目实战(三)基于全卷积神经网络的点云三维目标检测和ROS实战
  2. 【论文翻译 - RFID】射频全息图:利用商业化产品对移动射频标签进行实时高精度追踪
  3. 【漫漫长征路】hihocoder #1082 然而沼跃鱼早就看穿了一切
  4. 素描初学者入门教程素描高手分享经…
  5. 华为云PaaS平台微服务治理5云容器引擎CCE
  6. 使用SDL实现一个简单的YUV播放器
  7. 2021阳城一中高考成绩查询,2019阳城一中录取分数线(附2019高考成绩喜报)
  8. 大前端课程 - 4.5个月学习总结
  9. 01背包经典例题详解
  10. 以MacOS 13为例,VMware 16安装MacOS