Spring Boot internals
本文介绍springBoot架构与实现
Spring boot makes it easy to create stand-alone production-grade Spring based Applications
- Create stand-alone Spring applications
- Embed Tomcat,Jetty directly(no need to deploy WAR files)
- Provide opinionated ‘starter’ dependencies to simplify build configuration
- Automatically configure Spring and 3rd party libraries.
- Provide Production-ready features such as metrics, health checks, and externalized configuration
- Absolutely no code generation and no requirement for XML configuration.
Automatic Configuration
Spring boot achieves auto config mainly through various annotations and config class.
interface Configuration
interface SpringBootConfiguration extends Configuration
Bootstrap process
SpringApplication
Class that can be used to bootstrap and launch a Spring application from a java main method. Typical bootstrap steps:
- create
ApplicationContext
- register
CommandLinePropertySource
to expose command line arguments as Spring properties. - refresh the application context, loading all singleton beans
- trigger any
CommandLineRunner
beans.
class SpringApplication {
List<BootstrapRegistryInitializer> bootstrapRegistryInitializers
List<ApplicationContextInitializer<?>> initializers
List<ApplicationListener<?>> listeners
}
title: bootstrap process
:createBootStrapContext;
:SpringApplicationRunListeners.starting(bootstrapContext,mainclass);
:prepareEnvironment(listeners,bootstrapContext,applicationArguments);
:createApplicationContext();
:prepareContext(bootStrapContext,context,environment,listeners,appArgs);
:refreshContext(context);
:afterRefresh(context,appArgs);
:listenner.started(context,time);
:callRunners(context, appArgs);
BootStrapContext
A simple bootstrap context that is available during startup and Environment
post-processing up to the point that the ApplicationContext
is prepared.
@startuml
!theme plain
top to bottom direction
skinparam linetype ortho
interface BootstrapContext << interface >>
interface BootstrapRegistry << interface >>
interface ConfigurableBootstrapContext << interface >>
class DefaultBootstrapContext {
ApplicationEventMulticaster events
}
interface BootstrapRegistryInitializer
ConfigurableBootstrapContext -[#008200,plain]-^ BootstrapContext
ConfigurableBootstrapContext -[#008200,plain]-^ BootstrapRegistry
DefaultBootstrapContext -[#008200,dashed]-^ ConfigurableBootstrapContext
DefaultBootstrapContext -right-> BootstrapRegistryInitializer: init
@enduml
SpringApplicationRunListeners
EventPublishingRunListener
use an internal AppicationEventMulticaster
to publish SpringApplicationEvent
EnvironmentPostProcessorApplicationListener
used to trigger EnvironmentpostProcessors
registered in the spring.factories
file.
class SpringApplicationRunListeners {
List<SpringApplicationRunListener> listeners
}
interface SpringApplicationRunListener {
void starting(bootstrapContext)
void environmentPrepared( bootstrapContext, environment)
void contextPrepared(context)
}
class EventPublishingRunListener implements SpringApplicationRunListener {
SpringApplication application
SimpleApplicationEventMulticaster initialMulticaster
}
class EnvironmentPostProcessorApplicationListener implements SpringApplicationRunListener {
Function<ClassLoader, EnvironmentPostProcessorsFactory> postProcessorsFactory
}
SpringApplicationRunListeners o-- SpringApplicationRunListener
ApplicationContextFactory
Strategy interface for creating ApplicationContext
and ApplicationEnvironment
.
interface ApplicationContextFactory {
ConfigurableEnvironment createEnvironment(applicationType)
ConfigurableApplicationContext create(applicationType)
}
class ServletWebServerApplicationContextFactory implements ApplicationContextFactory
ServletWebServerApplicationContextFactory --> ApplicationServletEnvironment: createEnv
ServletWebServerApplicationContextFactory --> ServletWebServerApplicationContext: create Context
ApplicationServletEnvironment
default StandardServletEnvironment
used in SpringApplication
skinparam linetype ortho
' Declare interfaces
interface PropertyResolver <<interface>> {
boolean containsProperty(String key)
String getProperty(String key)
}
interface ConfigurablePropertyResolver <<interface>>
interface Environment <<interface>>
interface ConfigurableEnvironment <<interface>>
interface ConfigurableWebEnvironment <<interface>>
' Declare classes
class AbstractEnvironment {
Set<String> activeProfiles
Set<String> defaultProfiles
MutablePropertySources propertySources
ConfigurablePropertyResolver propertyResolver
protected void customizePropertySources(propertySources)
}
class StandardEnvironment {
protected void customizePropertySources(propertySources)
}
note "system properties system envs" as p1
StandardEnvironment .. p1
class StandardServletEnvironment {
protected void customizePropertySources(propertySources)
}
class ApplicationServletEnvironment
' Define relationships with arrow pointing from class to interface (left to right)
PropertyResolver <|-- ConfigurablePropertyResolver
Environment <|-- ConfigurableEnvironment
PropertyResolver <|-- Environment
ConfigurablePropertyResolver<|-- ConfigurableEnvironment
ConfigurableEnvironment <|-- ConfigurableWebEnvironment
ConfigurableEnvironment <|-- AbstractEnvironment
AbstractEnvironment <|-- StandardEnvironment
StandardEnvironment <-- StandardServletEnvironment
ConfigurableWebEnvironment <|-- StandardServletEnvironment
StandardServletEnvironment <|-- ApplicationServletEnvironment
Environment creation and configuration
package SpringBoot {
class SpringApplication {
ConfigurableEnvironment environment
getOrCreateEnvironment()
configureEnvironment(env, sourceArgs)
}
class ApplicationServletEnvironment
SpringApplication *-- ApplicationServletEnvironment
}
reference: 博客
ApplicationListener
EnvironmentPostProcessorApplicationListener
@startuml
!theme plain
top to bottom direction
skinparam linetype ortho
class ApplicationEvent
interface ApplicationListener<E> << interface >> {
void onApplicationEvent(E event)
}
class EnvironmentPostProcessorApplicationListener {
Function<ClassLoader, EnvironmentPostProcessorsFactory> postProcessorsFactory
getEnvironmentPostProcessors(resourceLoader,bootstrapContext)
onApplicationEnvironmentPreparedEvent( event)
}
interface EventListener << interface >>
annotation FunctionalInterface << annotation >>
interface Ordered << interface >>
interface SmartApplicationListener << interface >> {
boolean supportsEventType(eventType)
int getOrder()
}
ApplicationListener -[#595959,dashed]-> ApplicationEvent
ApplicationListener -[#008200,plain]-^ EventListener
ApplicationListener -[#999900,dotted]- FunctionalInterface
EnvironmentPostProcessorApplicationListener -[#008200,dashed]-^ Ordered
EnvironmentPostProcessorApplicationListener -[#008200,dashed]-^ SmartApplicationListener
SmartApplicationListener -[#008200,plain]-^ ApplicationListener
SmartApplicationListener -[#008200,plain]-^ Ordered
@enduml
EnvironmentPostProcessor
ConfigDataEnvironmentPostProcessor
!theme plain
top to bottom direction
skinparam linetype ortho
class ConfigDataEnvironmentPostProcessor {
void postProcessEnvironment( environment, application)
}
class ConfigDataEnvironment {
ConfigurableBootstrapContext bootstrapContext
ConfigurableEnvironment environment
ConfigDataLocationResolvers resolvers
Collection<String> additionalProfiles
ConfigDataEnvironmentUpdateListener environmentUpdateListener
ConfigDataLoaders loaders
ConfigDataEnvironmentContributors contributors
void processAndApply()
}
interface EnvironmentPostProcessor << interface >>
interface Ordered << interface >>
ConfigDataEnvironmentPostProcessor -[#008200,dashed]-^ EnvironmentPostProcessor
ConfigDataEnvironmentPostProcessor -[#008200,dashed]-^ Ordered
ConfigDataEnvironmentPostProcessor --> ConfigDataEnvironment: process
ConfigData processing
ConfigDataLocationResolver
strategy interface used to resolve locations into on or more resources.
ConfigDataLoader
strategy class that can be used to load ConfigData
for a given ConfigDataResource
Binder
A container object which Binds objects from one or more ConfigurationPropertySources
class EnvironmentPostProcessorApplicationListener{
onApplicationEnvironmentPreparedEvent(event)
}
class ConfigDataEnvironmentPostProcessor {
void postProcessEnvironment( environment, application)
}
class ConfigDataEnvironment {
ConfigurableEnvironment environment
ConfigDataLocationResolvers resolvers
Collection<String> additionalProfiles
ConfigDataEnvironmentUpdateListener environmentUpdateListener
ConfigDataLoaders loaders
ConfigDataEnvironmentContributors contributors
void processAndApply()
}
class ConfigDataLocationResolvers {
List<ConfigDataLocationResolver<?>> resolvers
List<ConfigDataResolutionResult> resolve(context, location,profiles)
}
interface ConfigDataLocationResolver<R extends ConfigDataResource> {
boolean isResolvable(context,location)
List<R> resolve(context,location)
}
class StandardConfigDataLocationResolver implements ConfigDataLocationResolver<StandardConfigDataResource> {
String[] configNames
List<PropertySourceLoader> propertySourceLoaders
}
interface PropertySourceLoader {
String[] getFileExtensions()
List<PropertySource<?>> load(String name, Resource resource)
}
class ConfigDataLoaders {
List<ConfigDataLoader> loaders
}
class ConfigDataEnvironmentContributors {
ConfigDataEnvironmentContributor root
ConfigurableBootstrapContext bootstrapContext
Binder getBinder(activationContext,filter,options)
}
class ConfigDataEnvironmentContributor implements Iterable {
ConfigDataLocation location
ConfigDataResource resource
PropertySource<?> propertySource
ConfigurationPropertySource configurationPropertySource
ConfigDataProperties properties
Map<ImportPhase, List<ConfigDataEnvironmentContributor>> children
iterator()
}
class Binder {
Iterable<ConfigurationPropertySource> sources
ConfigurationProperty findProperty(name, target,context)
}
EnvironmentPostProcessorApplicationListener --> ConfigDataEnvironmentPostProcessor: onEnvironmentPrepared
ConfigDataEnvironmentPostProcessor --> ConfigDataEnvironment: createEnv
ConfigDataEnvironment *-- ConfigDataLocationResolvers
ConfigDataEnvironment *-- ConfigDataLoaders
ConfigDataEnvironment *-- ConfigDataEnvironmentContributors
ConfigDataEnvironmentContributors *-- ConfigDataEnvironmentContributor
ConfigDataEnvironmentContributors --> Binder
ConfigDataLocationResolvers o-- ConfigDataLocationResolver
StandardConfigDataLocationResolver o-- PropertySourceLoader
top to bottom direction
package Spring {
interface BeanFactory {
+ {static} String FACTORY_BEAN_PREFIX
+ T getBean()
+ ObjectProvider<T> getBeanProvider(Class<T>)
+ boolean containsBean(String)
+ boolean isSingleton(String)
+ boolean isPrototype(String)
+ boolean isTypeMatch(String,Class<?>)
+ Class<?> getType(String)
+ String[] getAliases(String)
}
interface EnvironmentCapable {
Environment getEnvironment()
}
interface HierarchicalBeanFactory extends BeanFactory
interface ListableBeanFactory extends BeanFactory
interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
ApplicationContext getParent()
}
interface Lifecycle {
void start()
void stop()
boolean isRunning()
}
interface ConfigurableApplicationContext extends Lifecycle {
void setEnvironment()
void refresh()
}
interface WebApplicationContext extends ApplicationContext {
ServletContext getServletContext()
}
interface ConfigurableWebApplicationContext extends WebApplicationContext, ConfigurableApplicationContext {
String[] getConfigLocations()
void setConfigLocation()
void setServletContext()
}
interface BeanDefinitionRegistry {
void registerBeanDefinition()
void removeBeanDefinition()
BeanDefinition getBeanDefinition()
}
abstract class AbstractApplicationContext {
ApplicationContext parent
ConfigurableEnvironment environment
LifecycleProcessor lifecycleProcessor
List<BeanFactoryPostProcessor> beanFactoryPostProcessors
abstract void refreshBeanFactory()
abstract void closeBeanFactory()
}
class GenericApplicationContext {
- DefaultListableBeanFactory beanFactory
- ResourceLoader resourceLoader
- boolean customClassLoader
- AtomicBoolean refreshed
+ void setParent(ApplicationContext)
+ void setApplicationStartup(ApplicationStartup)
+ void setAllowBeanDefinitionOverriding(boolean)
+ void setAllowCircularReferences(boolean)
+ void setResourceLoader(ResourceLoader)
+ Resource getResource(String)
+ Resource[] getResources(String)
+ void setClassLoader(ClassLoader)
+ ClassLoader getClassLoader()
# void refreshBeanFactory()
# void cancelRefresh(Throwable)
# void closeBeanFactory()
+ ConfigurableListableBeanFactory getBeanFactory()
+ DefaultListableBeanFactory getDefaultListableBeanFactory()
+ AutowireCapableBeanFactory getAutowireCapableBeanFactory()
+ void registerAlias(String,String)
+ void removeAlias(String)
+ boolean isAlias(String)
+ void refreshForAotProcessing(RuntimeHints)
- void preDetermineBeanTypes(RuntimeHints)
+ void registerBean(Class<T>,Object)
}
class GenericApplicationContext$ClassDerivedBeanDefinition {
+ Constructor<?>[] getPreferredConstructors()
+ RootBeanDefinition cloneBeanDefinition()
}
class GenericWebApplicationContext {
- ServletContext servletContext
- ThemeSource themeSource
+ void setServletContext(ServletContext)
+ ServletContext getServletContext()
+ String getApplicationName()
+ Theme getTheme(String)
+ void setServletConfig(ServletConfig)
+ ServletConfig getServletConfig()
+ void setNamespace(String)
+ String getNamespace()
+ void setConfigLocation(String)
+ void setConfigLocations(String)
+ String[] getConfigLocations()
}
ConfigurableWebApplicationContext <|.. GenericWebApplicationContext
ThemeSource <|.. GenericWebApplicationContext
GenericApplicationContext <|-- GenericWebApplicationContext
ConfigurableApplicationContext <|.. AbstractApplicationContext
DefaultResourceLoader <|-- AbstractApplicationContext
BeanDefinitionRegistry <|.. GenericApplicationContext
AbstractApplicationContext <|-- GenericApplicationContext
GenericApplicationContext +.. GenericApplicationContext$ClassDerivedBeanDefinition
RootBeanDefinition <|-- GenericApplicationContext$ClassDerivedBeanDefinition
ApplicationContext <|-- ConfigurableApplicationContext
}
package SpringBoot {
class SpringApplication {
WebApplicationType webApplicationType
List<ApplicationContextInitializer<?>> initializers
List<ApplicationListener<?>> listeners
ApplicationContextFactory applicationContextFactory
ConfigurableApplicationContext run(String... args)
void prepareContext()
}
interface ApplicationContextFactory {
ConfigurableApplicationContext create(webApplicationType)
}
class ServletWebServerApplicationContext {
- {static} Log logger
+ {static} String DISPATCHER_SERVLET_NAME
- WebServer webServer
- ServletConfig servletConfig
- String serverNamespace
+ void refresh()
+ String getServerNamespace()
+ void setServerNamespace(String)
+ void setServletConfig(ServletConfig)
+ ServletConfig getServletConfig()
+ WebServer getWebServer()
}
class ServletWebServerApplicationContext$ExistingWebApplicationScopes {
- {static} Set<String> SCOPES
- ConfigurableListableBeanFactory beanFactory
- Map<String,Scope> scopes
+ void restore()
}
ConfigurableWebServerApplicationContext <|.. ServletWebServerApplicationContext
GenericWebApplicationContext <|----- ServletWebServerApplicationContext
ServletWebServerApplicationContext +.. ServletWebServerApplicationContext$ExistingWebApplicationScopes
class ServletWebServerApplicationContextFactory implements ApplicationContextFactory
SpringApplication *-- ApplicationContextFactory
ServletWebServerApplicationContextFactory -right-> ServletWebServerApplicationContext: create
}
3. spring boot startup
SpringApplication--> SpringApplication:createBootstrapContext
SpringApplication--> SpringApplication:prepareEnvironment
SpringApplication--> SpringApplication:createApplicationContext
SpringApplication--> SpringApplication:prepareContext
SpringApplication--> SpringApplication:refreshContext
SpringApplication--> SpringApplication:afterRefresh