SpringBoot源码技术栈太过庞大,这里只是简版解读,后续会细化部分源码细节.
@SpringBootApplication
public class FactoryDemoApplication {
public static void main(String[] args) {
// 从Run开始Debug
SpringApplication.run(FactoryDemoApplication.class, args);
}
}
public static ConfigurableApplicationContext run(Class[] primarySources, String[] args) {
return new SpringApplication(primarySources).run(args);
}
public SpringApplication(ResourceLoader resourceLoader, Class... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
// 即传入的pringApplication.run传入的FactoryDemoApplication.class这个参数
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
通过WebApplicationType.deduceFromClasspath()实现的,其实就是判断指定类是不是存在。
private static final String[] SERVLET_INDICATOR_CLASSES = {
"javax.servlet.Servlet",
"org.springframework.web.context.ConfigurableWebApplicationContext" };
private static final String WEBMVC_INDICATOR_CLASS = "org.springframework.web.servlet.DispatcherServlet";
private static final String WEBFLUX_INDICATOR_CLASS = "org.springframework.web.reactive.DispatcherHandler";
private static final String JERSEY_INDICATOR_CLASS = "org.glassfish.jersey.servlet.ServletContainer";
private static final String SERVLET_APPLICATION_CONTEXT_CLASS = "org.springframework.web.context.WebApplicationContext";
private static final String REACTIVE_APPLICATION_CONTEXT_CLASS = "org.springframework.boot.web.reactive.context.ReactiveWebApplicationContext";
static WebApplicationType deduceFromClasspath() {
if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
&& !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
return WebApplicationType.REACTIVE;
}
for (String className : SERVLET_INDICATOR_CLASSES) {
if (!ClassUtils.isPresent(className, null)) {
return WebApplicationType.NONE;
}
}
return WebApplicationType.SERVLET;
}
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
SpringFactoriesLoader.loadFactoryNames(type, classLoader)会加载全部并放入缓存中,方便后续使用。
"com.example.factory.project.ChildGenerationConfiguration" -> {
LinkedList@1984} size = 2
"org.springframework.boot.autoconfigure.EnableAutoConfiguration" -> {
LinkedList@1985} size = 128
"org.springframework.beans.BeanInfoFactory" -> {
LinkedList@1986} size = 1
"org.springframework.boot.env.EnvironmentPostProcessor" -> {
LinkedList@2022} size = 6
"org.springframework.context.ApplicationContextInitializer" -> {
LinkedList@2024} size = 8
"org.springframework.context.ApplicationListener" -> {
LinkedList@2026} size = 13
"org.springframework.boot.diagnostics.FailureAnalyzer" -> {
LinkedList@2028} size = 18
"org.springframework.boot.SpringApplicationRunListener" -> {
LinkedList@2030} size = 1
"org.springframework.boot.env.PropertySourceLoader" -> {
LinkedList@2032} size = 2
"org.springframework.boot.diagnostics.FailureAnalysisReporter" -> {
LinkedList@2034} size = 1
"org.springframework.boot.SpringBootExceptionReporter" -> {
LinkedList@2036} size = 1
"org.springframework.boot.autoconfigure.AutoConfigurationImportFilter" -> {
LinkedList@2038} size = 3
"org.springframework.boot.autoconfigure.AutoConfigurationImportListener" -> {
LinkedList@2040} size = 1
"org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider" -> {
LinkedList@2042} size = 5
0 = "org.springframework.boot.devtools.restart.RestartScopeInitializer"
1 = "org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer"
2 = "org.springframework.boot.context.ContextIdApplicationContextInitializer"
3 = "org.springframework.boot.context.config.DelegatingApplicationContextInitializer"
4 = "org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer"
5 = "org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer"
6 = "org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer"
7 = "org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener"
通过AnnotationAwareOrderComparator.sort(instances);进行排序
0 = {
DelegatingApplicationContextInitializer@1914}
1 = {
SharedMetadataReaderFactoryContextInitializer@1933}
2 = {
ContextIdApplicationContextInitializer@1896}
3 = {
RestartScopeInitializer@1861}
4 = {
ConfigurationWarningsApplicationContextInitializer@1878}
5 = {
RSocketPortInfoApplicationContextInitializer@1931}
6 = {
ServerPortInfoApplicationContextInitializer@1932}
7 = {
ConditionEvaluationReportLoggingListener@1934}
SpringApplication.setInitializers(Collection> initializers)
0 = "org.springframework.boot.devtools.restart.RestartApplicationListener"
1 = "org.springframework.boot.devtools.logger.DevToolsLogFactory.Listener"
2 = "org.springframework.boot.ClearCachesApplicationListener"
3 = "org.springframework.boot.builder.ParentContextCloserApplicationListener"
4 = "org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor"
5 = "org.springframework.boot.context.FileEncodingApplicationListener"
6 = "org.springframework.boot.context.config.AnsiOutputApplicationListener"
7 = "org.springframework.boot.context.config.ConfigFileApplicationListener"
8 = "org.springframework.boot.context.config.DelegatingApplicationListener"
9 = "org.springframework.boot.context.logging.ClasspathLoggingApplicationListener"
10 = "org.springframework.boot.context.logging.LoggingApplicationListener"
11 = "org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener"
12 = "org.springframework.boot.autoconfigure.BackgroundPreinitializer"
使用DevTools 会添加DevToolsPropertyDefaultsPostProcessor
0 = {
RestartApplicationListener@2043}
1 = {
CloudFoundryVcapEnvironmentPostProcessor@2044}
2 = {
ConfigFileApplicationListener@2045}
3 = {
AnsiOutputApplicationListener@2046}
4 = {
LoggingApplicationListener@2047}
5 = {
ClasspathLoggingApplicationListener@2048}
6 = {
BackgroundPreinitializer@2049}
7 = {
DelegatingApplicationListener@2050}
8 = {
ParentContextCloserApplicationListener@2051}
9 = {
DevToolsLogFactory$Listener@2052}
10 = {
ClearCachesApplicationListener@2053}
11 = {
FileEncodingApplicationListener@2054}
12 = {
LiquibaseServiceLocatorApplicationListener@2055}
实现了EnvironmentPostProcessor接口,会依次加载DEFAULT_SEARCH_LOCATIONS 配置的路径下的配置文件到环境变量中。另外这里也添加了1个RandomValuePropertySource来解析随机数。
private static final String DEFAULT_SEARCH_LOCATIONS = "classpath:/,classpath:/config/,file:./,file:./config/*/,file:./config/";
private Set getSearchLocations() {
Set locations = getSearchLocations(CONFIG_ADDITIONAL_LOCATION_PROPERTY);
if (this.environment.containsProperty(CONFIG_LOCATION_PROPERTY)) {
locations.addAll(getSearchLocations(CONFIG_LOCATION_PROPERTY));
}
else {
locations.addAll(
asResolvedSet(ConfigFileApplicationListener.this.searchLocations, DEFAULT_SEARCH_LOCATIONS));
}
return locations;
}
private Set asResolvedSet(String value, String fallback) {
List list = Arrays.asList(StringUtils.trimArrayElements(StringUtils.commaDelimitedListToStringArray(
(value != null) ? this.environment.resolvePlaceholders(value) : fallback)));
Collections.reverse(list);
return new LinkedHashSet<>(list);
}
spring对路径字符串拆分后进行了翻转操作,所以这里的加载顺序为:
高优先级的会覆盖低优先级的配置属性。
解析配置文件名后使用不同的加载器进行加载配置文件,默认的配置文件解析器:
# 解析"properties", "xml"文件
0 = {PropertiesPropertySourceLoader@3449}
# 解析 "yml", "yaml" 文件
1 = {YamlPropertySourceLoader@3456}
解析到文件会以添加到上下文中
0 = {ConfigurationPropertySourcesPropertySource@2330} "ConfigurationPropertySourcesPropertySource {name='configurationProperties'}"
1 = {PropertySource$StubPropertySource@2331} "StubPropertySource {name='servletConfigInitParams'}"
2 = {PropertySource$StubPropertySource@2332} "StubPropertySource {name='servletContextInitParams'}"
3 = {PropertiesPropertySource@2333} "PropertiesPropertySource {name='systemProperties'}"
4 = {SystemEnvironmentPropertySourceEnvironmentPostProcessor$OriginAwareSystemEnvironmentPropertySource@2702} "OriginAwareSystemEnvironmentPropertySource {name='systemEnvironment'}"
5 = {RandomValuePropertySource@3191} "RandomValuePropertySource {name='random'}"
6 = {OriginTrackedMapPropertySource@4042} "OriginTrackedMapPropertySource {name='applicationConfig: [classpath:/application.properties]'}"
7 = {OriginTrackedMapPropertySource@3962} "OriginTrackedMapPropertySource {name='applicationConfig: [classpath:/application.yml]'}"
SpringApplication.setListeners(Collection> listeners)
即获取main方法的所在类
try {
StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
for (StackTraceElement stackTraceElement : stackTrace) {
if ("main".equals(stackTraceElement.getMethodName())) {
return Class.forName(stackTraceElement.getClassName());
}
}
}
catch (ClassNotFoundException ex) {
// Swallow and continue
}
return null;
调用run方法
StopWatch stopWatch = new StopWatch();
stopWatch.start();
默认为true
private void configureHeadlessProperty() {
System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS,
System.getProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this.headless)));
}
0 = {
EventPublishingRunListener@1958}
实例化SpringApplicationRunListeners,并保存监听器
SpringApplicationRunListeners(Log log, Collection<? extends SpringApplicationRunListener> listeners) {
this.log = log;
this.listeners = new ArrayList<>(listeners);
}
目前只有一个监听器:EventPublishingRunListener
void starting() {
for (SpringApplicationRunListener listener : this.listeners) {
listener.starting();
}
}
@Override
public void starting() {
this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
}
0 = {
LoggingApplicationListener@1805}
1 = {
BackgroundPreinitializer@1827}
2 = {
DelegatingApplicationListener@1828}
3 = {
LiquibaseServiceLocatorApplicationListener@1829}
即循环调用支持ApplicationStartingEvent事件的监听器
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments) {
// Create and configure the environment
ConfigurableEnvironment environment = getOrCreateEnvironment();
configureEnvironment(environment, applicationArguments.getSourceArgs());
ConfigurationPropertySources.attach(environment);
listeners.environmentPrepared(environment);
bindToSpringApplication(environment);
if (!this.isCustomEnvironment) {
environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
deduceEnvironmentClass());
}
ConfigurationPropertySources.attach(environment);
return environment;
}
private ConfigurableEnvironment getOrCreateEnvironment() {
if (this.environment != null) {
return this.environment;
}
switch (this.webApplicationType) {
case SERVLET:
return new StandardServletEnvironment();
case REACTIVE:
return new StandardReactiveWebEnvironment();
default:
return new StandardEnvironment();
}
}
public static ConversionService getSharedInstance() {
ApplicationConversionService sharedInstance = ApplicationConversionService.sharedInstance;
if (sharedInstance == null) {
synchronized (ApplicationConversionService.class) {
sharedInstance = ApplicationConversionService.sharedInstance;
if (sharedInstance == null) {
sharedInstance = new ApplicationConversionService();
ApplicationConversionService.sharedInstance = sharedInstance;
}
}
}
return sharedInstance;
}
protected void configurePropertySources(ConfigurableEnvironment environment, String[] args) {
MutablePropertySources sources = environment.getPropertySources();
if (this.defaultProperties != null && !this.defaultProperties.isEmpty()) {
sources.addLast(new MapPropertySource("defaultProperties", this.defaultProperties));
}
if (this.addCommandLineProperties && args.length > 0) {
String name = CommandLinePropertySource.COMMAND_LINE_PROPERTY_SOURCE_NAME;
if (sources.contains(name)) {
PropertySource<?> source = sources.get(name);
CompositePropertySource composite = new CompositePropertySource(name);
composite.addPropertySource(
new SimpleCommandLinePropertySource("springApplicationCommandLineArgs", args));
composite.addPropertySource(source);
sources.replace(name, composite);
}
else {
sources.addFirst(new SimpleCommandLinePropertySource(args));
}
}
}
protected void configureProfiles(ConfigurableEnvironment environment, String[] args) {
Set<String> profiles = new LinkedHashSet<>(this.additionalProfiles);
profiles.addAll(Arrays.asList(environment.getActiveProfiles()));
environment.setActiveProfiles(StringUtils.toStringArray(profiles));
}
public static void attach(Environment environment) {
Assert.isInstanceOf(ConfigurableEnvironment.class, environment);
MutablePropertySources sources = ((ConfigurableEnvironment) environment).getPropertySources();
PropertySource<?> attached = sources.get(ATTACHED_PROPERTY_SOURCE_NAME);
if (attached != null && attached.getSource() != sources) {
sources.remove(ATTACHED_PROPERTY_SOURCE_NAME);
attached = null;
}
if (attached == null) {
sources.addFirst(new ConfigurationPropertySourcesPropertySource(ATTACHED_PROPERTY_SOURCE_NAME,
new SpringConfigurationPropertySources(sources)));
}
}
@Override
public void environmentPrepared(ConfigurableEnvironment environment) {
this.initialMulticaster
.multicastEvent(new ApplicationEnvironmentPreparedEvent(this.application, this.args, environment));
}
0 = {
ConfigFileApplicationListener@2838}
1 = {
AnsiOutputApplicationListener@3747}
2 = {
LoggingApplicationListener@1805}
3 = {
ClasspathLoggingApplicationListener@3748}
4 = {
BackgroundPreinitializer@1827}
5 = {
DelegatingApplicationListener@1828}
6 = {
FileEncodingApplicationListener@3749}
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}
0 = {
SystemEnvironmentPropertySourceEnvironmentPostProcessor@2911}
1 = {
SpringApplicationJsonEnvironmentPostProcessor@2912}
2 = {
CloudFoundryVcapEnvironmentPostProcessor@2913}
3 = {
ConfigFileApplicationListener@2838}
4 = {
DebugAgentEnvironmentPostProcessor@2914}
protected void bindToSpringApplication(ConfigurableEnvironment environment) {
try {
Binder.get(environment).bind("spring.main", Bindable.ofInstance(this));
}
catch (Exception ex) {
throw new IllegalStateException("Cannot bind to SpringApplication", ex);
}
}
封装结果保存在PropertySourcesPlaceholdersResolver
sources = {
SpringConfigurationPropertySources@3220}
sources = {
MutablePropertySources@3206} "[ConfigurationPropertySourcesPropertySource {name='configurationProperties'}, StubPropertySource {name='servletConfigInitParams'}, StubPropertySource {name='servletContextInitParams'}, PropertiesPropertySource {name='systemProperties'}, OriginAwareSystemEnvironmentPropertySource {name='systemEnvironment'}, RandomValuePropertySource {name='random'}, OriginTrackedMapPropertySource {name='applicationConfig: [classpath:/application.yml]'}]"
propertySourceList = {
CopyOnWriteArrayList@3241} size = 7
0 = {
ConfigurationPropertySourcesPropertySource@3212} "ConfigurationPropertySourcesPropertySource {name='configurationProperties'}"
1 = {
PropertySource$StubPropertySource@3243} "StubPropertySource {name='servletConfigInitParams'}"
2 = {
PropertySource$StubPropertySource@3244} "StubPropertySource {name='servletContextInitParams'}"
3 = {
PropertiesPropertySource@3245} "PropertiesPropertySource {name='systemProperties'}"
4 = {
SystemEnvironmentPropertySourceEnvironmentPostProcessor$OriginAwareSystemEnvironmentPropertySource@3246} "OriginAwareSystemEnvironmentPropertySource {name='systemEnvironment'}"
5 = {
RandomValuePropertySource@3247} "RandomValuePropertySource {name='random'}"
6 = {
OriginTrackedMapPropertySource@3248} "OriginTrackedMapPropertySource {name='applicationConfig: [classpath:/application.yml]'}"
cache = {
ConcurrentReferenceHashMap@3308} size = 4
{
RandomValuePropertySource@3247} "RandomValuePropertySource {name='random'}" -> {
SpringConfigurationPropertySource@3318} "RandomValuePropertySource {name='random'}"
{
SystemEnvironmentPropertySourceEnvironmentPostProcessor$OriginAwareSystemEnvironmentPropertySource@3246} "OriginAwareSystemEnvironmentPropertySource {name='systemEnvironment'}" -> {
SpringIterableConfigurationPropertySource@3319} "OriginAwareSystemEnvironmentPropertySource {name='systemEnvironment'}"
{
PropertiesPropertySource@3245} "PropertiesPropertySource {name='systemProperties'}" -> {
SpringIterableConfigurationPropertySource@3320} "PropertiesPropertySource {name='systemProperties'}"
{
OriginTrackedMapPropertySource@3248} "OriginTrackedMapPropertySource {name='applicationConfig: [classpath:/application.yml]'}" -> {
SpringIterableConfigurationPropertySource@3321} "OriginTrackedMapPropertySource {name='applicationConfig: [classpath:/application.yml]'}"
protected void bindToSpringApplication(ConfigurableEnvironment environment) {
try {
Binder.get(environment).bind("spring.main", Bindable.ofInstance(this));
}
catch (Exception ex) {
throw new IllegalStateException("Cannot bind to SpringApplication", ex);
}
}
0 = {
ConfigurationPropertySourcesPropertySource@3492} "ConfigurationPropertySourcesPropertySource {name='configurationProperties'}"
logger = {
LogAdapter$Slf4jLocationAwareLog@3505}
name = "configurationProperties"
source = {
SpringConfigurationPropertySources@3493}
sources = {
MutablePropertySources@3402} "[ConfigurationPropertySourcesPropertySource {name='configurationProperties'}, StubPropertySource {name='servletConfigInitParams'}, StubPropertySource {name='servletContextInitParams'}, PropertiesPropertySource {name='systemProperties'}, OriginAwareSystemEnvironmentPropertySource {name='systemEnvironment'}, RandomValuePropertySource {name='random'}, OriginTrackedMapPropertySource {name='applicationConfig: [classpath:/application.yml]'}]"
propertySourceList = {
CopyOnWriteArrayList@3406} size = 7
0 = {
ConfigurationPropertySourcesPropertySource@3492} "ConfigurationPropertySourcesPropertySource {name='configurationProperties'}"
1 = {
PropertySource$StubPropertySource@3409} "StubPropertySource {name='servletConfigInitParams'}"
2 = {
PropertySource$StubPropertySource@3410} "StubPropertySource {name='servletContextInitParams'}"
3 = {
PropertiesPropertySource@3411} "PropertiesPropertySource {name='systemProperties'}"
4 = {
SystemEnvironmentPropertySourceEnvironmentPostProcessor$OriginAwareSystemEnvironmentPropertySource@3412} "OriginAwareSystemEnvironmentPropertySource {name='systemEnvironment'}"
5 = {
RandomValuePropertySource@3413} "RandomValuePropertySource {name='random'}"
6 = {
OriginTrackedMapPropertySource@3414} "OriginTrackedMapPropertySource {name='applicationConfig: [classpath:/application.yml]'}"
cache = {
ConcurrentReferenceHashMap@3494} size = 0
1 = {
PropertySource$StubPropertySource@3409} "StubPropertySource {name='servletConfigInitParams'}"
2 = {
PropertySource$StubPropertySource@3410} "StubPropertySource {name='servletContextInitParams'}"
3 = {
PropertiesPropertySource@3411} "PropertiesPropertySource {name='systemProperties'}"
4 = {
SystemEnvironmentPropertySourceEnvironmentPostProcessor$OriginAwareSystemEnvironmentPropertySource@3412} "OriginAwareSystemEnvironmentPropertySource {name='systemEnvironment'}"
5 = {
RandomValuePropertySource@3413} "RandomValuePropertySource {name='random'}"
6 = {
OriginTrackedMapPropertySource@3414} "OriginTrackedMapPropertySource {name='applicationConfig: [classpath:/application.yml]'}"
private void configureIgnoreBeanInfo(ConfigurableEnvironment environment) {
if (System.getProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME) == null) {
Boolean ignore = environment.getProperty("spring.beaninfo.ignore", Boolean.class, Boolean.TRUE);
System.setProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME, ignore.toString());
}
}
private Banner printBanner(ConfigurableEnvironment environment) {
if (this.bannerMode == Banner.Mode.OFF) {
return null;
}
ResourceLoader resourceLoader = (this.resourceLoader != null) ? this.resourceLoader
: new DefaultResourceLoader(getClassLoader());
SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter(resourceLoader, this.banner);
if (this.bannerMode == Mode.LOG) {
return bannerPrinter.print(environment, this.mainApplicationClass, logger);
}
return bannerPrinter.print(environment, this.mainApplicationClass, System.out);
}
public void printBanner(Environment environment, Class<?> sourceClass, PrintStream printStream) {
for (String line : BANNER) {
printStream.println(line);
}
String version = SpringBootVersion.getVersion();
version = (version != null) ? " (v" + version + ")" : "";
StringBuilder padding = new StringBuilder();
while (padding.length() < STRAP_LINE_SIZE - (version.length() + SPRING_BOOT.length())) {
padding.append(" ");
}
printStream.println(AnsiOutput.toString(AnsiColor.GREEN, SPRING_BOOT, AnsiColor.DEFAULT, padding.toString(),
AnsiStyle.FAINT, version));
printStream.println();
}
WEB默认情况下是AnnotationConfigServletWebServerApplicationContext,然后实例化。
protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
switch (this.webApplicationType) {
case SERVLET:
contextClass = Class.forName("org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext");
break;
case REACTIVE:
contextClass = Class.forName("org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext");
break;
default:
contextClass = Class.forName("org.springframework.context."
+ "annotation.AnnotationConfigApplicationContext");
}
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Unable create a default ApplicationContext, please specify an ApplicationContextClass", ex);
}
}
return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}
这里会实例化DefaultListableBeanFactory并保存在beanFactory属性中,后续都会基于它进行操作
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
简略版继承关系:
AnnotationConfigServletWebServerApplicationContext (org.springframework.boot.web.servlet.context)
ServletWebServerApplicationContext (org.springframework.boot.web.servlet.context)
GenericWebApplicationContext (org.springframework.web.context.support)
GenericApplicationContext (org.springframework.context.support)
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);
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
// 获取上下文,即上文提到的GenericApplicationContext#beanFactory
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
// Order比较器
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
// 自动转入
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
// org.springframework.context.annotation.internalConfigurationAnnotationProcessor
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
// @Configuration类的引导处理的BeanFactoryPostProcessor
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// org.springframework.context.annotation.internalAutowiredAnnotationProcessor
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
// @Autowired @Value @Inject 等自动注入相关注解的处理类
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// org.springframework.context.annotation.internalCommonAnnotationProcessor
// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
// 支持普通的Java开箱即用注释,也支持JSR-250注释
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// jpa 功能支持 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));
}
// org.springframework.context.event.internalEventListenerProcessor
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));
}
// org.springframework.context.event.internalEventListenerFactory
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));
}
一个bean定义扫描器,它检测类路径上的bean候选,在给定的注册表(BeanFactory或ApplicationContext)中注册相应的bean定义,通过可配置的类型筛选器检测候选类,Bean条件过滤在这里做的。
* {
@link org.springframework.stereotype.Component @Component},
* {
@link org.springframework.stereotype.Repository @Repository},
* {
@link org.springframework.stereotype.Service @Service}, or
* {
@link org.springframework.stereotype.Controller @Controller} stereotype.
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
this(registry, true);
}
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
this(registry, useDefaultFilters, getOrCreateEnvironment(registry));
}
protected void registerDefaultFilters() {
this.includeFilters.add(new AnnotationTypeFilter(Component.class));
ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
try {
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
logger.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
}
catch (ClassNotFoundException ex) {
// JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
}
try {
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}
用于触发从spring.factories加载的FailureAnalyzer和FailureAnalysisReporter实例的实用程序。 需要访问BeanFactory来执行分析的故障分析器可以实现BeanFactoryAware,以便在调用故障分析器.analyze(Throwable)之前注入BeanFactory
org.springframework.boot.diagnostics.FailureAnalyzers
把之前加载的监听器,启动参数,环境变量放到上下文中
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
context.setEnvironment(environment);
postProcessApplicationContext(context);
applyInitializers(context);
listeners.contextPrepared(context);
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// Add boot specific singleton beans
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory) beanFactory)
.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
if (this.lazyInitialization) {
context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
}
// Load the sources
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
load(context, sources.toArray(new Object[0]));
listeners.contextLoaded(context);
}
0 = {
DelegatingApplicationContextInitializer@3540}
1 = {
SharedMetadataReaderFactoryContextInitializer@3541}
2 = {
ContextIdApplicationContextInitializer@3542}
3 = {
ConfigurationWarningsApplicationContextInitializer@3543}
4 = {
RSocketPortInfoApplicationContextInitializer@3544}
5 = {
ServerPortInfoApplicationContextInitializer@3545}
6 = {
ConditionEvaluationReportLoggingListener@3546}
protected void applyInitializers(ConfigurableApplicationContext context) {
for (ApplicationContextInitializer initializer : getInitializers()) {
Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(),
ApplicationContextInitializer.class);
Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
initializer.initialize(context);
}
}
监听该事件的监听器
0 = {
BackgroundPreinitializer@3824}
1 = {
DelegatingApplicationListener@3831}
new StartupInfoLogger(this.mainApplicationClass).logStarting(getApplicationLog());
void logStarting(Log applicationLog) {
Assert.notNull(applicationLog, "Log must not be null");
applicationLog.info(LogMessage.of(this::getStartingMessage));
applicationLog.debug(LogMessage.of(this::getRunningMessage));
}
private CharSequence getStartingMessage() {
StringBuilder message = new StringBuilder();
message.append("Starting ");
appendApplicationName(message);
appendVersion(message, this.sourceClass);
appendOn(message);
appendPid(message);
appendContext(message);
return message;
}
StartingMessage: info
2020-04-16 11:22:38.085 INFO 17884 --- [ main] c.e.factory.app.FactoryDemoApplication : Starting FactoryDemoApplication on Ccx with PID 17884 (E:\IDEA\ccxxx\factory-demo\target\classes started by cx521 in E:\IDEA\ccxxx)
RunningMessage: debug
2020-04-16 11:26:52.314 DEBUG 17884 --- [ main] c.e.factory.app.FactoryDemoApplication : Running with Spring Boot v2.2.2.RELEASE, Spring v5.2.2.RELEASE
打印当前环境:
protected void logStartupProfileInfo(ConfigurableApplicationContext context) {
Log log = getApplicationLog();
if (log.isInfoEnabled()) {
String[] activeProfiles = context.getEnvironment().getActiveProfiles();
if (ObjectUtils.isEmpty(activeProfiles)) {
String[] defaultProfiles = context.getEnvironment().getDefaultProfiles();
log.info("No active profile set, falling back to default profiles: "
+ StringUtils.arrayToCommaDelimitedString(defaultProfiles));
}
else {
log.info("The following profiles are active: "
+ StringUtils.arrayToCommaDelimitedString(activeProfiles));
}
}
}
2020-04-16 11:28:14.143 INFO 17884 --- [ main] c.e.factory.app.FactoryDemoApplication : No active profile set, falling back to default profiles: default
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory) beanFactory)
.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
if (this.lazyInitialization) {
context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
}
BeanDefinitionLoader(BeanDefinitionRegistry registry, Object... sources) {
Assert.notNull(registry, "Registry must not be null");
Assert.notEmpty(sources, "Sources must not be empty");
this.sources = sources;
this.annotatedReader = new AnnotatedBeanDefinitionReader(registry);
this.xmlReader = new XmlBeanDefinitionReader(registry);
if (isGroovyPresent()) {
this.groovyReader = new GroovyBeanDefinitionReader(registry);
}
this.scanner = new ClassPathBeanDefinitionScanner(registry);
this.scanner.addExcludeFilter(new ClassExcludeFilter(sources));
}
// sources为启动类
protected void load(ApplicationContext context, Object[] sources) {
if (logger.isDebugEnabled()) {
logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
}
BeanDefinitionLoader loader = createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources);
if (this.beanNameGenerator != null) {
loader.setBeanNameGenerator(this.beanNameGenerator);
}
if (this.resourceLoader != null) {
loader.setResourceLoader(this.resourceLoader);
}
if (this.environment != null) {
loader.setEnvironment(this.environment);
}
loader.load();
}
0 = {
CloudFoundryVcapEnvironmentPostProcessor@4378}
1 = {
ConfigFileApplicationListener@3859}
2 = {
AnsiOutputApplicationListener@3860}
3 = {
LoggingApplicationListener@3861}
4 = {
ClasspathLoggingApplicationListener@3862}
5 = {
BackgroundPreinitializer@3824}
6 = {
DelegatingApplicationListener@3831}
7 = {
ParentContextCloserApplicationListener@4379}
8 = {
ClearCachesApplicationListener@4380}
9 = {
FileEncodingApplicationListener@3863}
10 = {
LiquibaseServiceLocatorApplicationListener@4381}
public void contextLoaded(ConfigurableApplicationContext context) {
for (ApplicationListener<?> listener : this.application.getListeners()) {
if (listener instanceof ApplicationContextAware) {
((ApplicationContextAware) listener).setApplicationContext(context);
}
context.addApplicationListener(listener);
}
this.initialMulticaster.multicastEvent(new ApplicationPreparedEvent(this.application, this.args, context));
}
进行数据回调
0 = {
CloudFoundryVcapEnvironmentPostProcessor@3657}
1 = {
ConfigFileApplicationListener@3675}
2 = {
LoggingApplicationListener@3676}
3 = {
BackgroundPreinitializer@3365}
4 = {
DelegatingApplicationListener@3381}
spring的标准流程,spring启动
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 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);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// 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();
}
}
}
清空缓存,这里有2个回调,模板方法都是空实现
protected void prepareRefresh() {
// Switch to active.
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
if (logger.isDebugEnabled()) {
if (logger.isTraceEnabled()) {
logger.trace("Refreshing " + this);
}
else {
logger.debug("Refreshing " + getDisplayName());
}
}
// Initialize any placeholder property sources in the context environment.
initPropertySources();
// Validate that all properties marked as required are resolvable:
// see ConfigurablePropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties();
// Store pre-refresh ApplicationListeners...
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
// Reset local application listeners to pre-refresh state.
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<>();
}
earlyApplicationListeners列表
0 = {
RSocketPortInfoApplicationContextInitializer$Listener@3716}
1 = {
ServerPortInfoApplicationContextInitializer@3717}
2 = {
ConditionEvaluationReportLoggingListener$ConditionEvaluationReportListener@3718}
3 = {
CloudFoundryVcapEnvironmentPostProcessor@3719}
4 = {
ConfigFileApplicationListener@3720}
5 = {
AnsiOutputApplicationListener@3721}
6 = {
LoggingApplicationListener@3722}
7 = {
ClasspathLoggingApplicationListener@3723}
8 = {
BackgroundPreinitializer@3724}
9 = {
DelegatingApplicationListener@3725}
10 = {
ParentContextCloserApplicationListener@3726}
11 = {
ClearCachesApplicationListener@3727}
12 = {
FileEncodingApplicationListener@3728}
13 = {
LiquibaseServiceLocatorApplicationListener@3729}
调用GenericApplicationContext获取BeanFactory
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
return getBeanFactory();
}
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());
// BeanExpressionResolver接口的标准实现,Spring EL解析,ex: #{beanName}
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
//填充给定PropertyEditorRegistry(通常是org.springframe .bean)的PropertyEditorRegistry实现。
//用于在带有资源编辑器的org.springframework.context. context中创建bean的BeanWrapper。
//由org.springframework.context.support.AbstractApplicationContext使用
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// 配置工厂回调
// BeanPostProcessor实现供应ApplicationContext,环境,或StringValueResolver
//ApplicationContext EnvironmentAware bean实现,EmbeddedValueResolverAware, ResourceLoaderAware,
// ApplicationEventPublisherAware MessageSourceAware和/或ApplicationContextAware接口。
//实现的接口按照上面提到的顺序被满足。 应用程序上下文将自动将其注册到它们的底层bean工厂。应用程序不直接使用它。
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);
// 将系统Bean加入到容器中,我们可以在系统通过注入的方式获取
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// 将早期的后处理器注册为application监听器,用于检测内部bean。
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (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()));
}
// 注册环境变量相关Bean
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());
}
}
Spiring 将BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor区分开调用:
BeanDefinitionRegistryPostProcessor实现自BeanFactoryPostProcessor,因此需要2步:
1.void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
2.void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
单独BeanFactoryPostProcessor接口:
1.void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
0 = {
SharedMetadataReaderFactoryContextInitializer$CachingMetadataReaderFactoryPostProcessor@4139}
1 = {
ConfigurationWarningsApplicationContextInitializer$ConfigurationWarningsPostProcessor@4140}
2 = {
ConfigFileApplicationListener$PropertySourceOrderingPostProcessor@4141}
BeanDefinitionRegistryPostProcessor 实现自 BeanFactoryPostProcessor接口,调用前需要先调用BeanDefinitionRegistryPostProcessor 的postProcessBeanDefinitionRegistry接口,
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
currentRegistryProcessors保存从上下文中获取到实现PriorityOrdered接口的实例;
postProcessorNames保存的是beanName;
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
Set<String> processedBeans = new HashSet<>();
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// 注意这里类型过滤为 PriorityOrdered.class
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
// 排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
// 将容器中获取的processor添加到registryProcessors中
registryProcessors.addAll(currentRegistryProcessors);
// 循环调用新加的processor
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
// 清空临时列表
currentRegistryProcessors.clear();
循环调用新加的processor:
这里新加的是org.springframework.context.annotation.ConfigurationClassPostProcessor
private static void invokeBeanDefinitionRegistryPostProcessors(
Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanDefinitionRegistry(registry);
}
}
currentRegistryProcessors保存从上下文中获取到实现Ordered接口的实例;
postProcessorNames保存的是beanName;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// 注意这里类型过滤为 Ordered.class,且postProcessorName不存在,防止重复调用
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
// 排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
// 将容器中获取的processor添加到registryProcessors中
registryProcessors.addAll(currentRegistryProcessors);
// 循环调用新加的processor
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
// 清空临时列表
currentRegistryProcessors.clear();
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// postProcessorName不存在的,防止重复调用
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
// 排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
// 将容器中获取的processor添加到registryProcessors中
registryProcessors.addAll(currentRegistryProcessors);
// 循环调用新加的processor
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
// 清空临时列表
currentRegistryProcessors.clear();
调用postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
循环实现了BeanDefinitionRegistryPostProcessor接口的实例.
// 实现了BeanDefinitionRegistryPostProcessor的接口
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
// 只实现了BeanFactoryPostProcessor的接口
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
private static void invokeBeanFactoryPostProcessors(
Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
for (BeanFactoryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanFactory(beanFactory);
}
}
获取容器中只实现了BeanFactoryPostProcessors的处理器,注意和前边步骤BeanDefinitionRegistryPostProcessor区分开,前边是需要两步操作:
1.void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
2.void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
List priorityOrderedPostProcessors = new ArrayList<>();
List orderedPostProcessorNames = new ArrayList<>();
List nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
// 这里排除了已经处理过的processor
if (processedBeans.contains(ppName)) {
}
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);
}
}
// 首先调用实现了PriorityOrdered接口的
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// 然后实现了Ordered接口的
List orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// 调用无须的
List nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// 清空源信息
beanFactory.clearMetadataCache();
protected void initMessageSource() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
// Make MessageSource aware of parent MessageSource.
if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
if (hms.getParentMessageSource() == null) {
// Only set parent context as parent MessageSource if no parent MessageSource
// registered already.
hms.setParentMessageSource(getInternalParentMessageSource());
}
}
if (logger.isTraceEnabled()) {
logger.trace("Using MessageSource [" + this.messageSource + "]");
}
}
else {
// Use empty MessageSource to be able to accept getMessage calls.
// 默认实现
DelegatingMessageSource dms = new DelegatingMessageSource();
dms.setParentMessageSource(getInternalParentMessageSource());
this.messageSource = dms;
beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
if (logger.isTraceEnabled()) {
logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
}
}
}
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isTraceEnabled()) {
logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
else {
// 默认的广播实例
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
if (logger.isTraceEnabled()) {
logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
"[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
}
}
}
protected void onRefresh() {
// 调用的是GenericWebApplicationContext.onRefresh();
super.onRefresh();
try {
// 创建WebServer
createWebServer();
}
catch (Throwable ex) {
throw new ApplicationContextException("Unable to start web server", ex);
}
}
// 是GenericWebApplicationContext.onRefresh
protected void onRefresh() {
// 初始化主题
this.themeSource = UiApplicationContextUtils.initThemeSource(this);
}
调用ServletWebServerApplicationContext的createWebServer方法
private void createWebServer() {
// 启动时为null
WebServer webServer = this.webServer;
// 启动时为null
ServletContext servletContext = getServletContext();
if (webServer == null && servletContext == null) {
ServletWebServerFactory factory = getWebServerFactory();
this.webServer = factory.getWebServer(getSelfInitializer());
}
else if (servletContext != null) {
try {
getSelfInitializer().onStartup(servletContext);
}
catch (ServletException ex) {
throw new ApplicationContextException("Cannot initialize servlet context", ex);
}
}
initPropertySources();
}
protected ServletWebServerFactory getWebServerFactory() {
// Use bean names so that we don't consider the hierarchy
// 这里会获取到tomcatServletWebServerFactory
String[] beanNames = getBeanFactory().getBeanNamesForType(ServletWebServerFactory.class);
if (beanNames.length == 0) {
throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to missing "
+ "ServletWebServerFactory bean.");
}
if (beanNames.length > 1) {
throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to multiple "
+ "ServletWebServerFactory beans : " + StringUtils.arrayToCommaDelimitedString(beanNames));
}
return getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class);
}
TomcatServletWebServerFactory#getWebServer
public WebServer getWebServer(ServletContextInitializer... initializers) {
if (this.disableMBeanRegistry) {
// 默认禁用MBean注册
Registry.disableRegistry();
}
Tomcat tomcat = new Tomcat();
// 创建了一个临时目录,ex: C:\Users\cx521\AppData\Local\Temp\tomcat.5544330150298139628.8080
File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat");
// 设置Tomcat基本路径
tomcat.setBaseDir(baseDir.getAbsolutePath());
// 创建连接
Connector connector = new Connector(this.protocol);
// 启动失败时抛出异常
connector.setThrowOnFailure(true);
tomcat.getService().addConnector(connector);
// 自定义连接信息
customizeConnector(connector);
tomcat.setConnector(connector);
// 自动部署
tomcat.getHost().setAutoDeploy(false);
// 配置引擎
configureEngine(tomcat.getEngine());
for (Connector additionalConnector : this.additionalTomcatConnectors) {
tomcat.getService().addConnector(additionalConnector);
}
// 准备环境
prepareContext(tomcat.getHost(), initializers);
// 启动在这里进行.new TomcatWebServer(tomcat, getPort() >= 0);
return getTomcatWebServer(tomcat);
}
// 临时目录名为tomcat.端口形式
protected final File createTempDir(String prefix) {
File tempDir = File.createTempFile(prefix + ".", "." + getPort());
tempDir.delete();
tempDir.mkdir();
tempDir.deleteOnExit();
return tempDir;
}
// 自定义连接
protected void customizeConnector(Connector connector) {
// 设置端口
int port = Math.max(getPort(), 0);
connector.setPort(port);
if (StringUtils.hasText(this.getServerHeader())) {
connector.setAttribute("server", this.getServerHeader());
}
if (connector.getProtocolHandler() instanceof AbstractProtocol) {
// 自定义协议
customizeProtocol((AbstractProtocol<?>) connector.getProtocolHandler());
}
// 自定义协议处理器,默认为Http11NioProtocol
invokeProtocolHandlerCustomizers(connector.getProtocolHandler());
if (getUriEncoding() != null) {
// 设置编码为UTF-8
connector.setURIEncoding(getUriEncoding().name());
}
// 延迟绑定
connector.setProperty("bindOnInit", "false");
// 设置ssl,https相关
if (getSsl() != null && getSsl().isEnabled()) {
customizeSsl(connector);
}
// 设置压缩,最小响应包大小为2048B
TomcatConnectorCustomizer compression = new CompressionConnectorCustomizer(getCompression());
compression.customize(connector);
// 添加 其他的自定义属性,比如TomcatWebServerFactoryCustomizer#customize中定义的
for (TomcatConnectorCustomizer customizer : this.tomcatConnectorCustomizers) {
customizer.customize(connector);
}
}
// 准备上下文
protected void prepareContext(Host host, ServletContextInitializer[] initializers) {
File documentRoot = getValidDocumentRoot();
TomcatEmbeddedContext context = new TomcatEmbeddedContext();
if (documentRoot != null) {
context.setResources(new LoaderHidingResourceRoot(context));
}
// 设置名称
context.setName(getContextPath());
// 名字
context.setDisplayName(getDisplayName());
// 路径
context.setPath(getContextPath());
// 创建文档路径, ex: C:\Users\cx521\AppData\Local\Temp\tomcat-docbase.4781687470030327872.8080
File docBase = (documentRoot != null) ? documentRoot : createTempDir("tomcat-docbase");
context.setDocBase(docBase.getAbsolutePath());
// 设置监听器 上下文中的start()方法将把“configured”设置为false,并期望侦听器将其设置回true
context.addLifecycleListener(new FixContextListener());
// 类加载器
context.setParentClassLoader((this.resourceLoader != null) ? this.resourceLoader.getClassLoader()
: ClassUtils.getDefaultClassLoader());
// 重置默认的映射
resetDefaultLocaleMapping(context);
// 添加本地映射,HttpEncodingAutoConfiguration会去设置
addLocaleMappings(context);
context.setUseRelativeRedirects(false);
try {
context.setCreateUploadTargets(true);
}
catch (NoSuchMethodError ex) {
// Tomcat is < 8.5.39. Continue.
}
// 配置跳过指定jar过滤器表达式
configureTldSkipPatterns(context);
WebappLoader loader = new WebappLoader(context.getParentClassLoader());
loader.setLoaderClass(TomcatEmbeddedWebappClassLoader.class.getName());
loader.setDelegate(true);
context.setLoader(loader);
// 添加默认的Servlet
if (isRegisterDefaultServlet()) {
addDefaultServlet(context);
}
// 添加JspServlet
if (shouldRegisterJspServlet()) {
addJspServlet(context);
addJasperInitializer(context);
}
context.addLifecycleListener(new StaticResourceConfigurer(context));
ServletContextInitializer[] initializersToUse = mergeInitializers(initializers);
host.addChild(context);
// 配置上下文
configureContext(context, initializersToUse);
postProcessContext(context);
}
protected void configureContext(Context context, ServletContextInitializer[] initializers) {
TomcatStarter starter = new TomcatStarter(initializers);
if (context instanceof TomcatEmbeddedContext) {
// 嵌入式上下文环境
TomcatEmbeddedContext embeddedContext = (TomcatEmbeddedContext) context;
embeddedContext.setStarter(starter);
embeddedContext.setFailCtxIfServletStartFails(true);
}
context.addServletContainerInitializer(starter, NO_CLASSES);
for (LifecycleListener lifecycleListener : this.contextLifecycleListeners) {
context.addLifecycleListener(lifecycleListener);
}
for (Valve valve : this.contextValves) {
context.getPipeline().addValve(valve);
}
// 设置异常页面
for (ErrorPage errorPage : getErrorPages()) {
org.apache.tomcat.util.descriptor.web.ErrorPage tomcatErrorPage = new org.apache.tomcat.util.descriptor.web.ErrorPage();
tomcatErrorPage.setLocation(errorPage.getPath());
tomcatErrorPage.setErrorCode(errorPage.getStatusCode());
tomcatErrorPage.setExceptionType(errorPage.getExceptionName());
context.addErrorPage(tomcatErrorPage);
}
// 设置mime映射
for (MimeMappings.Mapping mapping : getMimeMappings()) {
context.addMimeMapping(mapping.getExtension(), mapping.getMimeType());
}
configureSession(context);
new DisableReferenceClearingContextCustomizer().customize(context);
for (TomcatContextCustomizer customizer : this.tomcatContextCustomizers) {
customizer.customize(context);
}
}
Http11NioProtocol的属性:
compressionConfig = {CompressionConfig@13417}
compressionLevel = 0
noCompressionUserAgents = null
compressibleMimeType = "text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/json,application/xml"
compressibleMimeTypes = null
compressionMinSize = 2048
useKeepAliveResponseHeader = true
relaxedPathChars = null
relaxedQueryChars = null
allowHostHeaderMismatch = false
rejectIllegalHeaderName = true
maxSavePostSize = 4096
maxHttpHeaderSize = 8192
connectionUploadTimeout = 300000
disableUploadTimeout = true
restrictedUserAgents = null
server = null
serverRemoveAppProvidedValues = false
maxTrailerSize = 8192
maxExtensionSize = 8192
maxSwallowSize = 2097152
secure = false
allowedTrailerHeaders = {Collections$SetFromMap@13418} size = 0
upgradeProtocols = {ArrayList@13419} size = 0
httpUpgradeProtocols = {HashMap@13420} size = 0
negotiatedProtocols = {HashMap@13421} size = 0
defaultSSLHostConfig = null
rgOname = null
nameIndex = 1
endpoint = {NioEndpoint@13422}
handler = {AbstractProtocol$ConnectionHandler@13423}
proto = {Http11NioProtocol@13347}
global = {RequestGroupInfo@13437} "BaseModelMbean[null]"
registerCount = {AtomicLong@13438} "0"
recycledProcessors = {AbstractProtocol$RecycledProcessors@13439}
waitingProcessors = {Collections$SetFromMap@13424} size = 0
timeoutFuture = null
monitorFuture = null
adapter = null
processorCache = 200
clientCertProvider = null
maxHeaderCount = 100
domain = null
oname = null
mserver = null
自定义的属性TomcatWebServerFactoryCustomizer#customize
@Override
public void customize(ConfigurableTomcatWebServerFactory factory) {
ServerProperties properties = this.serverProperties;
ServerProperties.Tomcat tomcatProperties = properties.getTomcat();
PropertyMapper propertyMapper = PropertyMapper.get();
propertyMapper.from(tomcatProperties::getBasedir).whenNonNull().to(factory::setBaseDirectory);
propertyMapper.from(tomcatProperties::getBackgroundProcessorDelay).whenNonNull().as(Duration::getSeconds)
.as(Long::intValue).to(factory::setBackgroundProcessorDelay);
customizeRemoteIpValve(factory);
propertyMapper.from(tomcatProperties::getMaxThreads).when(this::isPositive)
.to((maxThreads) -> customizeMaxThreads(factory, tomcatProperties.getMaxThreads()));
propertyMapper.from(tomcatProperties::getMinSpareThreads).when(this::isPositive)
.to((minSpareThreads) -> customizeMinThreads(factory, minSpareThreads));
propertyMapper.from(this::determineMaxHttpHeaderSize).whenNonNull().asInt(DataSize::toBytes)
.when(this::isPositive)
.to((maxHttpHeaderSize) -> customizeMaxHttpHeaderSize(factory, maxHttpHeaderSize));
propertyMapper.from(tomcatProperties::getMaxSwallowSize).whenNonNull().asInt(DataSize::toBytes)
.to((maxSwallowSize) -> customizeMaxSwallowSize(factory, maxSwallowSize));
propertyMapper.from(tomcatProperties::getMaxHttpPostSize).asInt(DataSize::toBytes)
.when((maxHttpPostSize) -> maxHttpPostSize != 0)
.to((maxHttpPostSize) -> customizeMaxHttpPostSize(factory, maxHttpPostSize));
propertyMapper.from(tomcatProperties::getAccesslog).when(ServerProperties.Tomcat.Accesslog::isEnabled)
.to((enabled) -> customizeAccessLog(factory));
propertyMapper.from(tomcatProperties::getUriEncoding).whenNonNull().to(factory::setUriEncoding);
propertyMapper.from(properties::getConnectionTimeout).whenNonNull()
.to((connectionTimeout) -> customizeConnectionTimeout(factory, connectionTimeout));
propertyMapper.from(tomcatProperties::getMaxConnections).when(this::isPositive)
.to((maxConnections) -> customizeMaxConnections(factory, maxConnections));
propertyMapper.from(tomcatProperties::getAcceptCount).when(this::isPositive)
.to((acceptCount) -> customizeAcceptCount(factory, acceptCount));
customizeStaticResources(factory);
customizeErrorReportValve(properties.getError(), factory);
}
跳过指定jar
0 = "ant-*.jar"
1 = "aspectj*.jar"
2 = "commons-beanutils*.jar"
3 = "commons-codec*.jar"
4 = "commons-collections*.jar"
5 = "commons-dbcp*.jar"
6 = "commons-digester*.jar"
7 = "commons-fileupload*.jar"
8 = "commons-httpclient*.jar"
9 = "commons-io*.jar"
10 = "commons-lang*.jar"
11 = "commons-logging*.jar"
12 = "commons-math*.jar"
13 = "commons-pool*.jar"
14 = "geronimo-spec-jaxrpc*.jar"
15 = "h2*.jar"
16 = "hamcrest*.jar"
17 = "hibernate*.jar"
18 = "jaxb-runtime-*.jar"
19 = "jmx*.jar"
20 = "jmx-tools-*.jar"
21 = "jta*.jar"
22 = "junit-*.jar"
23 = "httpclient*.jar"
24 = "log4j-*.jar"
25 = "mail*.jar"
26 = "org.hamcrest*.jar"
27 = "slf4j*.jar"
28 = "tomcat-embed-core-*.jar"
29 = "tomcat-embed-logging-*.jar"
30 = "tomcat-jdbc-*.jar"
31 = "tomcat-juli-*.jar"
32 = "tools.jar"
33 = "wsdl4j*.jar"
34 = "xercesImpl-*.jar"
35 = "xmlParserAPIs-*.jar"
36 = "xml-apis-*.jar"
37 = "antlr-*.jar"
38 = "aopalliance-*.jar"
39 = "aspectjrt-*.jar"
40 = "aspectjweaver-*.jar"
41 = "classmate-*.jar"
42 = "dom4j-*.jar"
43 = "ecj-*.jar"
44 = "ehcache-core-*.jar"
45 = "hibernate-core-*.jar"
46 = "hibernate-commons-annotations-*.jar"
47 = "hibernate-entitymanager-*.jar"
48 = "hibernate-jpa-2.1-api-*.jar"
49 = "hibernate-validator-*.jar"
50 = "hsqldb-*.jar"
51 = "jackson-annotations-*.jar"
52 = "jackson-core-*.jar"
53 = "jackson-databind-*.jar"
54 = "jandex-*.jar"
55 = "javassist-*.jar"
56 = "jboss-logging-*.jar"
57 = "jboss-transaction-api_*.jar"
58 = "jcl-over-slf4j-*.jar"
59 = "jdom-*.jar"
60 = "jul-to-slf4j-*.jar"
61 = "log4j-over-slf4j-*.jar"
62 = "logback-classic-*.jar"
63 = "logback-core-*.jar"
64 = "rome-*.jar"
65 = "slf4j-api-*.jar"
66 = "spring-aop-*.jar"
67 = "spring-aspects-*.jar"
68 = "spring-beans-*.jar"
69 = "spring-boot-*.jar"
70 = "spring-core-*.jar"
71 = "spring-context-*.jar"
72 = "spring-data-*.jar"
73 = "spring-expression-*.jar"
74 = "spring-jdbc-*.jar,"
75 = "spring-orm-*.jar"
76 = "spring-oxm-*.jar"
77 = "spring-tx-*.jar"
78 = "snakeyaml-*.jar"
79 = "tomcat-embed-el-*.jar"
80 = "validation-api-*.jar"
private void initialize() throws WebServerException {
logger.info("Tomcat initialized with port(s): " + getPortsDescription(false));
synchronized (this.monitor) {
try {
addInstanceIdToEngineName();
// StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]
Context context = findContext();
context.addLifecycleListener((event) -> {
if (context.equals(event.getSource()) && Lifecycle.START_EVENT.equals(event.getType())) {
// Remove service connectors so that protocol binding doesn't
// happen when the service is started.
removeServiceConnectors();
}
});
// 启动服务器以触发初始化监听器
this.tomcat.start();
// We can re-throw failure exception directly in the main thread
rethrowDeferredStartupExceptions();
try {
ContextBindings.bindClassLoader(context, context.getNamingToken(), getClass().getClassLoader());
}
catch (NamingException ex) {
// Naming is not enabled. Continue
}
// Unlike Jetty, all Tomcat threads are daemon threads. We create a
// blocking non-daemon to stop immediate shutdown
startDaemonAwaitThread();
}
catch (Exception ex) {
stopSilently();
destroySilently();
throw new WebServerException("Unable to start embedded Tomcat", ex);
}
}
}
@Override
public void initPropertySources(@Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) {
WebApplicationContextUtils.initServletPropertySources(getPropertySources(), servletContext, servletConfig);
}
protected void registerListeners() {
// 首先注册静态指定的侦听器。
for (ApplicationListener<?> listener : getApplicationListeners()) {
// 工厂自带的监听器需要检查下是否被代理,有的话需要去除
getApplicationEventMulticaster().addApplicationListener(listener);
}
}
public void addApplicationListener(ApplicationListener<?> listener) {
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();
}
}
工厂中自带的ApplicationListener
0 = {
RSocketPortInfoApplicationContextInitializer$Listener@29269}
1 = {
ServerPortInfoApplicationContextInitializer@29398}
2 = {
ConditionEvaluationReportLoggingListener$ConditionEvaluationReportListener@29399}
3 = {
CloudFoundryVcapEnvironmentPostProcessor@29400}
4 = {
ConfigFileApplicationListener@29401}
5 = {
AnsiOutputApplicationListener@29402}
6 = {
LoggingApplicationListener@29403}
7 = {
ClasspathLoggingApplicationListener@29404}
8 = {
BackgroundPreinitializer@29405}
9 = {
DelegatingApplicationListener@29406}
10 = {
ParentContextCloserApplicationListener@29407}
11 = {
ClearCachesApplicationListener@29408}
12 = {
FileEncodingApplicationListener@29409}
13 = {
LiquibaseServiceLocatorApplicationListener@29410}
14 = {
SharedMetadataReaderFactoryContextInitializer$SharedMetadataReaderFactoryBean@12087}
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
// 直接添加
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
public void addApplicationListenerBean(String listenerBeanName) {
synchronized (this.retrievalMutex) {
this.defaultRetriever.applicationListenerBeans.add(listenerBeanName);
this.retrieverCache.clear();
}
}
获取早期的应用事件
Set earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 为此上下文初始化转换服务。
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// Register a default embedded value resolver if no bean post-processor
// (such as a PropertyPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);
// 设置冻结,允许缓存所有的bean定义元数据。
beanFactory.freezeConfiguration();
// 实例化所有非延迟加载的单例对象
beanFactory.preInstantiateSingletons();
}
ServletWebServerApplicationContext#finishRefresh
@Override
protected void finishRefresh() {
super.finishRefresh();
WebServer webServer = startWebServer();
if (webServer != null) {
publishEvent(new ServletWebServerInitializedEvent(webServer, this));
}
}
protected void finishRefresh() {
// 清除上下文级的资源缓存(比如扫描的ASM元数据)。
clearResourceCaches();
// 为此上下文初始化生命周期处理器。DefaultLifecycleProcessor
initLifecycleProcessor();
// 生命周期处理器开始运行.
getLifecycleProcessor().onRefresh();
// 推送PayloadApplicationEvent事件
publishEvent(new ContextRefreshedEvent(this));
//注册MBean.
LiveBeansView.registerApplicationContext(this);
}
0 = {
SpringApplicationAdminMXBeanRegistrar@30505}
1 = {
DelegatingApplicationListener@29406}
2 = {
ServerPortInfoApplicationContextInitializer@29398}
protected void resetCommonCaches() {
ReflectionUtils.clearCache();
AnnotationUtils.clearCache();
ResolvableType.clearCache();
CachedIntrospectionResults.clearClassLoader(getClassLoader());
}
在虚拟中注册个勾子,以供关闭时能调用生命周期方法
public void registerShutdownHook() {
if (this.shutdownHook == null) {
// No shutdown hook registered yet.
this.shutdownHook = new Thread(SHUTDOWN_HOOK_THREAD_NAME) {
@Override
public void run() {
synchronized (startupShutdownMonitor) {
doClose();
}
}
};
Runtime.getRuntime().addShutdownHook(this.shutdownHook);
}
}
protected void doClose() {
// Check whether an actual close attempt is necessary...
if (this.active.get() && this.closed.compareAndSet(false, true)) {
if (logger.isDebugEnabled()) {
logger.debug("Closing " + this);
}
LiveBeansView.unregisterApplicationContext(this);
try {
// Publish shutdown event.
publishEvent(new ContextClosedEvent(this));
}
catch (Throwable ex) {
logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
}
// Stop all Lifecycle beans, to avoid delays during individual destruction.
if (this.lifecycleProcessor != null) {
try {
this.lifecycleProcessor.onClose();
}
catch (Throwable ex) {
logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
}
}
// Destroy all cached singletons in the context's BeanFactory.
destroyBeans();
// Close the state of this context itself.
closeBeanFactory();
// Let subclasses do some final clean-up if they wish...
onClose();
// Reset local application listeners to pre-refresh state.
if (this.earlyApplicationListeners != null) {
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// Switch to inactive.
this.active.set(false);
}
}
不做任何实现
protected void afterRefresh(ConfigurableApplicationContext context, ApplicationArguments args) {
}
2020-04-16 19:34:40.634 INFO 9204 --- [ main] c.e.factory.app.FactoryDemoApplication : Started FactoryDemoApplication in 211.377 seconds (JVM running for 212.963)
0 = {BackgroundPreinitializer@29405}
1 = {DelegatingApplicationListener@29406}
private void callRunners(ApplicationContext context, ApplicationArguments args) {
List
0 = {SpringApplicationAdminMXBeanRegistrar@6596}
1 = {BackgroundPreinitializer@6920}
2 = {DelegatingApplicationListener@6921}